1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/accessors.h"
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/api.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/once.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/utils/random-number-generator.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bootstrapper.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compilation-cache.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/conversions.h"
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/cpu-profiler.h"
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/debug.h"
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/deoptimizer.h"
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/global-handles.h"
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/heap/gc-idle-time-handler.h"
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/heap/incremental-marking.h"
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/heap/mark-compact.h"
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/heap/objects-visiting-inl.h"
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/heap/objects-visiting.h"
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/heap/store-buffer.h"
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/heap-profiler.h"
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/isolate-inl.h"
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/natives.h"
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/runtime-profiler.h"
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/scopeinfo.h"
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/snapshot.h"
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/utils.h"
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8threads.h"
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/vm-state-inl.h"
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/regexp-macro-assembler.h"          // NOLINT
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/regexp-macro-assembler-arm.h"  // NOLINT
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_MIPS && !V8_INTERPRETED_REGEXP
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/regexp-macro-assembler.h"            // NOLINT
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/mips/regexp-macro-assembler-mips.h"  // NOLINT
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_MIPS64 && !V8_INTERPRETED_REGEXP
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/regexp-macro-assembler.h"
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/mips64/regexp-macro-assembler-mips64.h"
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeap::Heap()
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : amount_of_external_allocated_memory_(0),
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      amount_of_external_allocated_memory_at_last_global_gc_(0),
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate_(NULL),
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      code_range_size_(0),
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // semispace_size_ should be a power of 2 and old_generation_size_ should
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // be a multiple of Page::kPageSize.
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reserved_semispace_size_(8 * (kPointerSize / 4) * MB),
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      max_semi_space_size_(8 * (kPointerSize / 4) * MB),
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      initial_semispace_size_(Page::kPageSize),
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      max_old_generation_size_(700ul * (kPointerSize / 4) * MB),
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      max_executable_size_(256ul * (kPointerSize / 4) * MB),
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Variables set based on semispace_size_ and old_generation_size_ in
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // ConfigureHeap.
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Will be 4 * reserved_semispace_size_ to ensure that young
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // generation can be aligned to its size.
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      maximum_committed_(0),
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      survived_since_last_expansion_(0),
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sweep_generation_(0),
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      always_allocate_scope_depth_(0),
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      contexts_disposed_(0),
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      global_ic_age_(0),
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      flush_monomorphic_ics_(false),
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      scan_on_scavenge_pages_(0),
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new_space_(this),
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      old_pointer_space_(NULL),
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      old_data_space_(NULL),
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      code_space_(NULL),
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      map_space_(NULL),
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cell_space_(NULL),
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      property_cell_space_(NULL),
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      lo_space_(NULL),
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      gc_state_(NOT_IN_GC),
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      gc_post_processing_depth_(0),
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      allocations_count_(0),
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      raw_allocations_hash_(0),
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      dump_allocations_hash_countdown_(FLAG_dump_allocations_digest_at_alloc),
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ms_count_(0),
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      gc_count_(0),
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      remembered_unmapped_pages_index_(0),
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      unflattened_strings_length_(0),
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      allocation_timeout_(0),
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // DEBUG
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      old_generation_allocation_limit_(kMinimumOldGenerationAllocationLimit),
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      old_gen_exhausted_(false),
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      inline_allocation_disabled_(false),
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      store_buffer_rebuilder_(store_buffer()),
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      hidden_string_(NULL),
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      gc_safe_size_of_old_object_(NULL),
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      total_regexp_code_generated_(0),
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      tracer_(this),
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      high_survival_rate_period_length_(0),
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      promoted_objects_size_(0),
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      promotion_rate_(0),
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      semi_space_copied_object_size_(0),
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      semi_space_copied_rate_(0),
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      nodes_died_in_new_space_(0),
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      nodes_copied_in_new_space_(0),
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      nodes_promoted_(0),
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      maximum_size_scavenges_(0),
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      max_gc_pause_(0.0),
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      total_gc_time_ms_(0.0),
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      max_alive_after_gc_(0),
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      min_in_mutator_(kMaxInt),
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      marking_time_(0.0),
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      sweeping_time_(0.0),
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mark_compact_collector_(this),
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      store_buffer_(this),
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      marking_(this),
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      incremental_marking_(this),
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      gc_count_at_last_idle_gc_(0),
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      full_codegen_bytes_generated_(0),
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      crankshaft_codegen_bytes_generated_(0),
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      gcs_since_last_deopt_(0),
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      no_weak_object_verification_scope_depth_(0),
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      allocation_sites_scratchpad_length_(0),
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      promotion_queue_(this),
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      configured_(false),
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      external_string_table_(this),
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      chunks_queued_for_free_(NULL),
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      gc_callbacks_depth_(0) {
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Allow build-time customization of the max semispace size. Building
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// V8 with snapshots and a non-default max semispace size is much
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// easier if you can define it as part of the build environment.
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(V8_MAX_SEMISPACE_SIZE)
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  max_semi_space_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE;
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Ensure old_generation_size_ is a multiple of kPageSize.
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(MB >= Page::kPageSize);
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  memset(roots_, 0, sizeof(roots_[0]) * kRootListLength);
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_native_contexts_list(NULL);
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_array_buffers_list(Smi::FromInt(0));
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_allocation_sites_list(Smi::FromInt(0));
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_encountered_weak_collections(Smi::FromInt(0));
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Put a dummy entry in the remembered pages so we can find the list the
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // minidump even if there are no real unmapped pages.
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RememberUnmappedPage(NULL, false);
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearObjectStats(true);
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochintptr_t Heap::Capacity() {
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!HasBeenSetUp()) return 0;
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return new_space_.Capacity() + old_pointer_space_->Capacity() +
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         old_data_space_->Capacity() + code_space_->Capacity() +
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         map_space_->Capacity() + cell_space_->Capacity() +
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         property_cell_space_->Capacity();
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochintptr_t Heap::CommittedMemory() {
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!HasBeenSetUp()) return 0;
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return new_space_.CommittedMemory() + old_pointer_space_->CommittedMemory() +
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         old_data_space_->CommittedMemory() + code_space_->CommittedMemory() +
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         map_space_->CommittedMemory() + cell_space_->CommittedMemory() +
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         property_cell_space_->CommittedMemory() + lo_space_->Size();
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochsize_t Heap::CommittedPhysicalMemory() {
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!HasBeenSetUp()) return 0;
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return new_space_.CommittedPhysicalMemory() +
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         old_pointer_space_->CommittedPhysicalMemory() +
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         old_data_space_->CommittedPhysicalMemory() +
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         code_space_->CommittedPhysicalMemory() +
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         map_space_->CommittedPhysicalMemory() +
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         cell_space_->CommittedPhysicalMemory() +
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         property_cell_space_->CommittedPhysicalMemory() +
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         lo_space_->CommittedPhysicalMemory();
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochintptr_t Heap::CommittedMemoryExecutable() {
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!HasBeenSetUp()) return 0;
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return isolate()->memory_allocator()->SizeExecutable();
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::UpdateMaximumCommitted() {
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!HasBeenSetUp()) return;
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t current_committed_memory = CommittedMemory();
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (current_committed_memory > maximum_committed_) {
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    maximum_committed_ = current_committed_memory;
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochintptr_t Heap::Available() {
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!HasBeenSetUp()) return 0;
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return new_space_.Available() + old_pointer_space_->Available() +
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         old_data_space_->Available() + code_space_->Available() +
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         map_space_->Available() + cell_space_->Available() +
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         property_cell_space_->Available();
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::HasBeenSetUp() {
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return old_pointer_space_ != NULL && old_data_space_ != NULL &&
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         code_space_ != NULL && map_space_ != NULL && cell_space_ != NULL &&
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         property_cell_space_ != NULL && lo_space_ != NULL;
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint Heap::GcSafeSizeOfOldObject(HeapObject* object) {
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IntrusiveMarking::IsMarked(object)) {
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return IntrusiveMarking::SizeOfMarkedObject(object);
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return object->SizeFromMap(object->map());
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochGarbageCollector Heap::SelectGarbageCollector(AllocationSpace space,
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              const char** reason) {
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Is global GC requested?
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (space != NEW_SPACE) {
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->gc_compactor_caused_by_request()->Increment();
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *reason = "GC in old space requested";
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return MARK_COMPACTOR;
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_gc_global || (FLAG_stress_compaction && (gc_count_ & 1) != 0)) {
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *reason = "GC in old space forced by flags";
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return MARK_COMPACTOR;
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Is enough data promoted to justify a global GC?
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (OldGenerationAllocationLimitReached()) {
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->gc_compactor_caused_by_promoted_data()->Increment();
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *reason = "promotion limit reached";
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return MARK_COMPACTOR;
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Have allocation in OLD and LO failed?
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (old_gen_exhausted_) {
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ->gc_compactor_caused_by_oldspace_exhaustion()
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ->Increment();
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *reason = "old generations exhausted";
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return MARK_COMPACTOR;
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Is there enough space left in OLD to guarantee that a scavenge can
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // succeed?
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Note that MemoryAllocator->MaxAvailable() undercounts the memory available
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for object promotion. It counts only the bytes that the memory
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // allocator has not yet allocated from the OS and assigned to any space,
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // and does not count available bytes already in the old space or code
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // space.  Undercounting is safe---we may get an unrequested full GC when
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // a scavenge would have succeeded.
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate_->memory_allocator()->MaxAvailable() <= new_space_.Size()) {
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ->gc_compactor_caused_by_oldspace_exhaustion()
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ->Increment();
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *reason = "scavenge might not succeed";
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return MARK_COMPACTOR;
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Default
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *reason = NULL;
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return SCAVENGER;
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(1238405): Combine the infrastructure for --heap-stats and
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// --log-gc to avoid the complicated preprocessor and flag testing.
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ReportStatisticsBeforeGC() {
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Heap::ReportHeapStatistics will also log NewSpace statistics when
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// compiled --log-gc is set.  The following logic is used to avoid
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// double logging.
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_heap_stats || FLAG_log_gc) new_space_.CollectStatistics();
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_heap_stats) {
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ReportHeapStatistics("Before GC");
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (FLAG_log_gc) {
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    new_space_.ReportStatistics();
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_heap_stats || FLAG_log_gc) new_space_.ClearHistograms();
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_log_gc) {
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    new_space_.CollectStatistics();
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    new_space_.ReportStatistics();
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    new_space_.ClearHistograms();
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // DEBUG
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::PrintShortHeapStatistics() {
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_trace_gc_verbose) return;
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintPID("Memory allocator,   used: %6" V8_PTR_PREFIX
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", available: %6" V8_PTR_PREFIX "d KB\n",
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           isolate_->memory_allocator()->Size() / KB,
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           isolate_->memory_allocator()->Available() / KB);
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintPID("New space,          used: %6" V8_PTR_PREFIX
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", available: %6" V8_PTR_PREFIX
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", committed: %6" V8_PTR_PREFIX "d KB\n",
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           new_space_.Size() / KB, new_space_.Available() / KB,
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           new_space_.CommittedMemory() / KB);
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintPID("Old pointers,       used: %6" V8_PTR_PREFIX
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", available: %6" V8_PTR_PREFIX
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", committed: %6" V8_PTR_PREFIX "d KB\n",
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           old_pointer_space_->SizeOfObjects() / KB,
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           old_pointer_space_->Available() / KB,
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           old_pointer_space_->CommittedMemory() / KB);
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintPID("Old data space,     used: %6" V8_PTR_PREFIX
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", available: %6" V8_PTR_PREFIX
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", committed: %6" V8_PTR_PREFIX "d KB\n",
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           old_data_space_->SizeOfObjects() / KB,
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           old_data_space_->Available() / KB,
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           old_data_space_->CommittedMemory() / KB);
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintPID("Code space,         used: %6" V8_PTR_PREFIX
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", available: %6" V8_PTR_PREFIX
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", committed: %6" V8_PTR_PREFIX "d KB\n",
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           code_space_->SizeOfObjects() / KB, code_space_->Available() / KB,
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           code_space_->CommittedMemory() / KB);
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintPID("Map space,          used: %6" V8_PTR_PREFIX
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", available: %6" V8_PTR_PREFIX
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", committed: %6" V8_PTR_PREFIX "d KB\n",
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           map_space_->SizeOfObjects() / KB, map_space_->Available() / KB,
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           map_space_->CommittedMemory() / KB);
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintPID("Cell space,         used: %6" V8_PTR_PREFIX
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", available: %6" V8_PTR_PREFIX
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", committed: %6" V8_PTR_PREFIX "d KB\n",
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           cell_space_->SizeOfObjects() / KB, cell_space_->Available() / KB,
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           cell_space_->CommittedMemory() / KB);
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintPID("PropertyCell space, used: %6" V8_PTR_PREFIX
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", available: %6" V8_PTR_PREFIX
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", committed: %6" V8_PTR_PREFIX "d KB\n",
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           property_cell_space_->SizeOfObjects() / KB,
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           property_cell_space_->Available() / KB,
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           property_cell_space_->CommittedMemory() / KB);
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintPID("Large object space, used: %6" V8_PTR_PREFIX
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", available: %6" V8_PTR_PREFIX
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", committed: %6" V8_PTR_PREFIX "d KB\n",
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           lo_space_->SizeOfObjects() / KB, lo_space_->Available() / KB,
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           lo_space_->CommittedMemory() / KB);
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintPID("All spaces,         used: %6" V8_PTR_PREFIX
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", available: %6" V8_PTR_PREFIX
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           "d KB"
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ", committed: %6" V8_PTR_PREFIX "d KB\n",
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           this->SizeOfObjects() / KB, this->Available() / KB,
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           this->CommittedMemory() / KB);
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintPID("External memory reported: %6" V8_PTR_PREFIX "d KB\n",
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           static_cast<intptr_t>(amount_of_external_allocated_memory_ / KB));
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintPID("Total time spent in GC  : %.1f ms\n", total_gc_time_ms_);
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(1238405): Combine the infrastructure for --heap-stats and
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// --log-gc to avoid the complicated preprocessor and flag testing.
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ReportStatisticsAfterGC() {
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Similar to the before GC, we use some complicated logic to ensure that
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// NewSpace statistics are logged exactly once when --log-gc is turned on.
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(DEBUG)
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_heap_stats) {
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    new_space_.CollectStatistics();
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ReportHeapStatistics("After GC");
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (FLAG_log_gc) {
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    new_space_.ReportStatistics();
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_log_gc) new_space_.ReportStatistics();
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // DEBUG
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::GarbageCollectionPrologue() {
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllowHeapAllocation for_the_first_part_of_prologue;
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ClearJSFunctionResultCaches();
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    gc_count_++;
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    unflattened_strings_length_ = 0;
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_flush_code && FLAG_flush_code_incrementally) {
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mark_compact_collector()->EnableCodeFlushing(true);
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_verify_heap) {
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Verify();
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Reset GC statistics.
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  promoted_objects_size_ = 0;
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  semi_space_copied_object_size_ = 0;
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  nodes_died_in_new_space_ = 0;
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  nodes_copied_in_new_space_ = 0;
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  nodes_promoted_ = 0;
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateMaximumCommitted();
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AllowHeapAllocation::IsAllowed() && gc_state_ == NOT_IN_GC);
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_gc_verbose) Print();
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ReportStatisticsBeforeGC();
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // DEBUG
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  store_buffer()->GCPrologue();
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate()->concurrent_osr_enabled()) {
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate()->optimizing_compiler_thread()->AgeBufferedOsrJobs();
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (new_space_.IsAtMaximumCapacity()) {
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    maximum_size_scavenges_++;
453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    maximum_size_scavenges_ = 0;
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckNewSpaceExpansionCriteria();
457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochintptr_t Heap::SizeOfObjects() {
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t total = 0;
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllSpaces spaces(this);
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    total += space->SizeOfObjects();
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return total;
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ClearAllICsByKind(Code::Kind kind) {
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObjectIterator it(code_space());
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (Object* object = it.Next(); object != NULL; object = it.Next()) {
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Code* code = Code::cast(object);
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Code::Kind current_kind = code->kind();
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (current_kind == Code::FUNCTION ||
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        current_kind == Code::OPTIMIZED_FUNCTION) {
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      code->ClearInlineCaches(kind);
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::RepairFreeListsAfterBoot() {
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PagedSpaces spaces(this);
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (PagedSpace* space = spaces.next(); space != NULL;
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       space = spaces.next()) {
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    space->RepairFreeListsAfterBoot();
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ProcessPretenuringFeedback() {
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_allocation_site_pretenuring) {
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int tenure_decisions = 0;
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int dont_tenure_decisions = 0;
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int allocation_mementos_found = 0;
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int allocation_sites = 0;
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int active_allocation_sites = 0;
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If the scratchpad overflowed, we have to iterate over the allocation
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // sites list.
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // TODO(hpayer): We iterate over the whole list of allocation sites when
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // we grew to the maximum semi-space size to deopt maybe tenured
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // allocation sites. We could hold the maybe tenured allocation sites
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // in a seperate data structure if this is a performance problem.
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool deopt_maybe_tenured = DeoptMaybeTenuredAllocationSites();
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool use_scratchpad =
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        allocation_sites_scratchpad_length_ < kAllocationSiteScratchpadSize &&
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        !deopt_maybe_tenured;
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int i = 0;
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* list_element = allocation_sites_list();
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool trigger_deoptimization = false;
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool maximum_size_scavenge = MaximumSizeScavenge();
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    while (use_scratchpad ? i < allocation_sites_scratchpad_length_
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          : list_element->IsAllocationSite()) {
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationSite* site =
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          use_scratchpad
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              ? AllocationSite::cast(allocation_sites_scratchpad()->get(i))
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              : AllocationSite::cast(list_element);
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      allocation_mementos_found += site->memento_found_count();
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (site->memento_found_count() > 0) {
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        active_allocation_sites++;
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (site->DigestPretenuringFeedback(maximum_size_scavenge)) {
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          trigger_deoptimization = true;
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (site->GetPretenureMode() == TENURED) {
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          tenure_decisions++;
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          dont_tenure_decisions++;
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        allocation_sites++;
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (deopt_maybe_tenured && site->IsMaybeTenure()) {
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        site->set_deopt_dependent_code(true);
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        trigger_deoptimization = true;
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (use_scratchpad) {
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        i++;
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        list_element = site->weak_next();
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (trigger_deoptimization) {
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate_->stack_guard()->RequestDeoptMarkedAllocationSites();
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FlushAllocationSitesScratchpad();
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_trace_pretenuring_statistics &&
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        (allocation_mementos_found > 0 || tenure_decisions > 0 ||
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         dont_tenure_decisions > 0)) {
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrintF(
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          "GC: (mode, #visited allocation sites, #active allocation sites, "
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          "#mementos, #tenure decisions, #donttenure decisions) "
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          "(%s, %d, %d, %d, %d, %d)\n",
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          use_scratchpad ? "use scratchpad" : "use list", allocation_sites,
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          active_allocation_sites, allocation_mementos_found, tenure_decisions,
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          dont_tenure_decisions);
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::DeoptMarkedAllocationSites() {
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(hpayer): If iterating over the allocation sites list becomes a
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // performance issue, use a cache heap data structure instead (similar to the
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // allocation sites scratchpad).
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* list_element = allocation_sites_list();
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (list_element->IsAllocationSite()) {
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationSite* site = AllocationSite::cast(list_element);
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (site->deopt_dependent_code()) {
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      site->dependent_code()->MarkCodeForDeoptimization(
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          isolate_, DependentCode::kAllocationSiteTenuringChangedGroup);
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      site->set_deopt_dependent_code(false);
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    list_element = site->weak_next();
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Deoptimizer::DeoptimizeMarkedCode(isolate_);
584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::GarbageCollectionEpilogue() {
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  store_buffer()->GCEpilogue();
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // In release mode, we only zap the from space under heap verification.
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (Heap::ShouldZapGarbage()) {
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ZapFromSpace();
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Process pretenuring feedback and update allocation sites.
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProcessPretenuringFeedback();
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_verify_heap) {
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Verify();
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowHeapAllocation for_the_rest_of_the_epilogue;
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_print_global_handles) isolate_->global_handles()->Print();
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_print_handles) PrintHandles();
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_gc_verbose) Print();
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_code_stats) ReportCodeStatistics("After GC");
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_deopt_every_n_garbage_collections > 0) {
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // TODO(jkummerow/ulan/jarin): This is not safe! We can't assume that
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the topmost optimized frame can be deoptimized safely, because it
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // might not have a lazy bailout point right after its current PC.
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (++gcs_since_last_deopt_ == FLAG_deopt_every_n_garbage_collections) {
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Deoptimizer::DeoptimizeAll(isolate());
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      gcs_since_last_deopt_ = 0;
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateMaximumCommitted();
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->counters()->alive_after_last_gc()->Set(
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(SizeOfObjects()));
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->counters()->string_table_capacity()->Set(
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      string_table()->Capacity());
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->counters()->number_of_symbols()->Set(
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      string_table()->NumberOfElements());
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (full_codegen_bytes_generated_ + crankshaft_codegen_bytes_generated_ > 0) {
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->codegen_fraction_crankshaft()->AddSample(
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<int>((crankshaft_codegen_bytes_generated_ * 100.0) /
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         (crankshaft_codegen_bytes_generated_ +
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          full_codegen_bytes_generated_)));
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (CommittedMemory() > 0) {
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->external_fragmentation_total()->AddSample(
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<int>(100 - (SizeOfObjects() * 100.0) / CommittedMemory()));
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->heap_fraction_new_space()->AddSample(static_cast<int>(
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        (new_space()->CommittedMemory() * 100.0) / CommittedMemory()));
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->heap_fraction_old_pointer_space()->AddSample(
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<int>((old_pointer_space()->CommittedMemory() * 100.0) /
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         CommittedMemory()));
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->heap_fraction_old_data_space()->AddSample(
649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<int>((old_data_space()->CommittedMemory() * 100.0) /
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         CommittedMemory()));
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->heap_fraction_code_space()->AddSample(
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<int>((code_space()->CommittedMemory() * 100.0) /
653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         CommittedMemory()));
654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->heap_fraction_map_space()->AddSample(static_cast<int>(
655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        (map_space()->CommittedMemory() * 100.0) / CommittedMemory()));
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->heap_fraction_cell_space()->AddSample(
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<int>((cell_space()->CommittedMemory() * 100.0) /
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         CommittedMemory()));
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->heap_fraction_property_cell_space()->AddSample(
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<int>((property_cell_space()->CommittedMemory() * 100.0) /
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         CommittedMemory()));
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->heap_fraction_lo_space()->AddSample(static_cast<int>(
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        (lo_space()->CommittedMemory() * 100.0) / CommittedMemory()));
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->heap_sample_total_committed()->AddSample(
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<int>(CommittedMemory() / KB));
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->heap_sample_total_used()->AddSample(
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<int>(SizeOfObjects() / KB));
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->heap_sample_map_space_committed()->AddSample(
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<int>(map_space()->CommittedMemory() / KB));
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->heap_sample_cell_space_committed()->AddSample(
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<int>(cell_space()->CommittedMemory() / KB));
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ->heap_sample_property_cell_space_committed()
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ->AddSample(
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            static_cast<int>(property_cell_space()->CommittedMemory() / KB));
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->heap_sample_code_space_committed()->AddSample(
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<int>(code_space()->CommittedMemory() / KB));
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->heap_sample_maximum_committed()->AddSample(
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<int>(MaximumCommittedMemory() / KB));
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define UPDATE_COUNTERS_FOR_SPACE(space)                \
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->counters()->space##_bytes_available()->Set( \
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(space()->Available()));          \
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->counters()->space##_bytes_committed()->Set( \
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(space()->CommittedMemory()));    \
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->counters()->space##_bytes_used()->Set(      \
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(space()->SizeOfObjects()));
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define UPDATE_FRAGMENTATION_FOR_SPACE(space)                          \
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (space()->CommittedMemory() > 0) {                                \
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->counters()->external_fragmentation_##space()->AddSample( \
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<int>(100 -                                         \
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         (space()->SizeOfObjects() * 100.0) /          \
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             space()->CommittedMemory()));             \
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(space) \
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UPDATE_COUNTERS_FOR_SPACE(space)                         \
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UPDATE_FRAGMENTATION_FOR_SPACE(space)
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UPDATE_COUNTERS_FOR_SPACE(new_space)
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(old_pointer_space)
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(old_data_space)
705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(code_space)
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(map_space)
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(cell_space)
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(property_cell_space)
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(lo_space)
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef UPDATE_COUNTERS_FOR_SPACE
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef UPDATE_FRAGMENTATION_FOR_SPACE
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ReportStatisticsAfterGC();
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // DEBUG
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Remember the last top pointer so that we can later find out
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // whether we allocated in new space since the last GC.
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_top_after_last_gc_ = new_space()->top();
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::CollectAllGarbage(int flags, const char* gc_reason,
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             const v8::GCCallbackFlags gc_callback_flags) {
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Since we are ignoring the return value, the exact choice of space does
727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // not matter, so long as we do not specify NEW_SPACE, which would not
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cause a full GC.
729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mark_compact_collector_.SetFlags(flags);
730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CollectGarbage(OLD_POINTER_SPACE, gc_reason, gc_callback_flags);
731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mark_compact_collector_.SetFlags(kNoGCFlags);
732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::CollectAllAvailableGarbage(const char* gc_reason) {
736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Since we are ignoring the return value, the exact choice of space does
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // not matter, so long as we do not specify NEW_SPACE, which would not
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cause a full GC.
739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Major GC would invoke weak handle callbacks on weakly reachable
740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // handles, but won't collect weakly reachable objects until next
741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // major GC.  Therefore if we collect aggressively and weak handle callback
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // has been invoked, we rerun major GC to release objects which become
743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // garbage.
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Note: as weak callbacks can execute arbitrary code, we cannot
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // hope that eventually there will be no weak callbacks invocations.
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Therefore stop recollecting after several attempts.
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate()->concurrent_recompilation_enabled()) {
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The optimizing compiler may be unnecessarily holding on to memory.
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DisallowHeapAllocation no_recursive_gc;
750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate()->optimizing_compiler_thread()->Flush();
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mark_compact_collector()->SetFlags(kMakeHeapIterableMask |
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     kReduceMemoryFootprintMask);
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->compilation_cache()->Clear();
755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kMaxNumberOfAttempts = 7;
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kMinNumberOfAttempts = 2;
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) {
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!CollectGarbage(MARK_COMPACTOR, gc_reason, NULL) &&
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        attempt + 1 >= kMinNumberOfAttempts) {
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mark_compact_collector()->SetFlags(kNoGCFlags);
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_.Shrink();
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UncommitFromSpace();
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  incremental_marking()->UncommitMarkingDeque();
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::EnsureFillerObjectAtTop() {
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // There may be an allocation memento behind every object in new space.
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If we evacuate a not full new space or if we are on the last page of
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the new space, then there may be uninitialized memory behind the top
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // pointer of the new space page. We store a filler object there to
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // identify the unused space.
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address from_top = new_space_.top();
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address from_limit = new_space_.limit();
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (from_top < from_limit) {
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int remaining_in_page = static_cast<int>(from_limit - from_top);
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateFillerObjectAt(from_top, remaining_in_page);
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::CollectGarbage(GarbageCollector collector, const char* gc_reason,
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const char* collector_reason,
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const v8::GCCallbackFlags gc_callback_flags) {
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The VM is in the GC state until exiting this function.
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VMState<GC> state(isolate_);
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Reset the allocation timeout to the GC interval, but make sure to
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // allow at least a few allocations after a collection. The reason
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for this is that we have a lot of allocation sequences and we
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // assume that a garbage collection will allow the subsequent
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // allocation attempts to go through.
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  allocation_timeout_ = Max(6, FLAG_gc_interval);
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnsureFillerObjectAtTop();
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (collector == SCAVENGER && !incremental_marking()->IsStopped()) {
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_trace_incremental_marking) {
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrintF("[IncrementalMarking] Scavenge during marking.\n");
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (collector == MARK_COMPACTOR &&
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !mark_compact_collector()->abort_incremental_marking() &&
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !incremental_marking()->IsStopped() &&
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !incremental_marking()->should_hurry() &&
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FLAG_incremental_marking_steps) {
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Make progress in incremental marking.
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const intptr_t kStepSizeWhenDelayedByScavenge = 1 * MB;
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    incremental_marking()->Step(kStepSizeWhenDelayedByScavenge,
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                IncrementalMarking::NO_GC_VIA_STACK_GUARD);
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!incremental_marking()->IsComplete() && !FLAG_gc_global) {
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (FLAG_trace_incremental_marking) {
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        PrintF("[IncrementalMarking] Delaying MarkSweep.\n");
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      collector = SCAVENGER;
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      collector_reason = "incremental marking delaying mark-sweep";
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool next_gc_likely_to_collect_more = false;
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    tracer()->Start(collector, gc_reason, collector_reason);
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(AllowHeapAllocation::IsAllowed());
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DisallowHeapAllocation no_allocation_during_gc;
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GarbageCollectionPrologue();
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      HistogramTimerScope histogram_timer_scope(
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          (collector == SCAVENGER) ? isolate_->counters()->gc_scavenger()
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   : isolate_->counters()->gc_compactor());
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      next_gc_likely_to_collect_more =
839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          PerformGarbageCollection(collector, gc_callback_flags);
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GarbageCollectionEpilogue();
843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    tracer()->Stop();
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Start incremental marking for the next cycle. The heap snapshot
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // generator needs incremental marking to stay off after it aborted.
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!mark_compact_collector()->abort_incremental_marking() &&
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      WorthActivatingIncrementalMarking()) {
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    incremental_marking()->Start();
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return next_gc_likely_to_collect_more;
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint Heap::NotifyContextDisposed() {
858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate()->concurrent_recompilation_enabled()) {
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Flush the queued recompilation tasks.
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate()->optimizing_compiler_thread()->Flush();
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  flush_monomorphic_ics_ = true;
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AgeInlineCaches();
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return ++contexts_disposed_;
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::MoveElements(FixedArray* array, int dst_index, int src_index,
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        int len) {
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (len == 0) return;
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(array->map() != fixed_cow_array_map());
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object** dst_objects = array->data_start() + dst_index;
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemMove(dst_objects, array->data_start() + src_index, len * kPointerSize);
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!InNewSpace(array)) {
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < len; i++) {
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // TODO(hpayer): check store buffer for entries
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (InNewSpace(dst_objects[i])) {
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        RecordWrite(array->address(), array->OffsetOfElementAt(dst_index + i));
880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  incremental_marking()->RecordWrites(array);
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Helper class for verifying the string table.
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass StringTableVerifier : public ObjectVisitor {
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitPointers(Object** start, Object** end) {
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Visit all HeapObject pointers in [start, end).
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (Object** p = start; p < end; p++) {
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if ((*p)->IsHeapObject()) {
895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Check that the string is actually internalized.
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK((*p)->IsTheHole() || (*p)->IsUndefined() ||
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              (*p)->IsInternalizedString());
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void VerifyStringTable(Heap* heap) {
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StringTableVerifier verifier;
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->string_table()->IterateElements(&verifier);
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // VERIFY_HEAP
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool AbortIncrementalMarkingAndCollectGarbage(
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Heap* heap, AllocationSpace space, const char* gc_reason = NULL) {
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->mark_compact_collector()->SetFlags(Heap::kAbortIncrementalMarkingMask);
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool result = heap->CollectGarbage(space, gc_reason);
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->mark_compact_collector()->SetFlags(Heap::kNoGCFlags);
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ReserveSpace(int* sizes, Address* locations_out) {
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool gc_performed = true;
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int counter = 0;
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kThreshold = 20;
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (gc_performed && counter++ < kThreshold) {
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    gc_performed = false;
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(NEW_SPACE == FIRST_PAGED_SPACE - 1);
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int space = NEW_SPACE; space <= LAST_PAGED_SPACE; space++) {
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (sizes[space] != 0) {
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AllocationResult allocation;
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (space == NEW_SPACE) {
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          allocation = new_space()->AllocateRaw(sizes[space]);
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          allocation = paged_space(space)->AllocateRaw(sizes[space]);
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        FreeListNode* node;
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (!allocation.To(&node)) {
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (space == NEW_SPACE) {
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Heap::CollectGarbage(NEW_SPACE,
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 "failed to reserve space in the new space");
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else {
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            AbortIncrementalMarkingAndCollectGarbage(
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                this, static_cast<AllocationSpace>(space),
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "failed to reserve space in paged space");
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          }
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          gc_performed = true;
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // Mark with a free list node, in case we have a GC before
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // deserializing.
950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          node->set_size(this, sizes[space]);
951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          locations_out[space] = node->address();
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (gc_performed) {
958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Failed to reserve the space after several attempts.
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    V8::FatalProcessOutOfMemory("Heap::ReserveSpace");
960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::EnsureFromSpaceIsCommitted() {
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (new_space_.CommitFromSpaceIfNeeded()) return;
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Committing memory to from space failed.
968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Memory is exhausted and we will die.
969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  V8::FatalProcessOutOfMemory("Committing semi space failed.");
970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ClearJSFunctionResultCaches() {
974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate_->bootstrapper()->IsActive()) return;
975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* context = native_contexts_list();
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (!context->IsUndefined()) {
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Get the caches for this context. GC can happen when the context
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // is not fully initialized, so the caches can be undefined.
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* caches_or_undefined =
981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Context::cast(context)->get(Context::JSFUNCTION_RESULT_CACHES_INDEX);
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!caches_or_undefined->IsUndefined()) {
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FixedArray* caches = FixedArray::cast(caches_or_undefined);
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Clear the caches:
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int length = caches->length();
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (int i = 0; i < length; i++) {
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        JSFunctionResultCache::cast(caches->get(i))->Clear();
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Get the next context:
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ClearNormalizedMapCaches() {
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate_->bootstrapper()->IsActive() &&
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !incremental_marking()->IsMarking()) {
999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* context = native_contexts_list();
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (!context->IsUndefined()) {
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // GC can happen when the context is not fully initialized,
1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // so the cache can be undefined.
1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* cache =
1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Context::cast(context)->get(Context::NORMALIZED_MAP_CACHE_INDEX);
1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!cache->IsUndefined()) {
1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      NormalizedMapCache::cast(cache)->Clear();
1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::UpdateSurvivalStatistics(int start_new_space_size) {
1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (start_new_space_size == 0) return;
1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  promotion_rate_ = (static_cast<double>(promoted_objects_size_) /
1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     static_cast<double>(start_new_space_size) * 100);
1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  semi_space_copied_rate_ =
1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (static_cast<double>(semi_space_copied_object_size_) /
1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       static_cast<double>(start_new_space_size) * 100);
1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  double survival_rate = promotion_rate_ + semi_space_copied_rate_;
1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (survival_rate > kYoungSurvivalRateHighThreshold) {
1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    high_survival_rate_period_length_++;
1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    high_survival_rate_period_length_ = 0;
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::PerformGarbageCollection(
1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) {
1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int freed_global_handles = 0;
1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (collector != SCAVENGER) {
1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PROFILE(isolate_, CodeMovingGCEvent());
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_verify_heap) {
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VerifyStringTable(this);
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GCType gc_type =
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      collector == MARK_COMPACTOR ? kGCTypeMarkSweepCompact : kGCTypeScavenge;
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GCCallbacksScope scope(this);
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (scope.CheckReenter()) {
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllowHeapAllocation allow_allocation;
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL);
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VMState<EXTERNAL> state(isolate_);
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      HandleScope handle_scope(isolate_);
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallGCPrologueCallbacks(gc_type, kNoGCCallbackFlags);
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EnsureFromSpaceIsCommitted();
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int start_new_space_size = Heap::new_space()->SizeAsInt();
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsHighSurvivalRate()) {
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We speed up the incremental marker if it is running so that it
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // does not fall behind the rate of promotion, which would cause a
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // constantly growing old space.
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    incremental_marking()->NotifyOfHighPromotionRate();
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (collector == MARK_COMPACTOR) {
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Perform mark-sweep with optional compaction.
1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MarkCompact();
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sweep_generation_++;
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Temporarily set the limit for case when PostGarbageCollectionProcessing
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // allocates and triggers GC. The real limit is set at after
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // PostGarbageCollectionProcessing.
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    old_generation_allocation_limit_ =
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        OldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), 0);
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    old_gen_exhausted_ = false;
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Scavenge();
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateSurvivalStatistics(start_new_space_size);
1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->counters()->objs_since_last_young()->Set(0);
1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Callbacks that fire after this point might trigger nested GCs and
1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // restart incremental marking, the assertion can't be moved down.
1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(collector == SCAVENGER || incremental_marking()->IsStopped());
1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  gc_post_processing_depth_++;
1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllowHeapAllocation allow_allocation;
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL);
1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    freed_global_handles =
1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate_->global_handles()->PostGarbageCollectionProcessing(collector);
1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  gc_post_processing_depth_--;
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->eternal_handles()->PostGarbageCollectionProcessing(this);
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update relocatables.
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Relocatable::PostGarbageCollectionProcessing(isolate_);
1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (collector == MARK_COMPACTOR) {
1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Register the amount of external allocated memory.
1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    amount_of_external_allocated_memory_at_last_global_gc_ =
1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        amount_of_external_allocated_memory_;
1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    old_generation_allocation_limit_ = OldGenerationAllocationLimit(
1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        PromotedSpaceSizeOfObjects(), freed_global_handles);
1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GCCallbacksScope scope(this);
1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (scope.CheckReenter()) {
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllowHeapAllocation allow_allocation;
1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL);
1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VMState<EXTERNAL> state(isolate_);
1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      HandleScope handle_scope(isolate_);
1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CallGCEpilogueCallbacks(gc_type, gc_callback_flags);
1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_verify_heap) {
1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VerifyStringTable(this);
1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return freed_global_handles > 0;
1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) {
1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) {
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (gc_type & gc_prologue_callbacks_[i].gc_type) {
1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!gc_prologue_callbacks_[i].pass_isolate_) {
1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::GCPrologueCallback callback =
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            reinterpret_cast<v8::GCPrologueCallback>(
1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                gc_prologue_callbacks_[i].callback);
1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        callback(gc_type, flags);
1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate());
1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        gc_prologue_callbacks_[i].callback(isolate, gc_type, flags);
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::CallGCEpilogueCallbacks(GCType gc_type,
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   GCCallbackFlags gc_callback_flags) {
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) {
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (gc_type & gc_epilogue_callbacks_[i].gc_type) {
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!gc_epilogue_callbacks_[i].pass_isolate_) {
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::GCPrologueCallback callback =
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            reinterpret_cast<v8::GCPrologueCallback>(
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                gc_epilogue_callbacks_[i].callback);
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        callback(gc_type, gc_callback_flags);
1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate());
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        gc_epilogue_callbacks_[i].callback(isolate, gc_type, gc_callback_flags);
1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::MarkCompact() {
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  gc_state_ = MARK_COMPACT;
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOG(isolate_, ResourceEvent("markcompact", "begin"));
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint64_t size_of_objects_before_gc = SizeOfObjects();
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mark_compact_collector_.Prepare();
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ms_count_++;
1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkCompactPrologue();
1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mark_compact_collector_.CollectGarbage();
1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOG(isolate_, ResourceEvent("markcompact", "end"));
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  gc_state_ = NOT_IN_GC;
1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->counters()->objs_since_last_full()->Set(0);
1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  flush_monomorphic_ics_ = false;
1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_allocation_site_pretenuring) {
1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EvaluateOldSpaceLocalPretenuring(size_of_objects_before_gc);
1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::MarkCompactPrologue() {
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // At any old GC clear the keyed lookup cache to enable collection of unused
1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // maps.
1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->keyed_lookup_cache()->Clear();
1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->context_slot_cache()->Clear();
1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->descriptor_lookup_cache()->Clear();
1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegExpResultsCache::Clear(string_split_cache());
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegExpResultsCache::Clear(regexp_multiple_cache());
1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->compilation_cache()->MarkCompactPrologue();
1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompletelyClearInstanceofCache();
1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlushNumberStringCache();
1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_cleanup_code_caches_at_gc) {
1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    polymorphic_code_cache()->set_cache(undefined_value());
1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearNormalizedMapCaches();
1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Helper class for copying HeapObjects
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ScavengeVisitor : public ObjectVisitor {
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit ScavengeVisitor(Heap* heap) : heap_(heap) {}
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitPointer(Object** p) { ScavengePointer(p); }
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitPointers(Object** start, Object** end) {
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Copy all HeapObject pointers in [start, end)
1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (Object** p = start; p < end; p++) ScavengePointer(p);
1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ScavengePointer(Object** p) {
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* object = *p;
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!heap_->InNewSpace(object)) return;
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p),
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         reinterpret_cast<HeapObject*>(object));
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap* heap_;
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Visitor class to verify pointers in code or data space do not point into
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// new space.
1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass VerifyNonPointerSpacePointersVisitor : public ObjectVisitor {
1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit VerifyNonPointerSpacePointersVisitor(Heap* heap) : heap_(heap) {}
1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitPointers(Object** start, Object** end) {
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (Object** current = start; current < end; current++) {
1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if ((*current)->IsHeapObject()) {
1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CHECK(!heap_->InNewSpace(HeapObject::cast(*current)));
1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap* heap_;
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void VerifyNonPointerSpacePointers(Heap* heap) {
1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Verify that there are no pointers to new space in spaces where we
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // do not expect them.
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VerifyNonPointerSpacePointersVisitor v(heap);
1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObjectIterator code_it(heap->code_space());
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (HeapObject* object = code_it.Next(); object != NULL;
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       object = code_it.Next())
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object->Iterate(&v);
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HeapObjectIterator data_it(heap->old_data_space());
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (HeapObject* object = data_it.Next(); object != NULL;
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         object = data_it.Next())
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      object->Iterate(&v);
1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // VERIFY_HEAP
1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::CheckNewSpaceExpansionCriteria() {
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() &&
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      survived_since_last_expansion_ > new_space_.TotalCapacity()) {
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Grow the size of new space if there is room to grow, enough data
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // has survived scavenge since the last expansion and we are not in
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // high promotion mode.
1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    new_space_.Grow();
1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    survived_since_last_expansion_ = 0;
1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool IsUnscavengedHeapObject(Heap* heap, Object** p) {
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return heap->InNewSpace(*p) &&
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         !HeapObject::cast(*p)->map_word().IsForwardingAddress();
1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ScavengeStoreBufferCallback(Heap* heap, MemoryChunk* page,
1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       StoreBufferEvent event) {
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap->store_buffer_rebuilder_.Callback(page, event);
1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StoreBufferRebuilder::Callback(MemoryChunk* page, StoreBufferEvent event) {
1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (event == kStoreBufferStartScanningPagesEvent) {
1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    start_of_current_page_ = NULL;
1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    current_page_ = NULL;
1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (event == kStoreBufferScanningPageEvent) {
1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (current_page_ != NULL) {
1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // If this page already overflowed the store buffer during this iteration.
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (current_page_->scan_on_scavenge()) {
1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Then we should wipe out the entries that have been added for it.
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        store_buffer_->SetTop(start_of_current_page_);
1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (store_buffer_->Top() - start_of_current_page_ >=
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 (store_buffer_->Limit() - store_buffer_->Top()) >> 2) {
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Did we find too many pointers in the previous page?  The heuristic is
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // that no page can take more then 1/5 the remaining slots in the store
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // buffer.
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        current_page_->set_scan_on_scavenge(true);
1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        store_buffer_->SetTop(start_of_current_page_);
1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // In this case the page we scanned took a reasonable number of slots in
1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // the store buffer.  It has now been rehabilitated and is no longer
1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // marked scan_on_scavenge.
1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!current_page_->scan_on_scavenge());
1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    start_of_current_page_ = store_buffer_->Top();
1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    current_page_ = page;
1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (event == kStoreBufferFullEvent) {
1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The current page overflowed the store buffer again.  Wipe out its entries
1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // in the store buffer and mark it scan-on-scavenge again.  This may happen
1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // several times while scanning.
1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (current_page_ == NULL) {
1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Store Buffer overflowed while scanning promoted objects.  These are not
1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // in any particular page, though they are likely to be clustered by the
1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // allocation routines.
1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      store_buffer_->EnsureSpace(StoreBuffer::kStoreBufferSize / 2);
1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Store Buffer overflowed while scanning a particular old space page for
1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // pointers to new space.
1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(current_page_ == page);
1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(page != NULL);
1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      current_page_->set_scan_on_scavenge(true);
1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(start_of_current_page_ != store_buffer_->Top());
1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      store_buffer_->SetTop(start_of_current_page_);
1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PromotionQueue::Initialize() {
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Assumes that a NewSpacePage exactly fits a number of promotion queue
1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // entries (where each is a pair of intptr_t). This allows us to simplify
1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the test fpr when to switch pages.
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((Page::kPageSize - MemoryChunk::kBodyOffset) % (2 * kPointerSize) ==
1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         0);
1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  limit_ = reinterpret_cast<intptr_t*>(heap_->new_space()->ToSpaceStart());
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  front_ = rear_ =
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<intptr_t*>(heap_->new_space()->ToSpaceEnd());
1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emergency_stack_ = NULL;
1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PromotionQueue::RelocateQueueHead() {
1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(emergency_stack_ == NULL);
1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Page* p = Page::FromAllocationTop(reinterpret_cast<Address>(rear_));
1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t* head_start = rear_;
1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t* head_end = Min(front_, reinterpret_cast<intptr_t*>(p->area_end()));
1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int entries_count =
1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(head_end - head_start) / kEntrySizeInWords;
1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  emergency_stack_ = new List<Entry>(2 * entries_count);
1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (head_start != head_end) {
1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int size = static_cast<int>(*(head_start++));
1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HeapObject* obj = reinterpret_cast<HeapObject*>(*(head_start++));
1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    emergency_stack_->Add(Entry(obj, size));
1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  rear_ = head_end;
1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ScavengeWeakObjectRetainer : public WeakObjectRetainer {
1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit ScavengeWeakObjectRetainer(Heap* heap) : heap_(heap) {}
1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual Object* RetainAs(Object* object) {
1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!heap_->InFromSpace(object)) {
1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return object;
1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MapWord map_word = HeapObject::cast(object)->map_word();
1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (map_word.IsForwardingAddress()) {
1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return map_word.ToForwardingAddress();
1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return NULL;
1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap* heap_;
1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::Scavenge() {
1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RelocationLock relocation_lock(this);
1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_verify_heap) VerifyNonPointerSpacePointers(this);
1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  gc_state_ = SCAVENGE;
1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Implements Cheney's copying algorithm
1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOG(isolate_, ResourceEvent("scavenge", "begin"));
1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clear descriptor cache.
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->descriptor_lookup_cache()->Clear();
1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Used for updating survived_since_last_expansion_ at function end.
1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t survived_watermark = PromotedSpaceSizeOfObjects();
1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SelectScavengingVisitorsTable();
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  incremental_marking()->PrepareForScavenge();
1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Flip the semispaces.  After flipping, to space is empty, from space has
1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // live objects.
1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_.Flip();
1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_.ResetAllocationInfo();
1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We need to sweep newly copied objects which can be either in the
1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to space or promoted to the old generation.  For to-space
1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // objects, we treat the bottom of the to space as a queue.  Newly
1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // copied and unswept objects lie between a 'front' mark and the
1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // allocation pointer.
1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Promoted objects can go into various old-generation spaces, and
1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // can be allocated internally in the spaces (from the free list).
1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We treat the top of the to space as a queue of addresses of
1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // promoted objects.  The addresses of newly promoted and unswept
1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // objects lie between a 'front' mark and a 'rear' mark that is
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // updated as a side effect of promoting an object.
1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // There is guaranteed to be enough room at the top of the to space
1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for the addresses of promoted objects: every object promoted
1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // frees up its size in bytes from the top of the new space, and
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // objects are at least one pointer in size.
1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address new_space_front = new_space_.ToSpaceStart();
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  promotion_queue_.Initialize();
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  store_buffer()->Clean();
1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ScavengeVisitor scavenge_visitor(this);
1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy roots.
1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE);
1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy objects reachable from the old generation.
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    StoreBufferRebuildScope scope(this, store_buffer(),
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  &ScavengeStoreBufferCallback);
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    store_buffer()->IteratePointersToNewSpace(&ScavengeObject);
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy objects reachable from simple cells by scavenging cell values
1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // directly.
1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObjectIterator cell_iterator(cell_space_);
1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (HeapObject* heap_object = cell_iterator.Next(); heap_object != NULL;
1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       heap_object = cell_iterator.Next()) {
1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (heap_object->IsCell()) {
1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Cell* cell = Cell::cast(heap_object);
1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Address value_address = cell->ValueAddress();
1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy objects reachable from global property cells by scavenging global
1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // property cell values directly.
1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObjectIterator js_global_property_cell_iterator(property_cell_space_);
1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (HeapObject* heap_object = js_global_property_cell_iterator.Next();
1491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       heap_object != NULL;
1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       heap_object = js_global_property_cell_iterator.Next()) {
1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (heap_object->IsPropertyCell()) {
1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PropertyCell* cell = PropertyCell::cast(heap_object);
1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Address value_address = cell->ValueAddress();
1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Address type_address = cell->TypeAddress();
1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(type_address));
1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy objects reachable from the encountered weak collections list.
1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  scavenge_visitor.VisitPointer(&encountered_weak_collections_);
1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy objects reachable from the code flushing candidates list.
1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkCompactCollector* collector = mark_compact_collector();
1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (collector->is_code_flushing_enabled()) {
1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    collector->code_flusher()->IteratePointersToFromSpace(&scavenge_visitor);
1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (isolate()->global_handles()->IterateObjectGroups(
1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      &scavenge_visitor, &IsUnscavengedHeapObject)) {
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->global_handles()->RemoveObjectGroups();
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->global_handles()->RemoveImplicitRefGroups();
1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->global_handles()->IdentifyNewSpaceWeakIndependentHandles(
1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      &IsUnscavengedHeapObject);
1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->global_handles()->IterateNewSpaceWeakIndependentRoots(
1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      &scavenge_visitor);
1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateNewSpaceReferencesInExternalStringTable(
1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      &UpdateNewSpaceReferenceInExternalStringTableEntry);
1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  promotion_queue_.Destroy();
1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  incremental_marking()->UpdateMarkingDequeAfterScavenge();
1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ScavengeWeakObjectRetainer weak_object_retainer(this);
1534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProcessWeakReferences(&weak_object_retainer);
1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(new_space_front == new_space_.top());
1537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set age mark.
1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_.set_age_mark(new_space_.top());
1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_.LowerInlineAllocationLimit(
1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new_space_.inline_allocation_limit_step());
1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update how much has survived scavenge.
1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IncrementYoungSurvivorsCounter(static_cast<int>(
1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size()));
1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOG(isolate_, ResourceEvent("scavenge", "end"));
1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  gc_state_ = NOT_IN_GC;
1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  gc_idle_time_handler_.NotifyScavenge();
1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochString* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                                Object** p) {
1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MapWord first_word = HeapObject::cast(*p)->map_word();
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!first_word.IsForwardingAddress()) {
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Unreachable external string can be finalized.
1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    heap->FinalizeExternalString(String::cast(*p));
1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return NULL;
1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // String is still reachable.
1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return String::cast(first_word.ToForwardingAddress());
1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::UpdateNewSpaceReferencesInExternalStringTable(
1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalStringTableUpdaterCallback updater_func) {
1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_verify_heap) {
1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    external_string_table_.Verify();
1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (external_string_table_.new_space_strings_.is_empty()) return;
1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object** start = &external_string_table_.new_space_strings_[0];
1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object** end = start + external_string_table_.new_space_strings_.length();
1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object** last = start;
1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (Object** p = start; p < end; ++p) {
1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(InFromSpace(*p));
1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    String* target = updater_func(this, p);
1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (target == NULL) continue;
1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(target->IsExternalString());
1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (InNewSpace(target)) {
1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // String is still in new space.  Update the table entry.
1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *last = target;
1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ++last;
1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // String got promoted.  Move it to the old string list.
1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      external_string_table_.AddOldString(target);
1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(last <= end);
1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  external_string_table_.ShrinkNewStrings(static_cast<int>(last - start));
1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::UpdateReferencesInExternalStringTable(
1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalStringTableUpdaterCallback updater_func) {
1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update old space string references.
1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (external_string_table_.old_space_strings_.length() > 0) {
1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object** start = &external_string_table_.old_space_strings_[0];
1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object** end = start + external_string_table_.old_space_strings_.length();
1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (Object** p = start; p < end; ++p) *p = updater_func(this, p);
1615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateNewSpaceReferencesInExternalStringTable(updater_func);
1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) {
1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProcessArrayBuffers(retainer);
1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProcessNativeContexts(retainer);
1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(mvstanton): AllocationSites only need to be processed during
1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // MARK_COMPACT, as they live in old space. Verify and address.
1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProcessAllocationSites(retainer);
1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ProcessNativeContexts(WeakObjectRetainer* retainer) {
1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* head = VisitWeakList<Context>(this, native_contexts_list(), retainer);
1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update the head of the list of contexts.
1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_native_contexts_list(head);
1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ProcessArrayBuffers(WeakObjectRetainer* retainer) {
1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* array_buffer_obj =
1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitWeakList<JSArrayBuffer>(this, array_buffers_list(), retainer);
1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_array_buffers_list(array_buffer_obj);
1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::TearDownArrayBuffers() {
1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* undefined = undefined_value();
1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (Object* o = array_buffers_list(); o != undefined;) {
1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JSArrayBuffer* buffer = JSArrayBuffer::cast(o);
1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Runtime::FreeArrayBuffer(isolate(), buffer);
1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    o = buffer->weak_next();
1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_array_buffers_list(undefined);
1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ProcessAllocationSites(WeakObjectRetainer* retainer) {
1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* allocation_site_obj =
1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitWeakList<AllocationSite>(this, allocation_sites_list(), retainer);
1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_allocation_sites_list(allocation_site_obj);
1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ResetAllAllocationSitesDependentCode(PretenureFlag flag) {
1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_allocation_scope;
1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* cur = allocation_sites_list();
1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool marked = false;
1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (cur->IsAllocationSite()) {
1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationSite* casted = AllocationSite::cast(cur);
1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (casted->GetPretenureMode() == flag) {
1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      casted->ResetPretenureDecision();
1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      casted->set_deopt_dependent_code(true);
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      marked = true;
1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cur = casted->weak_next();
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (marked) isolate_->stack_guard()->RequestDeoptMarkedAllocationSites();
1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::EvaluateOldSpaceLocalPretenuring(
1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint64_t size_of_objects_before_gc) {
1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint64_t size_of_objects_after_gc = SizeOfObjects();
1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  double old_generation_survival_rate =
1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (static_cast<double>(size_of_objects_after_gc) * 100) /
1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<double>(size_of_objects_before_gc);
1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (old_generation_survival_rate < kOldSurvivalRateLowThreshold) {
1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Too many objects died in the old generation, pretenuring of wrong
1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // allocation sites may be the cause for that. We have to deopt all
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // dependent code registered in the allocation sites to re-evaluate
1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // our pretenuring decisions.
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ResetAllAllocationSitesDependentCode(TENURED);
1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_trace_pretenuring) {
1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrintF(
1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          "Deopt all allocation sites dependent code due to low survival "
1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          "rate in the old generation %f\n",
1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          old_generation_survival_rate);
1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_allocation;
1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All external strings are listed in the external string table.
1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  class ExternalStringTableVisitorAdapter : public ObjectVisitor {
1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    explicit ExternalStringTableVisitorAdapter(
1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        v8::ExternalResourceVisitor* visitor)
1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : visitor_(visitor) {}
1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    virtual void VisitPointers(Object** start, Object** end) {
1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (Object** p = start; p < end; p++) {
1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK((*p)->IsExternalString());
1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        visitor_->VisitExternalString(
1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Utils::ToLocal(Handle<String>(String::cast(*p))));
1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::ExternalResourceVisitor* visitor_;
1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } external_string_table_visitor(visitor);
1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  external_string_table_.Iterate(&external_string_table_visitor);
1724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> {
1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline void VisitPointer(Heap* heap, Object** p) {
1730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* object = *p;
1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!heap->InNewSpace(object)) return;
1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p),
1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         reinterpret_cast<HeapObject*>(object));
1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAddress Heap::DoScavenge(ObjectVisitor* scavenge_visitor,
1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Address new_space_front) {
1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  do {
1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SemiSpace::AssertValidRange(new_space_front, new_space_.top());
1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The addresses new_space_front and new_space_.top() define a
1743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // queue of unprocessed copied objects.  Process them until the
1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // queue is empty.
1745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    while (new_space_front != new_space_.top()) {
1746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!NewSpacePage::IsAtEnd(new_space_front)) {
1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        HeapObject* object = HeapObject::FromAddress(new_space_front);
1748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new_space_front +=
1749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            NewSpaceScavenger::IterateBody(object->map(), object);
1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new_space_front =
1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            NewSpacePage::FromLimit(new_space_front)->next_page()->area_start();
1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Promote and process all the to-be-promoted objects.
1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      StoreBufferRebuildScope scope(this, store_buffer(),
1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    &ScavengeStoreBufferCallback);
1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      while (!promotion_queue()->is_empty()) {
1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        HeapObject* target;
1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int size;
1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        promotion_queue()->remove(&target, &size);
1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Promoted object might be already partially visited
1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // during old space pointer iteration. Thus we search specificly
1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // for pointers to from semispace instead of looking for pointers
1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // to new space.
1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!target->IsMap());
1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        IterateAndMarkPointersToFromSpace(
1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            target->address(), target->address() + size, &ScavengeObject);
1772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Take another spin if there are now unswept objects in new space
1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // (there are currently no more unswept promoted objects).
1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } while (new_space_front != new_space_.top());
1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return new_space_front;
1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSTATIC_ASSERT((FixedDoubleArray::kHeaderSize & kDoubleAlignmentMask) ==
1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              0);  // NOLINT
1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSTATIC_ASSERT((ConstantPoolArray::kFirstEntryOffset & kDoubleAlignmentMask) ==
1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              0);  // NOLINT
1787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSTATIC_ASSERT((ConstantPoolArray::kExtendedFirstOffset &
1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               kDoubleAlignmentMask) == 0);  // NOLINT
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochINLINE(static HeapObject* EnsureDoubleAligned(Heap* heap, HeapObject* object,
1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              int size));
1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic HeapObject* EnsureDoubleAligned(Heap* heap, HeapObject* object,
1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       int size) {
1796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((OffsetFrom(object->address()) & kDoubleAlignmentMask) != 0) {
1797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    heap->CreateFillerObjectAt(object->address(), kPointerSize);
1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return HeapObject::FromAddress(object->address() + kPointerSize);
1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    heap->CreateFillerObjectAt(object->address() + size - kPointerSize,
1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               kPointerSize);
1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return object;
1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum LoggingAndProfiling {
1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOGGING_AND_PROFILING_ENABLED,
1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOGGING_AND_PROFILING_DISABLED
1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum MarksHandling { TRANSFER_MARKS, IGNORE_MARKS };
1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <MarksHandling marks_handling,
1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          LoggingAndProfiling logging_and_profiling_mode>
1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ScavengingVisitor : public StaticVisitorBase {
1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void Initialize() {
1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(kVisitSeqOneByteString, &EvacuateSeqOneByteString);
1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(kVisitSeqTwoByteString, &EvacuateSeqTwoByteString);
1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(kVisitShortcutCandidate, &EvacuateShortcutCandidate);
1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(kVisitByteArray, &EvacuateByteArray);
1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(kVisitFixedArray, &EvacuateFixedArray);
1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(kVisitFixedDoubleArray, &EvacuateFixedDoubleArray);
1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(kVisitFixedTypedArray, &EvacuateFixedTypedArray);
1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(kVisitFixedFloat64Array, &EvacuateFixedFloat64Array);
1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(
1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        kVisitNativeContext,
1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        &ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized<
1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Context::kSize>);
1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(
1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        kVisitConsString,
1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        &ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized<
1838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            ConsString::kSize>);
1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(
1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        kVisitSlicedString,
1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        &ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized<
1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            SlicedString::kSize>);
1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(
1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        kVisitSymbol,
1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        &ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized<
1848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Symbol::kSize>);
1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(
1851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        kVisitSharedFunctionInfo,
1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        &ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized<
1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            SharedFunctionInfo::kSize>);
1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(kVisitJSWeakCollection,
1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    &ObjectEvacuationStrategy<POINTER_OBJECT>::Visit);
1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(kVisitJSArrayBuffer,
1859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    &ObjectEvacuationStrategy<POINTER_OBJECT>::Visit);
1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(kVisitJSTypedArray,
1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    &ObjectEvacuationStrategy<POINTER_OBJECT>::Visit);
1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(kVisitJSDataView,
1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    &ObjectEvacuationStrategy<POINTER_OBJECT>::Visit);
1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.Register(kVisitJSRegExp,
1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    &ObjectEvacuationStrategy<POINTER_OBJECT>::Visit);
1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (marks_handling == IGNORE_MARKS) {
1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      table_.Register(
1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          kVisitJSFunction,
1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          &ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized<
1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              JSFunction::kSize>);
1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      table_.Register(kVisitJSFunction, &EvacuateJSFunction);
1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.RegisterSpecializations<ObjectEvacuationStrategy<DATA_OBJECT>,
1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   kVisitDataObject, kVisitDataObjectGeneric>();
1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   kVisitJSObject, kVisitJSObjectGeneric>();
1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   kVisitStruct, kVisitStructGeneric>();
1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static VisitorDispatchTable<ScavengingCallback>* GetTable() {
1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return &table_;
1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum ObjectContents { DATA_OBJECT, POINTER_OBJECT };
1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void RecordCopiedObject(Heap* heap, HeapObject* obj) {
1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool should_record = false;
1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    should_record = FLAG_heap_stats;
1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    should_record = should_record || FLAG_log_gc;
1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (should_record) {
1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (heap->new_space()->Contains(obj)) {
1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        heap->new_space()->RecordAllocation(obj);
1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        heap->new_space()->RecordPromotion(obj);
1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Helper function used by CopyObject to copy a source object to an
1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // allocated target object and update the forwarding pointer in the source
1913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object.  Returns the target object.
1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static void MigrateObject(Heap* heap, HeapObject* source,
1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   HeapObject* target, int size)) {
1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If we migrate into to-space, then the to-space top pointer should be
1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // right after the target object. Incorporate double alignment
1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // over-allocation.
1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!heap->InToSpace(target) ||
1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           target->address() + size == heap->new_space()->top() ||
1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           target->address() + size + kPointerSize == heap->new_space()->top());
1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Make sure that we do not overwrite the promotion queue which is at
1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the end of to-space.
1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!heap->InToSpace(target) ||
1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           heap->promotion_queue()->IsBelowPromotionQueue(
1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               heap->new_space()->top()));
1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Copy the content of source to target.
1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    heap->CopyBlock(target->address(), source->address(), size);
1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Set the forwarding address.
1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    source->set_map_word(MapWord::FromForwardingAddress(target));
1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (logging_and_profiling_mode == LOGGING_AND_PROFILING_ENABLED) {
1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Update NewSpace stats if necessary.
1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RecordCopiedObject(heap, target);
1938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      heap->OnMoveEvent(target, source, size);
1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (marks_handling == TRANSFER_MARKS) {
1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (Marking::TransferColor(source, target)) {
1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        MemoryChunk::IncrementLiveBytesFromGC(target->address(), size);
1944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template <int alignment>
1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline bool SemiSpaceCopyObject(Map* map, HeapObject** slot,
1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         HeapObject* object, int object_size) {
1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Heap* heap = map->GetHeap();
1952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int allocation_size = object_size;
1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (alignment != kObjectAlignment) {
1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(alignment == kDoubleAlignment);
1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      allocation_size += kPointerSize;
1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(heap->AllowedToBeMigrated(object, NEW_SPACE));
1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation =
1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        heap->new_space()->AllocateRaw(allocation_size);
1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HeapObject* target = NULL;  // Initialization to please compiler.
1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (allocation.To(&target)) {
1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Order is important here: Set the promotion limit before storing a
1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // filler for double alignment or migrating the object. Otherwise we
1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // may end up overwriting promotion queue entries when we migrate the
1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // object.
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      heap->promotion_queue()->SetNewLimit(heap->new_space()->top());
1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (alignment != kObjectAlignment) {
1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        target = EnsureDoubleAligned(heap, target, allocation_size);
1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Order is important: slot might be inside of the target if target
1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // was allocated over a dead object and slot comes from the store
1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // buffer.
1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *slot = target;
1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MigrateObject(heap, object, target, object_size);
1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      heap->IncrementSemiSpaceCopiedObjectSize(object_size);
1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return true;
1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return false;
1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template <ObjectContents object_contents, int alignment>
1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline bool PromoteObject(Map* map, HeapObject** slot,
1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   HeapObject* object, int object_size) {
1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Heap* heap = map->GetHeap();
1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int allocation_size = object_size;
1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (alignment != kObjectAlignment) {
1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(alignment == kDoubleAlignment);
1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      allocation_size += kPointerSize;
1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation;
2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (object_contents == DATA_OBJECT) {
2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(heap->AllowedToBeMigrated(object, OLD_DATA_SPACE));
2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      allocation = heap->old_data_space()->AllocateRaw(allocation_size);
2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(heap->AllowedToBeMigrated(object, OLD_POINTER_SPACE));
2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      allocation = heap->old_pointer_space()->AllocateRaw(allocation_size);
2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HeapObject* target = NULL;  // Initialization to please compiler.
2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (allocation.To(&target)) {
2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (alignment != kObjectAlignment) {
2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        target = EnsureDoubleAligned(heap, target, allocation_size);
2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Order is important: slot might be inside of the target if target
2015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // was allocated over a dead object and slot comes from the store
2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // buffer.
2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *slot = target;
2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MigrateObject(heap, object, target, object_size);
2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (object_contents == POINTER_OBJECT) {
2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (map->instance_type() == JS_FUNCTION_TYPE) {
2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          heap->promotion_queue()->insert(target,
2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          JSFunction::kNonWeakFieldsEndOffset);
2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          heap->promotion_queue()->insert(target, object_size);
2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      heap->IncrementPromotedObjectsSize(object_size);
2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return true;
2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return false;
2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template <ObjectContents object_contents, int alignment>
2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline void EvacuateObject(Map* map, HeapObject** slot,
2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    HeapObject* object, int object_size) {
2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SLOW_DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SLOW_DCHECK(object->Size() == object_size);
2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Heap* heap = map->GetHeap();
2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!heap->ShouldBePromoted(object->address(), object_size)) {
2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // A semi-space copy may fail due to fragmentation. In that case, we
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // try to promote the object.
2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) {
2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (PromoteObject<object_contents, alignment>(map, slot, object,
2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  object_size)) {
2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If promotion failed, we try to copy the object to the other semi-space
2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) return;
2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline void EvacuateJSFunction(Map* map, HeapObject** slot,
2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        HeapObject* object) {
2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ObjectEvacuationStrategy<POINTER_OBJECT>::template VisitSpecialized<
2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        JSFunction::kSize>(map, slot, object);
2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MapWord map_word = object->map_word();
2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(map_word.IsForwardingAddress());
2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HeapObject* target = map_word.ToForwardingAddress();
2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MarkBit mark_bit = Marking::MarkBitFrom(target);
2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (Marking::IsBlack(mark_bit)) {
2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // This object is black and it might not be rescanned by marker.
2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // We should explicitly record code entry slot for compaction because
2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // promotion queue processing (IterateAndMarkPointersToFromSpace) will
2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // miss it as it is not HeapObject-tagged.
2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Address code_entry_slot =
2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          target->address() + JSFunction::kCodeEntryOffset;
2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Code* code = Code::cast(Code::GetObjectFromEntryAddress(code_entry_slot));
2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      map->GetHeap()->mark_compact_collector()->RecordCodeEntrySlot(
2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          code_entry_slot, code);
2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline void EvacuateFixedArray(Map* map, HeapObject** slot,
2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        HeapObject* object) {
2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int object_size = FixedArray::BodyDescriptor::SizeOf(map, object);
2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EvacuateObject<POINTER_OBJECT, kObjectAlignment>(map, slot, object,
2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     object_size);
2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline void EvacuateFixedDoubleArray(Map* map, HeapObject** slot,
2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              HeapObject* object) {
2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int length = reinterpret_cast<FixedDoubleArray*>(object)->length();
2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int object_size = FixedDoubleArray::SizeFor(length);
2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EvacuateObject<DATA_OBJECT, kDoubleAlignment>(map, slot, object,
2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  object_size);
2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline void EvacuateFixedTypedArray(Map* map, HeapObject** slot,
2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             HeapObject* object) {
2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int object_size = reinterpret_cast<FixedTypedArrayBase*>(object)->size();
2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EvacuateObject<DATA_OBJECT, kObjectAlignment>(map, slot, object,
2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  object_size);
2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline void EvacuateFixedFloat64Array(Map* map, HeapObject** slot,
2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               HeapObject* object) {
2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int object_size = reinterpret_cast<FixedFloat64Array*>(object)->size();
2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EvacuateObject<DATA_OBJECT, kDoubleAlignment>(map, slot, object,
2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  object_size);
2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline void EvacuateByteArray(Map* map, HeapObject** slot,
2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       HeapObject* object) {
2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int object_size = reinterpret_cast<ByteArray*>(object)->ByteArraySize();
2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EvacuateObject<DATA_OBJECT, kObjectAlignment>(map, slot, object,
2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  object_size);
2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline void EvacuateSeqOneByteString(Map* map, HeapObject** slot,
2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              HeapObject* object) {
2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int object_size = SeqOneByteString::cast(object)
2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          ->SeqOneByteStringSize(map->instance_type());
2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EvacuateObject<DATA_OBJECT, kObjectAlignment>(map, slot, object,
2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  object_size);
2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline void EvacuateSeqTwoByteString(Map* map, HeapObject** slot,
2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              HeapObject* object) {
2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int object_size = SeqTwoByteString::cast(object)
2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          ->SeqTwoByteStringSize(map->instance_type());
2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EvacuateObject<DATA_OBJECT, kObjectAlignment>(map, slot, object,
2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  object_size);
2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline void EvacuateShortcutCandidate(Map* map, HeapObject** slot,
2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               HeapObject* object) {
2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(IsShortcutCandidate(map->instance_type()));
2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Heap* heap = map->GetHeap();
2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (marks_handling == IGNORE_MARKS &&
2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ConsString::cast(object)->unchecked_second() == heap->empty_string()) {
2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      HeapObject* first =
2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          HeapObject::cast(ConsString::cast(object)->unchecked_first());
2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *slot = first;
2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!heap->InNewSpace(first)) {
2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        object->set_map_word(MapWord::FromForwardingAddress(first));
2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MapWord first_word = first->map_word();
2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (first_word.IsForwardingAddress()) {
2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        HeapObject* target = first_word.ToForwardingAddress();
2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        *slot = target;
2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        object->set_map_word(MapWord::FromForwardingAddress(target));
2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      heap->DoScavengeObject(first->map(), slot, first);
2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      object->set_map_word(MapWord::FromForwardingAddress(*slot));
2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int object_size = ConsString::kSize;
2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EvacuateObject<POINTER_OBJECT, kObjectAlignment>(map, slot, object,
2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                     object_size);
2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  template <ObjectContents object_contents>
2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  class ObjectEvacuationStrategy {
2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    template <int object_size>
2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static inline void VisitSpecialized(Map* map, HeapObject** slot,
2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        HeapObject* object) {
2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EvacuateObject<object_contents, kObjectAlignment>(map, slot, object,
2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        object_size);
2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static inline void Visit(Map* map, HeapObject** slot, HeapObject* object) {
2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int object_size = map->instance_size();
2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EvacuateObject<object_contents, kObjectAlignment>(map, slot, object,
2195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                        object_size);
2196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static VisitorDispatchTable<ScavengingCallback> table_;
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <MarksHandling marks_handling,
2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          LoggingAndProfiling logging_and_profiling_mode>
2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochVisitorDispatchTable<ScavengingCallback>
2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ScavengingVisitor<marks_handling, logging_and_profiling_mode>::table_;
2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InitializeScavengingVisitorsTables() {
2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ScavengingVisitor<TRANSFER_MARKS,
2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    LOGGING_AND_PROFILING_DISABLED>::Initialize();
2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_DISABLED>::Initialize();
2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ScavengingVisitor<TRANSFER_MARKS,
2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    LOGGING_AND_PROFILING_ENABLED>::Initialize();
2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_ENABLED>::Initialize();
2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::SelectScavengingVisitorsTable() {
2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool logging_and_profiling =
2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FLAG_verify_predictable || isolate()->logger()->is_logging() ||
2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate()->cpu_profiler()->is_profiling() ||
2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (isolate()->heap_profiler() != NULL &&
2224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       isolate()->heap_profiler()->is_tracking_object_moves());
2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!incremental_marking()->IsMarking()) {
2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!logging_and_profiling) {
2228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      scavenging_visitors_table_.CopyFrom(ScavengingVisitor<
2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          IGNORE_MARKS, LOGGING_AND_PROFILING_DISABLED>::GetTable());
2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      scavenging_visitors_table_.CopyFrom(ScavengingVisitor<
2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          IGNORE_MARKS, LOGGING_AND_PROFILING_ENABLED>::GetTable());
2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!logging_and_profiling) {
2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      scavenging_visitors_table_.CopyFrom(ScavengingVisitor<
2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          TRANSFER_MARKS, LOGGING_AND_PROFILING_DISABLED>::GetTable());
2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      scavenging_visitors_table_.CopyFrom(ScavengingVisitor<
2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          TRANSFER_MARKS, LOGGING_AND_PROFILING_ENABLED>::GetTable());
2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (incremental_marking()->IsCompacting()) {
2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // When compacting forbid short-circuiting of cons-strings.
2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Scavenging code relies on the fact that new space object
2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // can't be evacuated into evacuation candidate but
2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // short-circuiting violates this assumption.
2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      scavenging_visitors_table_.Register(
2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          StaticVisitorBase::kVisitShortcutCandidate,
2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          scavenging_visitors_table_.GetVisitorById(
2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              StaticVisitorBase::kVisitConsString));
2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SLOW_DCHECK(object->GetIsolate()->heap()->InFromSpace(object));
2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MapWord first_word = object->map_word();
2260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SLOW_DCHECK(!first_word.IsForwardingAddress());
2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Map* map = first_word.ToMap();
2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->GetHeap()->DoScavengeObject(map, p, object);
2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocatePartialMap(InstanceType instance_type,
2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          int instance_size) {
2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* result;
2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE, MAP_SPACE);
2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!allocation.To(&result)) return allocation;
2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Map::cast cannot be used due to uninitialized map field.
2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map());
2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reinterpret_cast<Map*>(result)->set_instance_type(instance_type);
2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reinterpret_cast<Map*>(result)->set_instance_size(instance_size);
2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reinterpret_cast<Map*>(result)->set_visitor_id(
2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      StaticVisitorBase::GetVisitorId(instance_type, instance_size));
2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reinterpret_cast<Map*>(result)->set_inobject_properties(0);
2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reinterpret_cast<Map*>(result)->set_pre_allocated_property_fields(0);
2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reinterpret_cast<Map*>(result)->set_unused_property_fields(0);
2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reinterpret_cast<Map*>(result)->set_bit_field(0);
2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reinterpret_cast<Map*>(result)->set_bit_field2(0);
2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) |
2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Map::OwnsDescriptors::encode(true);
2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reinterpret_cast<Map*>(result)->set_bit_field3(bit_field3);
2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateMap(InstanceType instance_type,
2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   int instance_size,
2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   ElementsKind elements_kind) {
2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE, MAP_SPACE);
2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!allocation.To(&result)) return allocation;
2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_map_no_write_barrier(meta_map());
2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Map* map = Map::cast(result);
2299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_instance_type(instance_type);
2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_visitor_id(
2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      StaticVisitorBase::GetVisitorId(instance_type, instance_size));
2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_prototype(null_value(), SKIP_WRITE_BARRIER);
2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_constructor(null_value(), SKIP_WRITE_BARRIER);
2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_instance_size(instance_size);
2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_inobject_properties(0);
2306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_pre_allocated_property_fields(0);
2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_code_cache(empty_fixed_array(), SKIP_WRITE_BARRIER);
2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_dependent_code(DependentCode::cast(empty_fixed_array()),
2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          SKIP_WRITE_BARRIER);
2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->init_back_pointer(undefined_value());
2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_unused_property_fields(0);
2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_instance_descriptors(empty_descriptor_array());
2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_bit_field(0);
2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_bit_field2(1 << Map::kIsExtensible);
2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) |
2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   Map::OwnsDescriptors::encode(true);
2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_bit_field3(bit_field3);
2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map->set_elements_kind(elements_kind);
2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return map;
2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateFillerObject(int size, bool double_align,
2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            AllocationSpace space) {
2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* obj;
2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRaw(size, space, space);
2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&obj)) return allocation;
2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address());
2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(chunk->owner()->identity() == space);
2334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
2335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CreateFillerObjectAt(obj->address(), size);
2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return obj;
2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst Heap::StringTypeTable Heap::string_type_table[] = {
2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define STRING_TYPE_ELEMENT(type, size, name, camel_name) \
2342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { type, size, k##camel_name##MapRootIndex }             \
2343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ,
2344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STRING_TYPE_LIST(STRING_TYPE_ELEMENT)
2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef STRING_TYPE_ELEMENT
2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst Heap::ConstantStringTable Heap::constant_string_table[] = {
2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define CONSTANT_STRING_ELEMENT(name, contents) \
2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { contents, k##name##RootIndex }              \
2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ,
2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    INTERNALIZED_STRING_LIST(CONSTANT_STRING_ELEMENT)
2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef CONSTANT_STRING_ELEMENT
2355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst Heap::StructTable Heap::struct_table[] = {
2359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define STRUCT_TABLE_ELEMENT(NAME, Name, name)        \
2360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { NAME##_TYPE, Name::kSize, k##Name##MapRootIndex } \
2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ,
2362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STRUCT_LIST(STRUCT_TABLE_ELEMENT)
2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef STRUCT_TABLE_ELEMENT
2364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::CreateInitialMaps() {
2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* obj;
2369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocatePartialMap(MAP_TYPE, Map::kSize);
2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&obj)) return false;
2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Map::cast cannot be used due to uninitialized map field.
2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Map* new_meta_map = reinterpret_cast<Map*>(obj);
2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_meta_map(new_meta_map);
2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_meta_map->set_map(new_meta_map);
2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {  // Partial map allocation
2379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ALLOCATE_PARTIAL_MAP(instance_type, size, field_name)                \
2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {                                                                          \
2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Map* map;                                                                \
2382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!AllocatePartialMap((instance_type), (size)).To(&map)) return false; \
2383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_##field_name##_map(map);                                             \
2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_PARTIAL_MAP(FIXED_ARRAY_TYPE, kVariableSizeSentinel, fixed_array);
2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_PARTIAL_MAP(ODDBALL_TYPE, Oddball::kSize, undefined);
2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_PARTIAL_MAP(ODDBALL_TYPE, Oddball::kSize, null);
2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_PARTIAL_MAP(CONSTANT_POOL_ARRAY_TYPE, kVariableSizeSentinel,
2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         constant_pool_array);
2391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ALLOCATE_PARTIAL_MAP
2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate the empty array.
2396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
2397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateEmptyFixedArray();
2398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&obj)) return false;
2399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_empty_fixed_array(FixedArray::cast(obj));
2401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
2403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = Allocate(null_map(), OLD_POINTER_SPACE);
2404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&obj)) return false;
2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_null_value(Oddball::cast(obj));
2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Oddball::cast(obj)->set_kind(Oddball::kNull);
2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = Allocate(undefined_map(), OLD_POINTER_SPACE);
2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&obj)) return false;
2412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_undefined_value(Oddball::cast(obj));
2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Oddball::cast(obj)->set_kind(Oddball::kUndefined);
2415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!InNewSpace(undefined_value()));
2416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set preliminary exception sentinel value before actually initializing it.
2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_exception(null_value());
2419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate the empty descriptor array.
2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
2422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateEmptyFixedArray();
2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&obj)) return false;
2424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_empty_descriptor_array(DescriptorArray::cast(obj));
2426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate the constant pool array.
2428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateEmptyConstantPoolArray();
2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&obj)) return false;
2431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_empty_constant_pool_array(ConstantPoolArray::cast(obj));
2433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Fix the instance_descriptors for the existing maps.
2435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  meta_map()->set_code_cache(empty_fixed_array());
2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  meta_map()->set_dependent_code(DependentCode::cast(empty_fixed_array()));
2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  meta_map()->init_back_pointer(undefined_value());
2438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  meta_map()->set_instance_descriptors(empty_descriptor_array());
2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fixed_array_map()->set_code_cache(empty_fixed_array());
2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fixed_array_map()->set_dependent_code(
2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DependentCode::cast(empty_fixed_array()));
2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fixed_array_map()->init_back_pointer(undefined_value());
2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fixed_array_map()->set_instance_descriptors(empty_descriptor_array());
2445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  undefined_map()->set_code_cache(empty_fixed_array());
2447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  undefined_map()->set_dependent_code(DependentCode::cast(empty_fixed_array()));
2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  undefined_map()->init_back_pointer(undefined_value());
2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  undefined_map()->set_instance_descriptors(empty_descriptor_array());
2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  null_map()->set_code_cache(empty_fixed_array());
2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  null_map()->set_dependent_code(DependentCode::cast(empty_fixed_array()));
2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  null_map()->init_back_pointer(undefined_value());
2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  null_map()->set_instance_descriptors(empty_descriptor_array());
2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  constant_pool_array_map()->set_code_cache(empty_fixed_array());
2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  constant_pool_array_map()->set_dependent_code(
2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DependentCode::cast(empty_fixed_array()));
2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  constant_pool_array_map()->init_back_pointer(undefined_value());
2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  constant_pool_array_map()->set_instance_descriptors(empty_descriptor_array());
2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Fix prototype object for existing maps.
2463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  meta_map()->set_prototype(null_value());
2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  meta_map()->set_constructor(null_value());
2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fixed_array_map()->set_prototype(null_value());
2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fixed_array_map()->set_constructor(null_value());
2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  undefined_map()->set_prototype(null_value());
2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  undefined_map()->set_constructor(null_value());
2471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  null_map()->set_prototype(null_value());
2473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  null_map()->set_constructor(null_value());
2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  constant_pool_array_map()->set_prototype(null_value());
2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  constant_pool_array_map()->set_constructor(null_value());
2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {  // Map allocation
2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ALLOCATE_MAP(instance_type, size, field_name)               \
2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {                                                                 \
2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Map* map;                                                       \
2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!AllocateMap((instance_type), size).To(&map)) return false; \
2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_##field_name##_map(map);                                    \
2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ALLOCATE_VARSIZE_MAP(instance_type, field_name) \
2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ALLOCATE_MAP(instance_type, kVariableSizeSentinel, field_name)
2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, fixed_cow_array)
2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(fixed_array_map() != fixed_cow_array_map());
2491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, scope_info)
2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(HEAP_NUMBER_TYPE, HeapNumber::kSize, heap_number)
2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(MUTABLE_HEAP_NUMBER_TYPE, HeapNumber::kSize,
2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 mutable_heap_number)
2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(SYMBOL_TYPE, Symbol::kSize, symbol)
2497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(FOREIGN_TYPE, Foreign::kSize, foreign)
2498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, the_hole);
2500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, boolean);
2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, uninitialized);
2502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, arguments_marker);
2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, no_interceptor_result_sentinel);
2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, exception);
2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, termination_exception);
2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (unsigned i = 0; i < arraysize(string_type_table); i++) {
2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const StringTypeTable& entry = string_type_table[i];
2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      {
2510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AllocationResult allocation = AllocateMap(entry.type, entry.size);
2511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (!allocation.To(&obj)) return false;
2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Mark cons string maps as unstable, because their objects can change
2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // maps during GC.
2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Map* map = Map::cast(obj);
2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (StringShape(entry.type).IsCons()) map->mark_unstable();
2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      roots_[entry.index] = map;
2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(STRING_TYPE, undetectable_string)
2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    undetectable_string_map()->set_is_undetectable();
2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(ONE_BYTE_STRING_TYPE, undetectable_one_byte_string);
2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    undetectable_one_byte_string_map()->set_is_undetectable();
2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(FIXED_DOUBLE_ARRAY_TYPE, fixed_double_array)
2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(BYTE_ARRAY_TYPE, byte_array)
2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(FREE_SPACE_TYPE, free_space)
2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ALLOCATE_EXTERNAL_ARRAY_MAP(Type, type, TYPE, ctype, size)        \
2531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ALLOCATE_MAP(EXTERNAL_##TYPE##_ARRAY_TYPE, ExternalArray::kAlignedSize, \
2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               external_##type##_array)
2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TYPED_ARRAYS(ALLOCATE_EXTERNAL_ARRAY_MAP)
2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ALLOCATE_EXTERNAL_ARRAY_MAP
2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ALLOCATE_FIXED_TYPED_ARRAY_MAP(Type, type, TYPE, ctype, size) \
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ALLOCATE_VARSIZE_MAP(FIXED_##TYPE##_ARRAY_TYPE, fixed_##type##_array)
2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TYPED_ARRAYS(ALLOCATE_FIXED_TYPED_ARRAY_MAP)
2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ALLOCATE_FIXED_TYPED_ARRAY_MAP
2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, sloppy_arguments_elements)
2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(CODE_TYPE, code)
2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(CELL_TYPE, Cell::kSize, cell)
2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(PROPERTY_CELL_TYPE, PropertyCell::kSize, global_property_cell)
2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(FILLER_TYPE, kPointerSize, one_pointer_filler)
2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(FILLER_TYPE, 2 * kPointerSize, two_pointer_filler)
2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (unsigned i = 0; i < arraysize(struct_table); i++) {
2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const StructTable& entry = struct_table[i];
2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Map* map;
2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!AllocateMap(entry.type, entry.size).To(&map)) return false;
2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      roots_[entry.index] = map;
2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, hash_table)
2561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, ordered_hash_table)
2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, function_context)
2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, catch_context)
2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, with_context)
2566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, block_context)
2567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, module_context)
2568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, global_context)
2569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, native_context)
2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    native_context_map()->set_dictionary_map(true);
2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    native_context_map()->set_visitor_id(
2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        StaticVisitorBase::kVisitNativeContext);
2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(SHARED_FUNCTION_INFO_TYPE, SharedFunctionInfo::kAlignedSize,
2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 shared_function_info)
2577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(JS_MESSAGE_OBJECT_TYPE, JSMessageObject::kSize, message_object)
2579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ALLOCATE_MAP(JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize, external)
2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    external_map()->set_is_extensible(false);
2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ALLOCATE_VARSIZE_MAP
2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ALLOCATE_MAP
2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {  // Empty arrays
2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ByteArray* byte_array;
2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!AllocateByteArray(0, TENURED).To(&byte_array)) return false;
2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      set_empty_byte_array(byte_array);
2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ALLOCATE_EMPTY_EXTERNAL_ARRAY(Type, type, TYPE, ctype, size)  \
2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {                                                                   \
2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalArray* obj;                                               \
2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!AllocateEmptyExternalArray(kExternal##Type##Array).To(&obj)) \
2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return false;                                                   \
2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_empty_external_##type##_array(obj);                           \
2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TYPED_ARRAYS(ALLOCATE_EMPTY_EXTERNAL_ARRAY)
2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ALLOCATE_EMPTY_EXTERNAL_ARRAY
2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ALLOCATE_EMPTY_FIXED_TYPED_ARRAY(Type, type, TYPE, ctype, size) \
2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {                                                                     \
2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FixedTypedArrayBase* obj;                                           \
2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!AllocateEmptyFixedTypedArray(kExternal##Type##Array).To(&obj)) \
2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return false;                                                     \
2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_empty_fixed_##type##_array(obj);                                \
2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TYPED_ARRAYS(ALLOCATE_EMPTY_FIXED_TYPED_ARRAY)
2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ALLOCATE_EMPTY_FIXED_TYPED_ARRAY
2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!InNewSpace(empty_fixed_array()));
2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateHeapNumber(double value, MutableMode mode,
2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          PretenureFlag pretenure) {
2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Statically ensure that it is safe to allocate heap numbers in paged
2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // spaces.
2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = HeapNumber::kSize;
2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxRegularHeapObjectSize);
2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
2629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
2630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRaw(size, space, OLD_DATA_SPACE);
2631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&result)) return allocation;
2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Map* map = mode == MUTABLE ? mutable_heap_number_map() : heap_number_map();
2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject::cast(result)->set_map_no_write_barrier(map);
2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapNumber::cast(result)->set_value(value);
2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateCell(Object* value) {
2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = Cell::kSize;
2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(Cell::kSize <= Page::kMaxRegularHeapObjectSize);
2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRaw(size, CELL_SPACE, CELL_SPACE);
2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&result)) return allocation;
2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_map_no_write_barrier(cell_map());
2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Cell::cast(result)->set_value(value);
2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocatePropertyCell() {
2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = PropertyCell::kSize;
2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(PropertyCell::kSize <= Page::kMaxRegularHeapObjectSize);
2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationResult allocation =
2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocateRaw(size, PROPERTY_CELL_SPACE, PROPERTY_CELL_SPACE);
2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!allocation.To(&result)) return allocation;
2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_map_no_write_barrier(global_property_cell_map());
2666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PropertyCell* cell = PropertyCell::cast(result);
2667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cell->set_dependent_code(DependentCode::cast(empty_fixed_array()),
2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           SKIP_WRITE_BARRIER);
2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cell->set_value(the_hole_value());
2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cell->set_type(HeapType::None());
2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::CreateApiObjects() {
2676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate());
2677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
2678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Map> new_neander_map =
2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Don't use Smi-only elements optimizations for objects with the neander
2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // map. There are too many cases where element values are set directly with a
2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // bottleneck to trap the Smi-only -> fast elements transition, and there
2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // appears to be no benefit for optimize this case.
2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_neander_map->set_elements_kind(TERMINAL_FAST_ELEMENTS_KIND);
2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_neander_map(*new_neander_map);
2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSObject> listeners = factory->NewNeanderObject();
2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FixedArray> elements = factory->NewFixedArray(2);
2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  elements->set(0, Smi::FromInt(0));
2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  listeners->set_elements(*elements);
2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_message_listeners(*listeners);
2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::CreateJSEntryStub() {
2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSEntryStub stub(isolate(), StackFrame::ENTRY);
2698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_js_entry_code(*stub.GetCode());
2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::CreateJSConstructEntryStub() {
2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSEntryStub stub(isolate(), StackFrame::ENTRY_CONSTRUCT);
2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_js_construct_entry_code(*stub.GetCode());
2705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::CreateFixedStubs() {
2709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Here we create roots for fixed stubs. They are needed at GC
2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for cooking and uncooking (check out frames.cc).
2711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The eliminates the need for doing dictionary lookup in the
2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // stub cache for these stubs.
2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate());
2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create stubs that should be there, so we don't unexpectedly have to
2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // create them if we need them during the creation of another stub.
2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Stub creation mixes raw pointers and handles in an unsafe manner so
2718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // we cannot create stubs while we are creating stubs.
2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeStub::GenerateStubsAheadOfTime(isolate());
2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // MacroAssembler::Abort calls (usually enabled with --debug-code) depend on
2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // CEntryStub, so we need to call GenerateStubsAheadOfTime before JSEntryStub
2723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // is created.
2724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // gcc-4.4 has problem generating correct code of following snippet:
2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // {  JSEntryStub stub;
2727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //    js_entry_code_ = *stub.GetCode();
2728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // }
2729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // {  JSConstructEntryStub stub;
2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //    js_construct_entry_code_ = *stub.GetCode();
2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // }
2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // To workaround the problem, make separate functions without inlining.
2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap::CreateJSEntryStub();
2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap::CreateJSConstructEntryStub();
2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::CreateInitialObjects() {
2739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate());
2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
2741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The -0 value must be set before NewNumber works.
2743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_minus_zero_value(*factory->NewHeapNumber(-0.0, IMMUTABLE, TENURED));
2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(std::signbit(minus_zero_value()->Number()) != 0);
2745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_nan_value(
2747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *factory->NewHeapNumber(base::OS::nan_value(), IMMUTABLE, TENURED));
2748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_infinity_value(*factory->NewHeapNumber(V8_INFINITY, IMMUTABLE, TENURED));
2749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The hole has not been created yet, but we want to put something
2751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // predictable in the gaps in the string table, so lets make that Smi zero.
2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_the_hole_value(reinterpret_cast<Oddball*>(Smi::FromInt(0)));
2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate initial string table.
2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_string_table(*StringTable::New(isolate(), kInitialStringTableSize));
2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Finish initializing oddballs after creating the string table.
2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Oddball::Initialize(isolate(), factory->undefined_value(), "undefined",
2759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      factory->nan_value(), Oddball::kUndefined);
2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize the null_value.
2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Oddball::Initialize(isolate(), factory->null_value(), "null",
2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      handle(Smi::FromInt(0), isolate()), Oddball::kNull);
2764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_true_value(*factory->NewOddball(factory->boolean_map(), "true",
2766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      handle(Smi::FromInt(1), isolate()),
2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Oddball::kTrue));
2768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_false_value(*factory->NewOddball(factory->boolean_map(), "false",
2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       handle(Smi::FromInt(0), isolate()),
2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Oddball::kFalse));
2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_the_hole_value(*factory->NewOddball(factory->the_hole_map(), "hole",
2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          handle(Smi::FromInt(-1), isolate()),
2775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Oddball::kTheHole));
2776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_uninitialized_value(*factory->NewOddball(
2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      factory->uninitialized_map(), "uninitialized",
2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      handle(Smi::FromInt(-1), isolate()), Oddball::kUninitialized));
2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_arguments_marker(*factory->NewOddball(
2782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      factory->arguments_marker_map(), "arguments_marker",
2783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      handle(Smi::FromInt(-4), isolate()), Oddball::kArgumentMarker));
2784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_no_interceptor_result_sentinel(*factory->NewOddball(
2786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      factory->no_interceptor_result_sentinel_map(),
2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      "no_interceptor_result_sentinel", handle(Smi::FromInt(-2), isolate()),
2788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Oddball::kOther));
2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_termination_exception(*factory->NewOddball(
2791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      factory->termination_exception_map(), "termination_exception",
2792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      handle(Smi::FromInt(-3), isolate()), Oddball::kOther));
2793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_exception(*factory->NewOddball(factory->exception_map(), "exception",
2795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     handle(Smi::FromInt(-5), isolate()),
2796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Oddball::kException));
2797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (unsigned i = 0; i < arraysize(constant_string_table); i++) {
2799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<String> str =
2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        factory->InternalizeUtf8String(constant_string_table[i].contents);
2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    roots_[constant_string_table[i].index] = *str;
2802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate the hidden string which is used to identify the hidden properties
2805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // in JSObjects. The hash code has a special value so that it will not match
2806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the empty string when searching for the property. It cannot be part of the
2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // loop above because it needs to be allocated manually with the special
2808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // hash code in place. The hash code for the hidden_string is zero to ensure
2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // that it will always be at the first entry in property descriptors.
2810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  hidden_string_ = *factory->NewOneByteInternalizedString(
2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      OneByteVector("", 0), String::kEmptyStringHash);
2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create the code_stubs dictionary. The initial size is set to avoid
2814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // expanding the dictionary during bootstrapping.
2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_code_stubs(*UnseededNumberDictionary::New(isolate(), 128));
2816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create the non_monomorphic_cache used in stub-cache.cc. The initial size
2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // is set to avoid expanding the dictionary during bootstrapping.
2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_non_monomorphic_cache(*UnseededNumberDictionary::New(isolate(), 64));
2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_polymorphic_code_cache(PolymorphicCodeCache::cast(
2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *factory->NewStruct(POLYMORPHIC_CODE_CACHE_TYPE)));
2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_instanceof_cache_function(Smi::FromInt(0));
2825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_instanceof_cache_map(Smi::FromInt(0));
2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_instanceof_cache_answer(Smi::FromInt(0));
2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CreateFixedStubs();
2829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate the dictionary of intrinsic function names.
2831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<NameDictionary> intrinsic_names =
2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      NameDictionary::New(isolate(), Runtime::kNumFunctions, TENURED);
2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Runtime::InitializeIntrinsicFunctionNames(isolate(), intrinsic_names);
2834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_intrinsic_function_names(*intrinsic_names);
2835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_number_string_cache(
2837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *factory->NewFixedArray(kInitialNumberStringCacheSize * 2, TENURED));
2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate cache for single character one byte strings.
2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_single_character_string_cache(
2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *factory->NewFixedArray(String::kMaxOneByteCharCode + 1, TENURED));
2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate cache for string split and regexp-multiple.
2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_string_split_cache(*factory->NewFixedArray(
2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RegExpResultsCache::kRegExpResultsCacheSize, TENURED));
2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_regexp_multiple_cache(*factory->NewFixedArray(
2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RegExpResultsCache::kRegExpResultsCacheSize, TENURED));
2848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate cache for external strings pointing to native source code.
2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_natives_source_cache(
2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *factory->NewFixedArray(Natives::GetBuiltinsCount()));
2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_undefined_cell(*factory->NewCell(factory->undefined_value()));
2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The symbol registry is initialized lazily.
2856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_symbol_registry(undefined_value());
2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate object to hold object observation state.
2859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_observation_state(*factory->NewJSObjectFromMap(
2860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize)));
2861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Microtask queue uses the empty fixed array as a sentinel for "empty".
2863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Number of queued microtasks stored in Isolate::pending_microtask_count().
2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_microtask_queue(empty_fixed_array());
2865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_detailed_stack_trace_symbol(*factory->NewPrivateOwnSymbol());
2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_elements_transition_symbol(*factory->NewPrivateOwnSymbol());
2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_frozen_symbol(*factory->NewPrivateOwnSymbol());
2869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_megamorphic_symbol(*factory->NewPrivateOwnSymbol());
2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_premonomorphic_symbol(*factory->NewPrivateOwnSymbol());
2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_generic_symbol(*factory->NewPrivateOwnSymbol());
2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_nonexistent_symbol(*factory->NewPrivateOwnSymbol());
2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_normal_ic_symbol(*factory->NewPrivateOwnSymbol());
2874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_observed_symbol(*factory->NewPrivateOwnSymbol());
2875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_stack_trace_symbol(*factory->NewPrivateOwnSymbol());
2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_uninitialized_symbol(*factory->NewPrivateOwnSymbol());
2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_home_object_symbol(*factory->NewPrivateOwnSymbol());
2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<SeededNumberDictionary> slow_element_dictionary =
2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SeededNumberDictionary::New(isolate(), 0, TENURED);
2881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  slow_element_dictionary->set_requires_slow_elements();
2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_empty_slow_element_dictionary(*slow_element_dictionary);
2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_materialized_objects(*factory->NewFixedArray(0, TENURED));
2885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Handling of script id generation is in Factory::NewScript.
2887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_last_script_id(Smi::FromInt(v8::UnboundScript::kNoScriptId));
2888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_allocation_sites_scratchpad(
2890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *factory->NewFixedArray(kAllocationSiteScratchpadSize, TENURED));
2891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InitializeAllocationSitesScratchpad();
2892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize keyed lookup cache.
2894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->keyed_lookup_cache()->Clear();
2895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize context slot cache.
2897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->context_slot_cache()->Clear();
2898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize descriptor cache.
2900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->descriptor_lookup_cache()->Clear();
2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize compilation cache.
2903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->compilation_cache()->Clear();
2904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
2908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RootListIndex writable_roots[] = {
2909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStoreBufferTopRootIndex,
2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStackLimitRootIndex,
2911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kNumberStringCacheRootIndex,
2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kInstanceofCacheFunctionRootIndex,
2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kInstanceofCacheMapRootIndex,
2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kInstanceofCacheAnswerRootIndex,
2915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kCodeStubsRootIndex,
2916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kNonMonomorphicCacheRootIndex,
2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kPolymorphicCodeCacheRootIndex,
2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kLastScriptIdRootIndex,
2919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kEmptyScriptRootIndex,
2920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kRealStackLimitRootIndex,
2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kArgumentsAdaptorDeoptPCOffsetRootIndex,
2922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kConstructStubDeoptPCOffsetRootIndex,
2923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kGetterStubDeoptPCOffsetRootIndex,
2924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kSetterStubDeoptPCOffsetRootIndex,
2925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kStringTableRootIndex,
2926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
2927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (unsigned int i = 0; i < arraysize(writable_roots); i++) {
2929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (root_index == writable_roots[i]) return true;
2930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return false;
2932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::RootCanBeTreatedAsConstant(RootListIndex root_index) {
2936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return !RootCanBeWrittenAfterInitialization(root_index) &&
2937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         !InNewSpace(roots_array_start()[root_index]);
2938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochObject* RegExpResultsCache::Lookup(Heap* heap, String* key_string,
2942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Object* key_pattern, ResultsCacheType type) {
2943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedArray* cache;
2944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!key_string->IsInternalizedString()) return Smi::FromInt(0);
2945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (type == STRING_SPLIT_SUBSTRINGS) {
2946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(key_pattern->IsString());
2947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!key_pattern->IsInternalizedString()) return Smi::FromInt(0);
2948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cache = heap->string_split_cache();
2949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(type == REGEXP_MULTIPLE_INDICES);
2951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(key_pattern->IsFixedArray());
2952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cache = heap->regexp_multiple_cache();
2953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t hash = key_string->Hash();
2956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t index = ((hash & (kRegExpResultsCacheSize - 1)) &
2957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    ~(kArrayEntriesPerCacheEntry - 1));
2958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cache->get(index + kStringOffset) == key_string &&
2959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cache->get(index + kPatternOffset) == key_pattern) {
2960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return cache->get(index + kArrayOffset);
2961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  index =
2963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ((index + kArrayEntriesPerCacheEntry) & (kRegExpResultsCacheSize - 1));
2964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cache->get(index + kStringOffset) == key_string &&
2965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cache->get(index + kPatternOffset) == key_pattern) {
2966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return cache->get(index + kArrayOffset);
2967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Smi::FromInt(0);
2969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RegExpResultsCache::Enter(Isolate* isolate, Handle<String> key_string,
2973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Handle<Object> key_pattern,
2974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Handle<FixedArray> value_array,
2975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               ResultsCacheType type) {
2976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate->factory();
2977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FixedArray> cache;
2978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!key_string->IsInternalizedString()) return;
2979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (type == STRING_SPLIT_SUBSTRINGS) {
2980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(key_pattern->IsString());
2981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!key_pattern->IsInternalizedString()) return;
2982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cache = factory->string_split_cache();
2983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(type == REGEXP_MULTIPLE_INDICES);
2985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(key_pattern->IsFixedArray());
2986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cache = factory->regexp_multiple_cache();
2987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t hash = key_string->Hash();
2990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t index = ((hash & (kRegExpResultsCacheSize - 1)) &
2991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    ~(kArrayEntriesPerCacheEntry - 1));
2992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cache->get(index + kStringOffset) == Smi::FromInt(0)) {
2993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cache->set(index + kStringOffset, *key_string);
2994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cache->set(index + kPatternOffset, *key_pattern);
2995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cache->set(index + kArrayOffset, *value_array);
2996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t index2 =
2998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ((index + kArrayEntriesPerCacheEntry) & (kRegExpResultsCacheSize - 1));
2999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (cache->get(index2 + kStringOffset) == Smi::FromInt(0)) {
3000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cache->set(index2 + kStringOffset, *key_string);
3001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cache->set(index2 + kPatternOffset, *key_pattern);
3002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cache->set(index2 + kArrayOffset, *value_array);
3003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
3004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cache->set(index2 + kStringOffset, Smi::FromInt(0));
3005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cache->set(index2 + kPatternOffset, Smi::FromInt(0));
3006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cache->set(index2 + kArrayOffset, Smi::FromInt(0));
3007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cache->set(index + kStringOffset, *key_string);
3008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cache->set(index + kPatternOffset, *key_pattern);
3009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cache->set(index + kArrayOffset, *value_array);
3010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the array is a reasonably short list of substrings, convert it into a
3013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // list of internalized strings.
3014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (type == STRING_SPLIT_SUBSTRINGS && value_array->length() < 100) {
3015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < value_array->length(); i++) {
3016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<String> str(String::cast(value_array->get(i)), isolate);
3017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<String> internalized_str = factory->InternalizeString(str);
3018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      value_array->set(i, *internalized_str);
3019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Convert backing store to a copy-on-write array.
3022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  value_array->set_map_no_write_barrier(*factory->fixed_cow_array_map());
3023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RegExpResultsCache::Clear(FixedArray* cache) {
3027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < kRegExpResultsCacheSize; i++) {
3028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cache->set(i, Smi::FromInt(0));
3029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint Heap::FullSizeNumberStringCacheLength() {
3034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compute the size of the number string cache based on the max newspace size.
3035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The number string cache has a minimum size based on twice the initial cache
3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // size to ensure that it is bigger after being made 'full size'.
3037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int number_string_cache_size = max_semi_space_size_ / 512;
3038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  number_string_cache_size = Max(kInitialNumberStringCacheSize * 2,
3039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Min(0x4000, number_string_cache_size));
3040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // There is a string and a number per entry so the length is twice the number
3041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // of entries.
3042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return number_string_cache_size * 2;
3043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::FlushNumberStringCache() {
3047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Flush the number to string cache.
3048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int len = number_string_cache()->length();
3049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < len; i++) {
3050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    number_string_cache()->set_undefined(i);
3051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::FlushAllocationSitesScratchpad() {
3056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < allocation_sites_scratchpad_length_; i++) {
3057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    allocation_sites_scratchpad()->set_undefined(i);
3058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  allocation_sites_scratchpad_length_ = 0;
3060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::InitializeAllocationSitesScratchpad() {
3064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(allocation_sites_scratchpad()->length() ==
3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         kAllocationSiteScratchpadSize);
3066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < kAllocationSiteScratchpadSize; i++) {
3067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    allocation_sites_scratchpad()->set_undefined(i);
3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::AddAllocationSiteToScratchpad(AllocationSite* site,
3073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         ScratchpadSlotMode mode) {
3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (allocation_sites_scratchpad_length_ < kAllocationSiteScratchpadSize) {
3075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We cannot use the normal write-barrier because slots need to be
3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // recorded with non-incremental marking as well. We have to explicitly
3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // record the slot to take evacuation candidates into account.
3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    allocation_sites_scratchpad()->set(allocation_sites_scratchpad_length_,
3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       site, SKIP_WRITE_BARRIER);
3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object** slot = allocation_sites_scratchpad()->RawFieldOfElementAt(
3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        allocation_sites_scratchpad_length_);
3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (mode == RECORD_SCRATCHPAD_SLOT) {
3084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // We need to allow slots buffer overflow here since the evacuation
3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // candidates are not part of the global list of old space pages and
3086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // releasing an evacuation candidate due to a slots buffer overflow
3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // results in lost pages.
3088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mark_compact_collector()->RecordSlot(slot, slot, *slot,
3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           SlotsBuffer::IGNORE_OVERFLOW);
3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    allocation_sites_scratchpad_length_++;
3092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMap* Heap::MapForExternalArrayType(ExternalArrayType array_type) {
3097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Map::cast(roots_[RootIndexForExternalArrayType(array_type)]);
3098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeap::RootListIndex Heap::RootIndexForExternalArrayType(
3102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalArrayType array_type) {
3103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (array_type) {
3104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ARRAY_TYPE_TO_ROOT_INDEX(Type, type, TYPE, ctype, size) \
3105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  case kExternal##Type##Array:                                  \
3106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return kExternal##Type##ArrayMapRootIndex;
3107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TYPED_ARRAYS(ARRAY_TYPE_TO_ROOT_INDEX)
3109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ARRAY_TYPE_TO_ROOT_INDEX
3110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
3113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return kUndefinedValueRootIndex;
3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMap* Heap::MapForFixedTypedArray(ExternalArrayType array_type) {
3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Map::cast(roots_[RootIndexForFixedTypedArray(array_type)]);
3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeap::RootListIndex Heap::RootIndexForFixedTypedArray(
3124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalArrayType array_type) {
3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (array_type) {
3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ARRAY_TYPE_TO_ROOT_INDEX(Type, type, TYPE, ctype, size) \
3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  case kExternal##Type##Array:                                  \
3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return kFixed##Type##ArrayMapRootIndex;
3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TYPED_ARRAYS(ARRAY_TYPE_TO_ROOT_INDEX)
3131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ARRAY_TYPE_TO_ROOT_INDEX
3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
3135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return kUndefinedValueRootIndex;
3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeap::RootListIndex Heap::RootIndexForEmptyExternalArray(
3141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ElementsKind elementsKind) {
3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (elementsKind) {
3143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ELEMENT_KIND_TO_ROOT_INDEX(Type, type, TYPE, ctype, size) \
3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  case EXTERNAL_##TYPE##_ELEMENTS:                                \
3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return kEmptyExternal##Type##ArrayRootIndex;
3146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TYPED_ARRAYS(ELEMENT_KIND_TO_ROOT_INDEX)
3148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ELEMENT_KIND_TO_ROOT_INDEX
3149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
3151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
3152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return kUndefinedValueRootIndex;
3153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeap::RootListIndex Heap::RootIndexForEmptyFixedTypedArray(
3158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ElementsKind elementsKind) {
3159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (elementsKind) {
3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ELEMENT_KIND_TO_ROOT_INDEX(Type, type, TYPE, ctype, size) \
3161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  case TYPE##_ELEMENTS:                                           \
3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return kEmptyFixed##Type##ArrayRootIndex;
3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TYPED_ARRAYS(ELEMENT_KIND_TO_ROOT_INDEX)
3165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ELEMENT_KIND_TO_ROOT_INDEX
3166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
3167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
3168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return kUndefinedValueRootIndex;
3169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochExternalArray* Heap::EmptyExternalArrayForMap(Map* map) {
3174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return ExternalArray::cast(
3175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      roots_[RootIndexForEmptyExternalArray(map->elements_kind())]);
3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochFixedTypedArrayBase* Heap::EmptyFixedTypedArrayForMap(Map* map) {
3180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return FixedTypedArrayBase::cast(
3181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      roots_[RootIndexForEmptyFixedTypedArray(map->elements_kind())]);
3182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateForeign(Address address,
3186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       PretenureFlag pretenure) {
3187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Statically ensure that it is safe to allocate foreigns in paged spaces.
3188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(Foreign::kSize <= Page::kMaxRegularHeapObjectSize);
3189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
3190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Foreign* result;
3191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationResult allocation = Allocate(foreign_map(), space);
3192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!allocation.To(&result)) return allocation;
3193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_foreign_address(address);
3194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
3195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateByteArray(int length, PretenureFlag pretenure) {
3199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (length < 0 || length > ByteArray::kMaxLength) {
3200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", true);
3201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = ByteArray::SizeFor(length);
3203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
3204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
3205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRaw(size, space, OLD_DATA_SPACE);
3207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&result)) return allocation;
3208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_map_no_write_barrier(byte_array_map());
3211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ByteArray::cast(result)->set_length(length);
3212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
3213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::CreateFillerObjectAt(Address addr, int size) {
3217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (size == 0) return;
3218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* filler = HeapObject::FromAddress(addr);
3219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (size == kPointerSize) {
3220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    filler->set_map_no_write_barrier(one_pointer_filler_map());
3221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (size == 2 * kPointerSize) {
3222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    filler->set_map_no_write_barrier(two_pointer_filler_map());
3223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    filler->set_map_no_write_barrier(free_space_map());
3225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FreeSpace::cast(filler)->set_size(size);
3226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::CanMoveObjectStart(HeapObject* object) {
3231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address address = object->address();
3232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_in_old_pointer_space = InOldPointerSpace(address);
3233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_in_old_data_space = InOldDataSpace(address);
3234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (lo_space()->Contains(object)) return false;
3236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Page* page = Page::FromAddress(address);
3238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We can move the object start if:
3239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (1) the object is not in old pointer or old data space,
3240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (2) the page of the object was already swept,
3241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (3) the page was already concurrently swept. This case is an optimization
3242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for concurrent sweeping. The WasSwept predicate for concurrently swept
3243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // pages is set after sweeping all pages.
3244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (!is_in_old_pointer_space && !is_in_old_data_space) ||
3245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         page->WasSwept() || page->SweepingCompleted();
3246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::AdjustLiveBytes(Address address, int by, InvocationMode mode) {
3250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (incremental_marking()->IsMarking() &&
3251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Marking::IsBlack(Marking::MarkBitFrom(address))) {
3252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (mode == FROM_GC) {
3253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MemoryChunk::IncrementLiveBytesFromGC(address, by);
3254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
3255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MemoryChunk::IncrementLiveBytesFromMutator(address, by);
3256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochFixedArrayBase* Heap::LeftTrimFixedArray(FixedArrayBase* object,
3262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         int elements_to_trim) {
3263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int element_size = object->IsFixedArray() ? kPointerSize : kDoubleSize;
3264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int bytes_to_trim = elements_to_trim * element_size;
3265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Map* map = object->map();
3266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For now this trick is only applied to objects in new and paged space.
3268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // In large object space the object's start must coincide with chunk
3269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // and thus the trick is just not applicable.
3270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!lo_space()->Contains(object));
3271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(object->map() != fixed_cow_array_map());
3272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FixedArrayBase::kMapOffset == 0);
3274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FixedArrayBase::kLengthOffset == kPointerSize);
3275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FixedArrayBase::kHeaderSize == 2 * kPointerSize);
3276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int len = object->length();
3278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(elements_to_trim <= len);
3279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate location of new array start.
3281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address new_start = object->address() + bytes_to_trim;
3282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Technically in new space this write might be omitted (except for
3284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // debug mode which iterates through the heap), but to play safer
3285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // we still do it.
3286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CreateFillerObjectAt(object->address(), bytes_to_trim);
3287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize header of the trimmed array. Since left trimming is only
3289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // performed on pages which are not concurrently swept creating a filler
3290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object does not require synchronization.
3291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(CanMoveObjectStart(object));
3292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object** former_start = HeapObject::RawField(object, 0);
3293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int new_start_index = elements_to_trim * (element_size / kPointerSize);
3294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  former_start[new_start_index] = map;
3295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  former_start[new_start_index + 1] = Smi::FromInt(len - elements_to_trim);
3296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedArrayBase* new_object =
3297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FixedArrayBase::cast(HeapObject::FromAddress(new_start));
3298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Maintain consistency of live bytes during incremental marking
3300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  marking()->TransferMark(object->address(), new_start);
3301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AdjustLiveBytes(new_start, -bytes_to_trim, Heap::FROM_MUTATOR);
3302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Notify the heap profiler of change in object layout.
3304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OnMoveEvent(new_object, object, new_object->Size());
3305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return new_object;
3306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Force instantiation of templatized method.
3310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate
3311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::RightTrimFixedArray<Heap::FROM_GC>(FixedArrayBase*, int);
3312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate
3313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::RightTrimFixedArray<Heap::FROM_MUTATOR>(FixedArrayBase*, int);
3314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<Heap::InvocationMode mode>
3317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::RightTrimFixedArray(FixedArrayBase* object, int elements_to_trim) {
3318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int element_size = object->IsFixedArray() ? kPointerSize : kDoubleSize;
3319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int bytes_to_trim = elements_to_trim * element_size;
3320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For now this trick is only applied to objects in new and paged space.
3322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(object->map() != fixed_cow_array_map());
3323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int len = object->length();
3325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(elements_to_trim < len);
3326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate location of new array end.
3328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address new_end = object->address() + object->Size() - bytes_to_trim;
3329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Technically in new space this write might be omitted (except for
3331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // debug mode which iterates through the heap), but to play safer
3332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // we still do it.
3333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We do not create a filler for objects in large object space.
3334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(hpayer): We should shrink the large object page if the size
3335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // of the object changed significantly.
3336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!lo_space()->Contains(object)) {
3337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateFillerObjectAt(new_end, bytes_to_trim);
3338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize header of the trimmed array. We are storing the new length
3341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // using release store after creating a filler for the left-over space to
3342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // avoid races with the sweeper thread.
3343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object->synchronized_set_length(len - elements_to_trim);
3344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Maintain consistency of live bytes during incremental marking
3346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AdjustLiveBytes(object->address(), -bytes_to_trim, mode);
3347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Notify the heap profiler of change in object layout. The array may not be
3349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // moved during GC, and size has to be adjusted nevertheless.
3350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapProfiler* profiler = isolate()->heap_profiler();
3351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (profiler->is_tracking_allocations()) {
3352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    profiler->UpdateObjectSizeEvent(object->address(), object->Size());
3353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateExternalArray(int length,
3358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             ExternalArrayType array_type,
3359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             void* external_pointer,
3360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             PretenureFlag pretenure) {
3361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = ExternalArray::kAlignedSize;
3362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
3363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
3364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRaw(size, space, OLD_DATA_SPACE);
3366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&result)) return allocation;
3367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_map_no_write_barrier(MapForExternalArrayType(array_type));
3370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArray::cast(result)->set_length(length);
3371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalArray::cast(result)->set_external_pointer(external_pointer);
3372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
3373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ForFixedTypedArray(ExternalArrayType array_type, int* element_size,
3376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               ElementsKind* element_kind) {
3377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (array_type) {
3378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
3379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  case kExternal##Type##Array:                          \
3380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *element_size = size;                               \
3381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *element_kind = TYPE##_ELEMENTS;                    \
3382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
3383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TYPED_ARRAYS(TYPED_ARRAY_CASE)
3385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef TYPED_ARRAY_CASE
3386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
3388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *element_size = 0;               // Bogus
3389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *element_kind = UINT8_ELEMENTS;  // Bogus
3390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
3391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateFixedTypedArray(int length,
3396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               ExternalArrayType array_type,
3397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               PretenureFlag pretenure) {
3398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int element_size;
3399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ElementsKind elements_kind;
3400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ForFixedTypedArray(array_type, &element_size, &elements_kind);
3401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = OBJECT_POINTER_ALIGN(length * element_size +
3402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  FixedTypedArrayBase::kDataOffset);
3403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_HOST_ARCH_64_BIT
3404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (array_type == kExternalFloat64Array) {
3405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    size += kPointerSize;
3406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
3408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
3409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* object;
3411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationResult allocation = AllocateRaw(size, space, OLD_DATA_SPACE);
3412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!allocation.To(&object)) return allocation;
3413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (array_type == kExternalFloat64Array) {
3415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object = EnsureDoubleAligned(this, object, size);
3416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object->set_map(MapForFixedTypedArray(array_type));
3419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedTypedArrayBase* elements = FixedTypedArrayBase::cast(object);
3420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  elements->set_length(length);
3421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  memset(elements->DataPtr(), 0, elements->DataSize());
3422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return elements;
3423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateCode(int object_size, bool immovable) {
3427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsAligned(static_cast<intptr_t>(object_size), kCodeAlignment));
3428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationResult allocation =
3429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocateRaw(object_size, CODE_SPACE, CODE_SPACE);
3430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
3432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!allocation.To(&result)) return allocation;
3433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (immovable) {
3435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address address = result->address();
3436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Code objects which should stay at a fixed address are allocated either
3437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // in the first page of code space (objects on the first page of each space
3438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // are never moved) or in large object space.
3439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!code_space_->FirstPage()->Contains(address) &&
3440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        MemoryChunk::FromAddress(address)->owner()->identity() != LO_SPACE) {
3441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Discard the first code allocation, which was on a page where it could
3442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // be moved.
3443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CreateFillerObjectAt(result->address(), object_size);
3444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      allocation = lo_space_->AllocateRaw(object_size, EXECUTABLE);
3445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!allocation.To(&result)) return allocation;
3446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      OnAllocationEvent(result, object_size);
3447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_map_no_write_barrier(code_map());
3451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Code* code = Code::cast(result);
3452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(isolate_->code_range() == NULL || !isolate_->code_range()->valid() ||
3453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         isolate_->code_range()->contains(code->address()));
3454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code->set_gc_metadata(Smi::FromInt(0));
3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code->set_ic_age(global_ic_age_);
3456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return code;
3457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::CopyCode(Code* code) {
3461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationResult allocation;
3462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* new_constant_pool;
3463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_enable_ool_constant_pool &&
3464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      code->constant_pool() != empty_constant_pool_array()) {
3465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Copy the constant pool, since edits to the copied code may modify
3466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the constant pool.
3467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    allocation = CopyConstantPoolArray(code->constant_pool());
3468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&new_constant_pool)) return allocation;
3469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    new_constant_pool = empty_constant_pool_array();
3471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
3474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate an object the same size as the code object.
3475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int obj_size = code->Size();
3476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  allocation = AllocateRaw(obj_size, CODE_SPACE, CODE_SPACE);
3477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!allocation.To(&result)) return allocation;
3478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy code object.
3480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address old_addr = code->address();
3481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address new_addr = result->address();
3482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CopyBlock(new_addr, old_addr, obj_size);
3483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Code* new_code = Code::cast(result);
3484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update the constant pool.
3486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_code->set_constant_pool(new_constant_pool);
3487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Relocate the copy.
3489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(isolate_->code_range() == NULL || !isolate_->code_range()->valid() ||
3490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         isolate_->code_range()->contains(code->address()));
3491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_code->Relocate(new_addr - old_addr);
3492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return new_code;
3493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::CopyCode(Code* code, Vector<byte> reloc_info) {
3497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate ByteArray and ConstantPoolArray before the Code object, so that we
3498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // do not risk leaving uninitialized Code object (and breaking the heap).
3499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ByteArray* reloc_info_array;
3500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation =
3502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AllocateByteArray(reloc_info.length(), TENURED);
3503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&reloc_info_array)) return allocation;
3504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* new_constant_pool;
3506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_enable_ool_constant_pool &&
3507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      code->constant_pool() != empty_constant_pool_array()) {
3508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Copy the constant pool, since edits to the copied code may modify
3509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the constant pool.
3510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = CopyConstantPoolArray(code->constant_pool());
3511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&new_constant_pool)) return allocation;
3512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    new_constant_pool = empty_constant_pool_array();
3514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int new_body_size = RoundUp(code->instruction_size(), kObjectAlignment);
3517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int new_obj_size = Code::SizeFor(new_body_size);
3519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address old_addr = code->address();
3521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t relocation_offset =
3523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<size_t>(code->instruction_end() - old_addr);
3524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
3526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationResult allocation =
3527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocateRaw(new_obj_size, CODE_SPACE, CODE_SPACE);
3528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!allocation.To(&result)) return allocation;
3529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy code object.
3531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address new_addr = result->address();
3532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy header and instructions.
3534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CopyBytes(new_addr, old_addr, relocation_offset);
3535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Code* new_code = Code::cast(result);
3537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_code->set_relocation_info(reloc_info_array);
3538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update constant pool.
3540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_code->set_constant_pool(new_constant_pool);
3541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy patched rinfo.
3543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CopyBytes(new_code->relocation_start(), reloc_info.start(),
3544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            static_cast<size_t>(reloc_info.length()));
3545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Relocate the copy.
3547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(isolate_->code_range() == NULL || !isolate_->code_range()->valid() ||
3548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         isolate_->code_range()->contains(code->address()));
3549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_code->Relocate(new_addr - old_addr);
3550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
3552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_verify_heap) code->ObjectVerify();
3553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
3554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return new_code;
3555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::InitializeAllocationMemento(AllocationMemento* memento,
3559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       AllocationSite* allocation_site) {
3560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  memento->set_map_no_write_barrier(allocation_memento_map());
3561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(allocation_site->map() == allocation_site_map());
3562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  memento->set_allocation_site(allocation_site, SKIP_WRITE_BARRIER);
3563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_allocation_site_pretenuring) {
3564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    allocation_site->IncrementMementoCreateCount();
3565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::Allocate(Map* map, AllocationSpace space,
3570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                AllocationSite* allocation_site) {
3571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(gc_state_ == NOT_IN_GC);
3572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(map->instance_type() != MAP_TYPE);
3573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If allocation failures are disallowed, we may allocate in a different
3574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // space when new space is full and the object is not a large object.
3575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace retry_space =
3576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (space != NEW_SPACE) ? space : TargetSpaceId(map->instance_type());
3577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = map->instance_size();
3578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (allocation_site != NULL) {
3579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    size += AllocationMemento::kSize;
3580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
3582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationResult allocation = AllocateRaw(size, space, retry_space);
3583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!allocation.To(&result)) return allocation;
3584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // No need for write barrier since object is white and map is in old space.
3585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_map_no_write_barrier(map);
3586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (allocation_site != NULL) {
3587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>(
3588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        reinterpret_cast<Address>(result) + map->instance_size());
3589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InitializeAllocationMemento(alloc_memento, allocation_site);
3590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
3592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::InitializeJSObjectFromMap(JSObject* obj, FixedArray* properties,
3596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Map* map) {
3597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->set_properties(properties);
3598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->initialize_elements();
3599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(1240798): Initialize the object's body using valid initial values
3600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // according to the object's initial map.  For example, if the map's
3601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // instance type is JS_ARRAY_TYPE, the length field should be initialized
3602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to a number (e.g. Smi::FromInt(0)) and the elements initialized to a
3603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // fixed array (e.g. Heap::empty_fixed_array()).  Currently, the object
3604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // verification code has to cope with (temporarily) invalid objects.  See
3605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for example, JSArray::JSArrayVerify).
3606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* filler;
3607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We cannot always fill with one_pointer_filler_map because objects
3608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // created from API functions expect their internal fields to be initialized
3609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // with undefined_value.
3610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Pre-allocated fields need to be initialized with undefined_value as well
3611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // so that object accesses before the constructor completes (e.g. in the
3612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // debugger) will not cause a crash.
3613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (map->constructor()->IsJSFunction() &&
3614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      JSFunction::cast(map->constructor())
3615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ->IsInobjectSlackTrackingInProgress()) {
3616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We might want to shrink the object later.
3617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(obj->GetInternalFieldCount() == 0);
3618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    filler = Heap::one_pointer_filler_map();
3619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    filler = Heap::undefined_value();
3621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->InitializeBody(map, Heap::undefined_value(), filler);
3623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateJSObjectFromMap(
3627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Map* map, PretenureFlag pretenure, bool allocate_properties,
3628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationSite* allocation_site) {
3629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // JSFunctions should be allocated using AllocateFunction to be
3630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // properly initialized.
3631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(map->instance_type() != JS_FUNCTION_TYPE);
3632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Both types of global objects should be allocated using
3634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // AllocateGlobalObject to be properly initialized.
3635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(map->instance_type() != JS_GLOBAL_OBJECT_TYPE);
3636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(map->instance_type() != JS_BUILTINS_OBJECT_TYPE);
3637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate the backing storage for the properties.
3639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedArray* properties;
3640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (allocate_properties) {
3641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int prop_size = map->InitialPropertiesLength();
3642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(prop_size >= 0);
3643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
3644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationResult allocation = AllocateFixedArray(prop_size, pretenure);
3645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!allocation.To(&properties)) return allocation;
3646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    properties = empty_fixed_array();
3649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate the JSObject.
3652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = map->instance_size();
3653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace space = SelectSpace(size, OLD_POINTER_SPACE, pretenure);
3654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSObject* js_obj;
3655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationResult allocation = Allocate(map, space, allocation_site);
3656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!allocation.To(&js_obj)) return allocation;
3657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize the JSObject.
3659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InitializeJSObjectFromMap(js_obj, properties, map);
3660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(js_obj->HasFastElements() || js_obj->HasExternalArrayElements() ||
3661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         js_obj->HasFixedTypedArrayElements());
3662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return js_obj;
3663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateJSObject(JSFunction* constructor,
3667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        PretenureFlag pretenure,
3668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        AllocationSite* allocation_site) {
3669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(constructor->has_initial_map());
3670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate the object based on the constructors initial map.
3672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationResult allocation = AllocateJSObjectFromMap(
3673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      constructor->initial_map(), pretenure, true, allocation_site);
3674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
3675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make sure result is NOT a global object if valid.
3676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* obj;
3677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!allocation.To(&obj) || !obj->IsGlobalObject());
3678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
3679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return allocation;
3680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::CopyJSObject(JSObject* source, AllocationSite* site) {
3684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Never used to copy functions.  If functions need to be copied we
3685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // have to be careful to clear the literals array.
3686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SLOW_DCHECK(!source->IsJSFunction());
3687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make the clone.
3689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Map* map = source->map();
3690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int object_size = map->instance_size();
3691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* clone;
3692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(site == NULL || AllocationSite::CanTrack(map->instance_type()));
3694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WriteBarrierMode wb_mode = UPDATE_WRITE_BARRIER;
3696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If we're forced to always allocate, we use the general allocation
3698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // functions which may leave us with an object in old space.
3699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (always_allocate()) {
3700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
3701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationResult allocation =
3702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AllocateRaw(object_size, NEW_SPACE, OLD_POINTER_SPACE);
3703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!allocation.To(&clone)) return allocation;
3704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address clone_address = clone->address();
3706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CopyBlock(clone_address, source->address(), object_size);
3707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Update write barrier for all fields that lie beyond the header.
3708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordWrites(clone_address, JSObject::kHeaderSize,
3709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 (object_size - JSObject::kHeaderSize) / kPointerSize);
3710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    wb_mode = SKIP_WRITE_BARRIER;
3712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
3714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int adjusted_object_size =
3715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          site != NULL ? object_size + AllocationMemento::kSize : object_size;
3716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationResult allocation =
3717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AllocateRaw(adjusted_object_size, NEW_SPACE, NEW_SPACE);
3718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!allocation.To(&clone)) return allocation;
3719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SLOW_DCHECK(InNewSpace(clone));
3721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Since we know the clone is allocated in new space, we can copy
3722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the contents without worrying about updating the write barrier.
3723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CopyBlock(clone->address(), source->address(), object_size);
3724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (site != NULL) {
3726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>(
3727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          reinterpret_cast<Address>(clone) + object_size);
3728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      InitializeAllocationMemento(alloc_memento, site);
3729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SLOW_DCHECK(JSObject::cast(clone)->GetElementsKind() ==
3733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              source->GetElementsKind());
3734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedArrayBase* elements = FixedArrayBase::cast(source->elements());
3735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedArray* properties = FixedArray::cast(source->properties());
3736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update elements if necessary.
3737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (elements->length() > 0) {
3738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FixedArrayBase* elem;
3739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
3740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationResult allocation;
3741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (elements->map() == fixed_cow_array_map()) {
3742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        allocation = FixedArray::cast(elements);
3743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (source->HasFastDoubleElements()) {
3744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        allocation = CopyFixedDoubleArray(FixedDoubleArray::cast(elements));
3745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
3746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        allocation = CopyFixedArray(FixedArray::cast(elements));
3747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
3748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!allocation.To(&elem)) return allocation;
3749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JSObject::cast(clone)->set_elements(elem, wb_mode);
3751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update properties if necessary.
3753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (properties->length() > 0) {
3754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FixedArray* prop;
3755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
3756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocationResult allocation = CopyFixedArray(properties);
3757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!allocation.To(&prop)) return allocation;
3758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JSObject::cast(clone)->set_properties(prop, wb_mode);
3760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return the new clone.
3762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return clone;
3763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic inline void WriteOneByteData(Vector<const char> vector, uint8_t* chars,
3767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    int len) {
3768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Only works for one byte strings.
3769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(vector.length() == len);
3770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemCopy(chars, vector.start(), len);
3771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic inline void WriteTwoByteData(Vector<const char> vector, uint16_t* chars,
3774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    int len) {
3775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const uint8_t* stream = reinterpret_cast<const uint8_t*>(vector.start());
3776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned stream_length = vector.length();
3777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (stream_length != 0) {
3778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    unsigned consumed = 0;
3779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t c = unibrow::Utf8::ValueOf(stream, stream_length, &consumed);
3780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(c != unibrow::Utf8::kBadChar);
3781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(consumed <= stream_length);
3782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stream_length -= consumed;
3783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stream += consumed;
3784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (c > unibrow::Utf16::kMaxNonSurrogateCharCode) {
3785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      len -= 2;
3786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (len < 0) break;
3787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *chars++ = unibrow::Utf16::LeadSurrogate(c);
3788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *chars++ = unibrow::Utf16::TrailSurrogate(c);
3789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
3790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      len -= 1;
3791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (len < 0) break;
3792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *chars++ = c;
3793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(stream_length == 0);
3796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(len == 0);
3797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic inline void WriteOneByteData(String* s, uint8_t* chars, int len) {
3801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(s->length() == len);
3802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::WriteToFlat(s, chars, 0, len);
3803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic inline void WriteTwoByteData(String* s, uint16_t* chars, int len) {
3807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(s->length() == len);
3808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::WriteToFlat(s, chars, 0, len);
3809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <bool is_one_byte, typename T>
3813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateInternalizedStringImpl(T t, int chars,
3814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                      uint32_t hash_field) {
3815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(chars >= 0);
3816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compute map and object size.
3817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size;
3818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Map* map;
3819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_LE(0, chars);
3821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_GE(String::kMaxLength, chars);
3822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (is_one_byte) {
3823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    map = one_byte_internalized_string_map();
3824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    size = SeqOneByteString::SizeFor(chars);
3825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    map = internalized_string_map();
3827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    size = SeqTwoByteString::SizeFor(chars);
3828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, TENURED);
3830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate string.
3832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
3833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRaw(size, space, OLD_DATA_SPACE);
3835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&result)) return allocation;
3836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_map_no_write_barrier(map);
3839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set length and hash fields of the allocated string.
3840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String* answer = String::cast(result);
3841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  answer->set_length(chars);
3842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  answer->set_hash_field(hash_field);
3843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(size, answer->Size());
3845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (is_one_byte) {
3847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    WriteOneByteData(t, SeqOneByteString::cast(answer)->GetChars(), chars);
3848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    WriteTwoByteData(t, SeqTwoByteString::cast(answer)->GetChars(), chars);
3850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return answer;
3852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Need explicit instantiations.
3856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate AllocationResult Heap::AllocateInternalizedStringImpl<true>(String*,
3857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                                     int,
3858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                                     uint32_t);
3859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate AllocationResult Heap::AllocateInternalizedStringImpl<false>(String*,
3860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                                      int,
3861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                                      uint32_t);
3862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate AllocationResult Heap::AllocateInternalizedStringImpl<false>(
3863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Vector<const char>, int, uint32_t);
3864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateRawOneByteString(int length,
3867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                PretenureFlag pretenure) {
3868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_LE(0, length);
3869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_GE(String::kMaxLength, length);
3870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = SeqOneByteString::SizeFor(length);
3871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(size <= SeqOneByteString::kMaxSize);
3872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
3873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
3875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRaw(size, space, OLD_DATA_SPACE);
3877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&result)) return allocation;
3878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Partially initialize the object.
3881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_map_no_write_barrier(one_byte_string_map());
3882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::cast(result)->set_length(length);
3883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::cast(result)->set_hash_field(String::kEmptyHashField);
3884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(size, HeapObject::cast(result)->Size());
3885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
3887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateRawTwoByteString(int length,
3891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                PretenureFlag pretenure) {
3892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_LE(0, length);
3893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_GE(String::kMaxLength, length);
3894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = SeqTwoByteString::SizeFor(length);
3895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(size <= SeqTwoByteString::kMaxSize);
3896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
3897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
3899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRaw(size, space, OLD_DATA_SPACE);
3901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&result)) return allocation;
3902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Partially initialize the object.
3905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_map_no_write_barrier(string_map());
3906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::cast(result)->set_length(length);
3907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::cast(result)->set_hash_field(String::kEmptyHashField);
3908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(size, HeapObject::cast(result)->Size());
3909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
3910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateEmptyFixedArray() {
3914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = FixedArray::SizeFor(0);
3915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
3916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation =
3918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE);
3919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&result)) return allocation;
3920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize the object.
3922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_map_no_write_barrier(fixed_array_map());
3923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedArray::cast(result)->set_length(0);
3924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
3925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateEmptyExternalArray(
3929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalArrayType array_type) {
3930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return AllocateExternalArray(0, array_type, NULL, TENURED);
3931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::CopyAndTenureFixedCOWArray(FixedArray* src) {
3935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!InNewSpace(src)) {
3936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return src;
3937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int len = src->length();
3940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* obj;
3941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRawFixedArray(len, TENURED);
3943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&obj)) return allocation;
3944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->set_map_no_write_barrier(fixed_array_map());
3946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedArray* result = FixedArray::cast(obj);
3947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_length(len);
3948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy the content
3950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_gc;
3951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
3952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < len; i++) result->set(i, src->get(i), mode);
3953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(mvstanton): The map is set twice because of protection against calling
3955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // set() on a COW FixedArray. Issue v8:3221 created to track this, and
3956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // we might then be able to remove this whole method.
3957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject::cast(obj)->set_map_no_write_barrier(fixed_cow_array_map());
3958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
3959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateEmptyFixedTypedArray(
3963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalArrayType array_type) {
3964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return AllocateFixedTypedArray(0, array_type, TENURED);
3965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) {
3969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int len = src->length();
3970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* obj;
3971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRawFixedArray(len, NOT_TENURED);
3973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&obj)) return allocation;
3974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (InNewSpace(obj)) {
3976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj->set_map_no_write_barrier(map);
3977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CopyBlock(obj->address() + kPointerSize, src->address() + kPointerSize,
3978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              FixedArray::SizeFor(len) - kPointerSize);
3979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return obj;
3980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->set_map_no_write_barrier(map);
3982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedArray* result = FixedArray::cast(obj);
3983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_length(len);
3984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy the content
3986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_gc;
3987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
3988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < len; i++) result->set(i, src->get(i), mode);
3989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
3990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::CopyFixedDoubleArrayWithMap(FixedDoubleArray* src,
3994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                   Map* map) {
3995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int len = src->length();
3996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* obj;
3997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRawFixedDoubleArray(len, NOT_TENURED);
3999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&obj)) return allocation;
4000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->set_map_no_write_barrier(map);
4002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CopyBlock(obj->address() + FixedDoubleArray::kLengthOffset,
4003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            src->address() + FixedDoubleArray::kLengthOffset,
4004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            FixedDoubleArray::SizeFor(len) - FixedDoubleArray::kLengthOffset);
4005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return obj;
4006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::CopyConstantPoolArrayWithMap(ConstantPoolArray* src,
4010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Map* map) {
4011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* obj;
4012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (src->is_extended_layout()) {
4013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ConstantPoolArray::NumberOfEntries small(src,
4014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             ConstantPoolArray::SMALL_SECTION);
4015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ConstantPoolArray::NumberOfEntries extended(
4016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        src, ConstantPoolArray::EXTENDED_SECTION);
4017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation =
4018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AllocateExtendedConstantPoolArray(small, extended);
4019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&obj)) return allocation;
4020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ConstantPoolArray::NumberOfEntries small(src,
4022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             ConstantPoolArray::SMALL_SECTION);
4023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateConstantPoolArray(small);
4024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&obj)) return allocation;
4025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->set_map_no_write_barrier(map);
4027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CopyBlock(obj->address() + ConstantPoolArray::kFirstEntryOffset,
4028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            src->address() + ConstantPoolArray::kFirstEntryOffset,
4029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            src->size() - ConstantPoolArray::kFirstEntryOffset);
4030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return obj;
4031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateRawFixedArray(int length,
4035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             PretenureFlag pretenure) {
4036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (length < 0 || length > FixedArray::kMaxLength) {
4037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", true);
4038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = FixedArray::SizeFor(length);
4040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace space = SelectSpace(size, OLD_POINTER_SPACE, pretenure);
4041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return AllocateRaw(size, space, OLD_POINTER_SPACE);
4043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateFixedArrayWithFiller(int length,
4047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    PretenureFlag pretenure,
4048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    Object* filler) {
4049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(length >= 0);
4050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(empty_fixed_array()->IsFixedArray());
4051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (length == 0) return empty_fixed_array();
4052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!InNewSpace(filler));
4054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
4055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRawFixedArray(length, pretenure);
4057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&result)) return allocation;
4058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_map_no_write_barrier(fixed_array_map());
4061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedArray* array = FixedArray::cast(result);
4062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  array->set_length(length);
4063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemsetPointer(array->data_start(), filler, length);
4064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return array;
4065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateFixedArray(int length, PretenureFlag pretenure) {
4069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return AllocateFixedArrayWithFiller(length, pretenure, undefined_value());
4070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateUninitializedFixedArray(int length) {
4074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (length == 0) return empty_fixed_array();
4075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* obj;
4077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRawFixedArray(length, NOT_TENURED);
4079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&obj)) return allocation;
4080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->set_map_no_write_barrier(fixed_array_map());
4083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedArray::cast(obj)->set_length(length);
4084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return obj;
4085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateUninitializedFixedDoubleArray(
4089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int length, PretenureFlag pretenure) {
4090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (length == 0) return empty_fixed_array();
4091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* elements;
4093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationResult allocation = AllocateRawFixedDoubleArray(length, pretenure);
4094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!allocation.To(&elements)) return allocation;
4095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  elements->set_map_no_write_barrier(fixed_double_array_map());
4097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FixedDoubleArray::cast(elements)->set_length(length);
4098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return elements;
4099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateRawFixedDoubleArray(int length,
4103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                   PretenureFlag pretenure) {
4104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (length < 0 || length > FixedDoubleArray::kMaxLength) {
4105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", true);
4106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = FixedDoubleArray::SizeFor(length);
4108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_HOST_ARCH_64_BIT
4109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size += kPointerSize;
4110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
4111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
4112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* object;
4114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRaw(size, space, OLD_DATA_SPACE);
4116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&object)) return allocation;
4117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return EnsureDoubleAligned(this, object, size);
4120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateConstantPoolArray(
4124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const ConstantPoolArray::NumberOfEntries& small) {
4125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(small.are_in_range(0, ConstantPoolArray::kMaxSmallEntriesPerType));
4126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = ConstantPoolArray::SizeFor(small);
4127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_HOST_ARCH_64_BIT
4128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size += kPointerSize;
4129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
4130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace space = SelectSpace(size, OLD_POINTER_SPACE, TENURED);
4131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* object;
4133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRaw(size, space, OLD_POINTER_SPACE);
4135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&object)) return allocation;
4136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object = EnsureDoubleAligned(this, object, size);
4138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object->set_map_no_write_barrier(constant_pool_array_map());
4139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ConstantPoolArray* constant_pool = ConstantPoolArray::cast(object);
4141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  constant_pool->Init(small);
4142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  constant_pool->ClearPtrEntries(isolate());
4143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return constant_pool;
4144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateExtendedConstantPoolArray(
4148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const ConstantPoolArray::NumberOfEntries& small,
4149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const ConstantPoolArray::NumberOfEntries& extended) {
4150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(small.are_in_range(0, ConstantPoolArray::kMaxSmallEntriesPerType));
4151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(extended.are_in_range(0, kMaxInt));
4152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = ConstantPoolArray::SizeForExtended(small, extended);
4153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_HOST_ARCH_64_BIT
4154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size += kPointerSize;
4155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
4156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace space = SelectSpace(size, OLD_POINTER_SPACE, TENURED);
4157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* object;
4159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = AllocateRaw(size, space, OLD_POINTER_SPACE);
4161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&object)) return allocation;
4162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object = EnsureDoubleAligned(this, object, size);
4164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object->set_map_no_write_barrier(constant_pool_array_map());
4165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ConstantPoolArray* constant_pool = ConstantPoolArray::cast(object);
4167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  constant_pool->InitExtended(small, extended);
4168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  constant_pool->ClearPtrEntries(isolate());
4169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return constant_pool;
4170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateEmptyConstantPoolArray() {
4174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ConstantPoolArray::NumberOfEntries small(0, 0, 0, 0);
4175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = ConstantPoolArray::SizeFor(small);
4176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
4177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation =
4179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE);
4180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&result)) return allocation;
4181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_map_no_write_barrier(constant_pool_array_map());
4183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ConstantPoolArray::cast(result)->Init(small);
4184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
4185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateSymbol() {
4189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Statically ensure that it is safe to allocate symbols in paged spaces.
4190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(Symbol::kSize <= Page::kMaxRegularHeapObjectSize);
4191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* result;
4193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationResult allocation =
4194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocateRaw(Symbol::kSize, OLD_POINTER_SPACE, OLD_POINTER_SPACE);
4195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!allocation.To(&result)) return allocation;
4196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->set_map_no_write_barrier(symbol_map());
4198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generate a random hash value.
4200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int hash;
4201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int attempts = 0;
4202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  do {
4203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    hash = isolate()->random_number_generator()->NextInt() & Name::kHashBitMask;
4204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    attempts++;
4205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } while (hash == 0 && attempts < 30);
4206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hash == 0) hash = 1;  // never return 0
4207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Symbol::cast(result)
4209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ->set_hash_field(Name::kIsNotArrayIndexMask | (hash << Name::kHashShift));
4210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Symbol::cast(result)->set_name(undefined_value());
4211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Symbol::cast(result)->set_flags(Smi::FromInt(0));
4212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!Symbol::cast(result)->is_private());
4214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
4215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAllocationResult Heap::AllocateStruct(InstanceType type) {
4219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Map* map;
4220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (type) {
4221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define MAKE_CASE(NAME, Name, name) \
4222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  case NAME##_TYPE:                 \
4223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    map = name##_map();             \
4224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    break;
4225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STRUCT_LIST(MAKE_CASE)
4226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef MAKE_CASE
4227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
4228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
4229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return exception();
4230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int size = map->instance_size();
4232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSpace space = SelectSpace(size, OLD_POINTER_SPACE, TENURED);
4233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Struct* result;
4234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationResult allocation = Allocate(map, space);
4236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!allocation.To(&result)) return allocation;
4237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  result->InitializeBody(size);
4239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
4240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::IsHeapIterable() {
4244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(hpayer): This function is not correct. Allocation folding in old
4245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // space breaks the iterability.
4246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return new_space_top_after_last_gc_ == new_space()->top();
4247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::MakeHeapIterable() {
4251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(AllowHeapAllocation::IsAllowed());
4252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!IsHeapIterable()) {
4253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CollectAllGarbage(kMakeHeapIterableMask, "Heap::MakeHeapIterable");
4254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mark_compact_collector()->sweeping_in_progress()) {
4256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mark_compact_collector()->EnsureSweepingCompleted();
4257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(IsHeapIterable());
4259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::IdleMarkCompact(const char* message) {
4263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool uncommit = false;
4264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (gc_count_at_last_idle_gc_ == gc_count_) {
4265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // No GC since the last full GC, the mutator is probably not active.
4266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->compilation_cache()->Clear();
4267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uncommit = true;
4268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CollectAllGarbage(kReduceMemoryFootprintMask, message);
4270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  gc_idle_time_handler_.NotifyIdleMarkCompact();
4271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  gc_count_at_last_idle_gc_ = gc_count_;
4272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (uncommit) {
4273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    new_space_.Shrink();
4274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UncommitFromSpace();
4275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::AdvanceIdleIncrementalMarking(intptr_t step_size) {
4280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  incremental_marking()->Step(step_size,
4281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              IncrementalMarking::NO_GC_VIA_STACK_GUARD, true);
4282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (incremental_marking()->IsComplete()) {
4284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    IdleMarkCompact("idle notification: finalize incremental");
4285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::WorthActivatingIncrementalMarking() {
4290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return incremental_marking()->IsStopped() &&
4291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         incremental_marking()->WorthActivating() && NextGCIsLikelyToBeFull();
4292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::IdleNotification(int idle_time_in_ms) {
4296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If incremental marking is off, we do not perform idle notification.
4297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_incremental_marking) return true;
4298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::ElapsedTimer timer;
4299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  timer.Start();
4300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->gc_idle_time_allotted_in_ms()->AddSample(
4301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      idle_time_in_ms);
4302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HistogramTimerScope idle_notification_scope(
4303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate_->counters()->gc_idle_notification());
4304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GCIdleTimeHandler::HeapState heap_state;
4306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap_state.contexts_disposed = contexts_disposed_;
4307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects());
4308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap_state.incremental_marking_stopped = incremental_marking()->IsStopped();
4309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(ulan): Start incremental marking only for large heaps.
4310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap_state.can_start_incremental_marking =
4311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      incremental_marking()->ShouldActivate();
4312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap_state.sweeping_in_progress =
4313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mark_compact_collector()->sweeping_in_progress();
4314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap_state.mark_compact_speed_in_bytes_per_ms =
4315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<size_t>(tracer()->MarkCompactSpeedInBytesPerMillisecond());
4316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap_state.incremental_marking_speed_in_bytes_per_ms = static_cast<size_t>(
4317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      tracer()->IncrementalMarkingSpeedInBytesPerMillisecond());
4318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap_state.scavenge_speed_in_bytes_per_ms =
4319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<size_t>(tracer()->ScavengeSpeedInBytesPerMillisecond());
4320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap_state.available_new_space_memory = new_space_.Available();
4321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap_state.new_space_capacity = new_space_.Capacity();
4322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  heap_state.new_space_allocation_throughput_in_bytes_per_ms =
4323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<size_t>(
4324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond());
4325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GCIdleTimeAction action =
4327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      gc_idle_time_handler_.Compute(idle_time_in_ms, heap_state);
4328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool result = false;
4330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (action.type) {
4331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case DONE:
4332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      result = true;
4333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
4334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case DO_INCREMENTAL_MARKING:
4335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (incremental_marking()->IsStopped()) {
4336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        incremental_marking()->Start();
4337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
4338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AdvanceIdleIncrementalMarking(action.parameter);
4339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
4340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case DO_FULL_GC: {
4341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      HistogramTimerScope scope(isolate_->counters()->gc_context());
4342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (contexts_disposed_) {
4343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        CollectAllGarbage(kReduceMemoryFootprintMask,
4344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          "idle notification: contexts disposed");
4345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        gc_idle_time_handler_.NotifyIdleMarkCompact();
4346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        gc_count_at_last_idle_gc_ = gc_count_;
4347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
4348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        IdleMarkCompact("idle notification: finalize idle round");
4349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
4350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
4351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case DO_SCAVENGE:
4353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CollectGarbage(NEW_SPACE, "idle notification: scavenge");
4354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
4355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case DO_FINALIZE_SWEEPING:
4356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mark_compact_collector()->EnsureSweepingCompleted();
4357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
4358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case DO_NOTHING:
4359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
4360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int actual_time_ms = static_cast<int>(timer.Elapsed().InMilliseconds());
4363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (actual_time_ms <= idle_time_in_ms) {
4364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate()->counters()->gc_idle_time_limit_undershot()->AddSample(
4365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        idle_time_in_ms - actual_time_ms);
4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate()->counters()->gc_idle_time_limit_overshot()->AddSample(
4368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        actual_time_ms - idle_time_in_ms);
4369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trace_idle_notification) {
4372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("Idle notification: requested idle time %d ms, actual time %d ms [",
4373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           idle_time_in_ms, actual_time_ms);
4374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    action.Print();
4375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("]\n");
4376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  contexts_disposed_ = 0;
4379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
4380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
4384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::Print() {
4386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!HasBeenSetUp()) return;
4387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->PrintStack(stdout);
4388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllSpaces spaces(this);
4389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
4390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    space->Print();
4391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ReportCodeStatistics(const char* title) {
4396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF(">>>>>> Code Stats (%s) >>>>>>\n", title);
4397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PagedSpace::ResetCodeStatistics(isolate());
4398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We do not look for code in new space, map space, or old space.  If code
4399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // somehow ends up in those spaces, we would miss it here.
4400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code_space_->CollectCodeStatistics();
4401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lo_space_->CollectCodeStatistics();
4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PagedSpace::ReportCodeStatistics(isolate());
4403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// This function expects that NewSpace's allocated objects histogram is
4407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// populated (via a call to CollectStatistics or else as a side effect of a
4408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// just-completed scavenge collection).
4409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ReportHeapStatistics(const char* title) {
4410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  USE(title);
4411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF(">>>>>> =============== %s (%d) =============== >>>>>>\n", title,
4412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         gc_count_);
4413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF("old_generation_allocation_limit_ %" V8_PTR_PREFIX "d\n",
4414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         old_generation_allocation_limit_);
4415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF("\n");
4417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF("Number of handles : %d\n", HandleScope::NumberOfHandles(isolate_));
4418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->global_handles()->PrintStats();
4419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF("\n");
4420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF("Heap statistics : ");
4422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->memory_allocator()->ReportStatistics();
4423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF("To space : ");
4424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_.ReportStatistics();
4425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF("Old pointer space : ");
4426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  old_pointer_space_->ReportStatistics();
4427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF("Old data space : ");
4428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  old_data_space_->ReportStatistics();
4429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF("Code space : ");
4430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code_space_->ReportStatistics();
4431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF("Map space : ");
4432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map_space_->ReportStatistics();
4433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF("Cell space : ");
4434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cell_space_->ReportStatistics();
4435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF("PropertyCell space : ");
4436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  property_cell_space_->ReportStatistics();
4437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF("Large object space : ");
4438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lo_space_->ReportStatistics();
4439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF(">>>>>> ========================================= >>>>>>\n");
4440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // DEBUG
4443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::Contains(HeapObject* value) { return Contains(value->address()); }
4445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::Contains(Address addr) {
4448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate_->memory_allocator()->IsOutsideAllocatedSpace(addr)) return false;
4449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return HasBeenSetUp() &&
4450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         (new_space_.ToSpaceContains(addr) ||
4451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          old_pointer_space_->Contains(addr) ||
4452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          old_data_space_->Contains(addr) || code_space_->Contains(addr) ||
4453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          map_space_->Contains(addr) || cell_space_->Contains(addr) ||
4454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          property_cell_space_->Contains(addr) ||
4455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          lo_space_->SlowContains(addr));
4456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::InSpace(HeapObject* value, AllocationSpace space) {
4460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return InSpace(value->address(), space);
4461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::InSpace(Address addr, AllocationSpace space) {
4465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate_->memory_allocator()->IsOutsideAllocatedSpace(addr)) return false;
4466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!HasBeenSetUp()) return false;
4467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (space) {
4469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case NEW_SPACE:
4470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return new_space_.ToSpaceContains(addr);
4471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case OLD_POINTER_SPACE:
4472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return old_pointer_space_->Contains(addr);
4473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case OLD_DATA_SPACE:
4474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return old_data_space_->Contains(addr);
4475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case CODE_SPACE:
4476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return code_space_->Contains(addr);
4477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case MAP_SPACE:
4478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return map_space_->Contains(addr);
4479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case CELL_SPACE:
4480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return cell_space_->Contains(addr);
4481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case PROPERTY_CELL_SPACE:
4482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return property_cell_space_->Contains(addr);
4483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case LO_SPACE:
4484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return lo_space_->SlowContains(addr);
4485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case INVALID_SPACE:
4486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
4487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UNREACHABLE();
4489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return false;
4490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
4494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::Verify() {
4495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK(HasBeenSetUp());
4496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate());
4497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  store_buffer()->Verify();
4499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mark_compact_collector()->sweeping_in_progress()) {
4501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We have to wait here for the sweeper threads to have an iterable heap.
4502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mark_compact_collector()->EnsureSweepingCompleted();
4503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VerifyPointersVisitor visitor;
4506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IterateRoots(&visitor, VISIT_ONLY_STRONG);
4507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VerifySmisVisitor smis_visitor;
4509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IterateSmiRoots(&smis_visitor);
4510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_.Verify();
4512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  old_pointer_space_->Verify(&visitor);
4514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map_space_->Verify(&visitor);
4515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VerifyPointersVisitor no_dirty_regions_visitor;
4517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  old_data_space_->Verify(&no_dirty_regions_visitor);
4518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code_space_->Verify(&no_dirty_regions_visitor);
4519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cell_space_->Verify(&no_dirty_regions_visitor);
4520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  property_cell_space_->Verify(&no_dirty_regions_visitor);
4521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lo_space_->Verify();
4523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
4525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ZapFromSpace() {
4528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NewSpacePageIterator it(new_space_.FromSpaceStart(),
4529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          new_space_.FromSpaceEnd());
4530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (it.has_next()) {
4531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    NewSpacePage* page = it.next();
4532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (Address cursor = page->area_start(), limit = page->area_end();
4533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         cursor < limit; cursor += kPointerSize) {
4534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Memory::Address_at(cursor) = kFromSpaceZapValue;
4535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::IterateAndMarkPointersToFromSpace(Address start, Address end,
4541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             ObjectSlotCallback callback) {
4542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address slot_address = start;
4543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We are not collecting slots on new space objects during mutation
4545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // thus we have to scan for pointers to evacuation candidates when we
4546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // promote objects. But we should not record any slots in non-black
4547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // objects. Grey object's slots would be rescanned.
4548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // White object might not survive until the end of collection
4549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // it would be a violation of the invariant to record it's slots.
4550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool record_slots = false;
4551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (incremental_marking()->IsCompacting()) {
4552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MarkBit mark_bit = Marking::MarkBitFrom(HeapObject::FromAddress(start));
4553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    record_slots = Marking::IsBlack(mark_bit);
4554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (slot_address < end) {
4557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object** slot = reinterpret_cast<Object**>(slot_address);
4558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* object = *slot;
4559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If the store buffer becomes overfull we mark pages as being exempt from
4560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the store buffer.  These pages are scanned to find pointers that point
4561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // to the new space.  In that case we may hit newly promoted objects and
4562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // fix the pointers before the promotion queue gets to them.  Thus the 'if'.
4563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (object->IsHeapObject()) {
4564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (Heap::InFromSpace(object)) {
4565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        callback(reinterpret_cast<HeapObject**>(slot),
4566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 HeapObject::cast(object));
4567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Object* new_object = *slot;
4568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (InNewSpace(new_object)) {
4569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          SLOW_DCHECK(Heap::InToSpace(new_object));
4570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          SLOW_DCHECK(new_object->IsHeapObject());
4571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          store_buffer_.EnterDirectlyIntoStoreBuffer(
4572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              reinterpret_cast<Address>(slot));
4573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
4574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        SLOW_DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(new_object));
4575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (record_slots &&
4576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 MarkCompactCollector::IsOnEvacuationCandidate(object)) {
4577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        mark_compact_collector()->RecordSlot(slot, slot, object);
4578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
4579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    slot_address += kPointerSize;
4581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
4586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef bool (*CheckStoreBufferFilter)(Object** addr);
4587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool IsAMapPointerAddress(Object** addr) {
4590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uintptr_t a = reinterpret_cast<uintptr_t>(addr);
4591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int mod = a % Map::kSize;
4592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return mod >= Map::kPointerFieldsBeginOffset &&
4593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         mod < Map::kPointerFieldsEndOffset;
4594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool EverythingsAPointer(Object** addr) { return true; }
4598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckStoreBuffer(Heap* heap, Object** current, Object** limit,
4601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Object**** store_buffer_position,
4602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Object*** store_buffer_top,
4603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             CheckStoreBufferFilter filter,
4604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Address special_garbage_start,
4605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Address special_garbage_end) {
4606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Map* free_space_map = heap->free_space_map();
4607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (; current < limit; current++) {
4608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* o = *current;
4609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address current_address = reinterpret_cast<Address>(current);
4610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Skip free space.
4611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (o == free_space_map) {
4612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Address current_address = reinterpret_cast<Address>(current);
4613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FreeSpace* free_space =
4614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          FreeSpace::cast(HeapObject::FromAddress(current_address));
4615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int skip = free_space->Size();
4616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(current_address + skip <= reinterpret_cast<Address>(limit));
4617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(skip > 0);
4618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      current_address += skip - kPointerSize;
4619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      current = reinterpret_cast<Object**>(current_address);
4620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      continue;
4621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Skip the current linear allocation space between top and limit which is
4623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // unmarked with the free space map, but can contain junk.
4624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (current_address == special_garbage_start &&
4625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        special_garbage_end != special_garbage_start) {
4626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      current_address = special_garbage_end - kPointerSize;
4627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      current = reinterpret_cast<Object**>(current_address);
4628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      continue;
4629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!(*filter)(current)) continue;
4631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(current_address < special_garbage_start ||
4632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           current_address >= special_garbage_end);
4633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(reinterpret_cast<uintptr_t>(o) != kFreeListZapValue);
4634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We have to check that the pointer does not point into new space
4635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // without trying to cast it to a heap object since the hash field of
4636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // a string can contain values like 1 and 3 which are tagged null
4637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // pointers.
4638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!heap->InNewSpace(o)) continue;
4639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    while (**store_buffer_position < current &&
4640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           *store_buffer_position < store_buffer_top) {
4641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (*store_buffer_position)++;
4642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (**store_buffer_position != current ||
4644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        *store_buffer_position == store_buffer_top) {
4645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Object** obj_start = current;
4646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      while (!(*obj_start)->IsMap()) obj_start--;
4647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
4648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Check that the store buffer contains all intergenerational pointers by
4654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// scanning a page and ensuring that all pointers to young space are in the
4655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// store buffer.
4656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::OldPointerSpaceCheckStoreBuffer() {
4657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OldSpace* space = old_pointer_space();
4658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PageIterator pages(space);
4659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  store_buffer()->SortUniq();
4661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (pages.has_next()) {
4663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Page* page = pages.next();
4664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object** current = reinterpret_cast<Object**>(page->area_start());
4665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address end = page->area_end();
4667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object*** store_buffer_position = store_buffer()->Start();
4669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object*** store_buffer_top = store_buffer()->Top();
4670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object** limit = reinterpret_cast<Object**>(end);
4672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckStoreBuffer(this, current, limit, &store_buffer_position,
4673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     store_buffer_top, &EverythingsAPointer, space->top(),
4674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     space->limit());
4675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::MapSpaceCheckStoreBuffer() {
4680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MapSpace* space = map_space();
4681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PageIterator pages(space);
4682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  store_buffer()->SortUniq();
4684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (pages.has_next()) {
4686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Page* page = pages.next();
4687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object** current = reinterpret_cast<Object**>(page->area_start());
4688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address end = page->area_end();
4690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object*** store_buffer_position = store_buffer()->Start();
4692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object*** store_buffer_top = store_buffer()->Top();
4693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object** limit = reinterpret_cast<Object**>(end);
4695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CheckStoreBuffer(this, current, limit, &store_buffer_position,
4696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     store_buffer_top, &IsAMapPointerAddress, space->top(),
4697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     space->limit());
4698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::LargeObjectSpaceCheckStoreBuffer() {
4703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LargeObjectIterator it(lo_space());
4704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) {
4705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We only have code, sequential strings, or fixed arrays in large
4706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // object space, and only fixed arrays can possibly contain pointers to
4707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the young generation.
4708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (object->IsFixedArray()) {
4709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Object*** store_buffer_position = store_buffer()->Start();
4710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Object*** store_buffer_top = store_buffer()->Top();
4711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Object** current = reinterpret_cast<Object**>(object->address());
4712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Object** limit =
4713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          reinterpret_cast<Object**>(object->address() + object->Size());
4714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CheckStoreBuffer(this, current, limit, &store_buffer_position,
4715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       store_buffer_top, &EverythingsAPointer, NULL, NULL);
4716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
4720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::IterateRoots(ObjectVisitor* v, VisitMode mode) {
4723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IterateStrongRoots(v, mode);
4724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IterateWeakRoots(v, mode);
4725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) {
4729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->VisitPointer(reinterpret_cast<Object**>(&roots_[kStringTableRootIndex]));
4730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kStringTable);
4731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode != VISIT_ALL_IN_SCAVENGE && mode != VISIT_ALL_IN_SWEEP_NEWSPACE) {
4732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Scavenge collections have special processing for this.
4733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    external_string_table_.Iterate(v);
4734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kExternalStringsTable);
4736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::IterateSmiRoots(ObjectVisitor* v) {
4740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Acquire execution access since we are going to read stack limit values.
4741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExecutionAccess access(isolate());
4742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->VisitPointers(&roots_[kSmiRootsStart], &roots_[kRootListLength]);
4743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kSmiRootList);
4744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) {
4748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]);
4749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kStrongRootList);
4750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->VisitPointer(bit_cast<Object**>(&hidden_string_));
4752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kInternalizedString);
4753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->bootstrapper()->Iterate(v);
4755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kBootstrapper);
4756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->Iterate(v);
4757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kTop);
4758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Relocatable::Iterate(isolate_, v);
4759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kRelocatable);
4760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate_->deoptimizer_data() != NULL) {
4762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->deoptimizer_data()->Iterate(v);
4763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kDebug);
4765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->compilation_cache()->Iterate(v);
4766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kCompilationCache);
4767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Iterate over local handles in handle scopes.
4769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->handle_scope_implementer()->Iterate(v);
4770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->IterateDeferredHandles(v);
4771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kHandleScope);
4772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Iterate over the builtin code objects and code stubs in the
4774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // heap. Note that it is not necessary to iterate over code objects
4775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // on scavenge collections.
4776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode != VISIT_ALL_IN_SCAVENGE) {
4777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->builtins()->IterateBuiltins(v);
4778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kBuiltins);
4780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Iterate over global handles.
4782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (mode) {
4783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case VISIT_ONLY_STRONG:
4784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate_->global_handles()->IterateStrongRoots(v);
4785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
4786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case VISIT_ALL_IN_SCAVENGE:
4787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate_->global_handles()->IterateNewSpaceStrongAndDependentRoots(v);
4788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
4789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case VISIT_ALL_IN_SWEEP_NEWSPACE:
4790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case VISIT_ALL:
4791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate_->global_handles()->IterateAllRoots(v);
4792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
4793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kGlobalHandles);
4795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Iterate over eternal handles.
4797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode == VISIT_ALL_IN_SCAVENGE) {
4798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->eternal_handles()->IterateNewSpaceRoots(v);
4799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->eternal_handles()->IterateAllRoots(v);
4801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kEternalHandles);
4803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Iterate over pointers being held by inactive threads.
4805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->thread_manager()->Iterate(v);
4806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v->Synchronize(VisitorSynchronization::kThreadManager);
4807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Iterate over the pointers the Serialization/Deserialization code is
4809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // holding.
4810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // During garbage collection this keeps the partial snapshot cache alive.
4811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // During deserialization of the startup snapshot this creates the partial
4812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // snapshot cache and deserializes the objects it refers to.  During
4813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // serialization this does nothing, since the partial snapshot cache is
4814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // empty.  However the next thing we do is create the partial snapshot,
4815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // filling up the partial snapshot cache with objects it needs as we go.
4816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SerializerDeserializer::Iterate(isolate_, v);
4817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We don't do a v->Synchronize call here, because in debug mode that will
4818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // output a flag to the snapshot.  However at this point the serializer and
4819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // deserializer are deliberately a little unsynchronized (see above) so the
4820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // checking of the sync flag in the snapshot would fail.
4821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(1236194): Since the heap size is configurable on the command line
4825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// and through the API, we should gracefully handle the case that the heap
4826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// size is not big enough to fit all the initial objects.
4827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::ConfigureHeap(int max_semi_space_size, int max_old_space_size,
4828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         int max_executable_size, size_t code_range_size) {
4829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (HasBeenSetUp()) return false;
4830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Overwrite default configuration.
4832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (max_semi_space_size > 0) {
4833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    max_semi_space_size_ = max_semi_space_size * MB;
4834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (max_old_space_size > 0) {
4836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    max_old_generation_size_ = max_old_space_size * MB;
4837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (max_executable_size > 0) {
4839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    max_executable_size_ = max_executable_size * MB;
4840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If max space size flags are specified overwrite the configuration.
4843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_max_semi_space_size > 0) {
4844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    max_semi_space_size_ = FLAG_max_semi_space_size * MB;
4845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_max_old_space_size > 0) {
4847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    max_old_generation_size_ = FLAG_max_old_space_size * MB;
4848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_max_executable_size > 0) {
4850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    max_executable_size_ = FLAG_max_executable_size * MB;
4851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_stress_compaction) {
4854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This will cause more frequent GCs when stressing.
4855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    max_semi_space_size_ = Page::kPageSize;
4856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (Snapshot::HaveASnapshotToStartFrom()) {
4859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If we are using a snapshot we always reserve the default amount
4860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // of memory for each semispace because code in the snapshot has
4861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // write-barrier code that relies on the size and alignment of new
4862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // space.  We therefore cannot use a larger max semispace size
4863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // than the default reserved semispace size.
4864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (max_semi_space_size_ > reserved_semispace_size_) {
4865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      max_semi_space_size_ = reserved_semispace_size_;
4866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (FLAG_trace_gc) {
4867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        PrintPID("Max semi-space size cannot be more than %d kbytes\n",
4868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 reserved_semispace_size_ >> 10);
4869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
4870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If we are not using snapshots we reserve space for the actual
4873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // max semispace size.
4874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    reserved_semispace_size_ = max_semi_space_size_;
4875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The max executable size must be less than or equal to the max old
4878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // generation size.
4879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (max_executable_size_ > max_old_generation_size_) {
4880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    max_executable_size_ = max_old_generation_size_;
4881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The new space size must be a power of two to support single-bit testing
4884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for containment.
4885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  max_semi_space_size_ =
4886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      base::bits::RoundUpToPowerOfTwo32(max_semi_space_size_);
4887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  reserved_semispace_size_ =
4888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      base::bits::RoundUpToPowerOfTwo32(reserved_semispace_size_);
4889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_min_semi_space_size > 0) {
4891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int initial_semispace_size = FLAG_min_semi_space_size * MB;
4892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (initial_semispace_size > max_semi_space_size_) {
4893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      initial_semispace_size_ = max_semi_space_size_;
4894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (FLAG_trace_gc) {
4895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        PrintPID(
4896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            "Min semi-space size cannot be more than the maximum"
4897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            "semi-space size of %d MB\n",
4898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            max_semi_space_size_);
4899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
4900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      initial_semispace_size_ = initial_semispace_size;
4902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  initial_semispace_size_ = Min(initial_semispace_size_, max_semi_space_size_);
4906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The old generation is paged and needs at least one page for each space.
4908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int paged_space_count = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1;
4909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  max_old_generation_size_ =
4910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Max(static_cast<intptr_t>(paged_space_count * Page::kPageSize),
4911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          max_old_generation_size_);
4912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We rely on being able to allocate new arrays in paged spaces.
4914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Page::kMaxRegularHeapObjectSize >=
4915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         (JSArray::kSize +
4916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          FixedArray::SizeFor(JSObject::kInitialMaxFastElementArray) +
4917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          AllocationMemento::kSize));
4918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code_range_size_ = code_range_size * MB;
4920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  configured_ = true;
4922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
4923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::ConfigureHeapDefault() { return ConfigureHeap(0, 0, 0, 0); }
4927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
4930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->start_marker = HeapStats::kStartMarker;
4931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->end_marker = HeapStats::kEndMarker;
4932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->new_space_size = new_space_.SizeAsInt();
4933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->new_space_capacity = static_cast<int>(new_space_.Capacity());
4934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->old_pointer_space_size = old_pointer_space_->SizeOfObjects();
4935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->old_pointer_space_capacity = old_pointer_space_->Capacity();
4936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->old_data_space_size = old_data_space_->SizeOfObjects();
4937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->old_data_space_capacity = old_data_space_->Capacity();
4938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->code_space_size = code_space_->SizeOfObjects();
4939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->code_space_capacity = code_space_->Capacity();
4940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->map_space_size = map_space_->SizeOfObjects();
4941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->map_space_capacity = map_space_->Capacity();
4942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->cell_space_size = cell_space_->SizeOfObjects();
4943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->cell_space_capacity = cell_space_->Capacity();
4944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->property_cell_space_size = property_cell_space_->SizeOfObjects();
4945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->property_cell_space_capacity = property_cell_space_->Capacity();
4946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->lo_space_size = lo_space_->Size();
4947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->global_handles()->RecordStats(stats);
4948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->memory_allocator_size = isolate()->memory_allocator()->Size();
4949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->memory_allocator_capacity =
4950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate()->memory_allocator()->Size() +
4951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate()->memory_allocator()->Available();
4952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  *stats->os_error = base::OS::GetLastError();
4953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->memory_allocator()->Available();
4954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (take_snapshot) {
4955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HeapIterator iterator(this);
4956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (HeapObject* obj = iterator.next(); obj != NULL;
4957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         obj = iterator.next()) {
4958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      InstanceType type = obj->map()->instance_type();
4959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(0 <= type && type <= LAST_TYPE);
4960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stats->objects_per_type[type]++;
4961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stats->size_per_type[type] += obj->Size();
4962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochintptr_t Heap::PromotedSpaceSizeOfObjects() {
4968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return old_pointer_space_->SizeOfObjects() +
4969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         old_data_space_->SizeOfObjects() + code_space_->SizeOfObjects() +
4970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         map_space_->SizeOfObjects() + cell_space_->SizeOfObjects() +
4971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         property_cell_space_->SizeOfObjects() + lo_space_->SizeOfObjects();
4972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint64_t Heap::PromotedExternalMemorySize() {
4976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (amount_of_external_allocated_memory_ <=
4977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      amount_of_external_allocated_memory_at_last_global_gc_)
4978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return 0;
4979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return amount_of_external_allocated_memory_ -
4980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         amount_of_external_allocated_memory_at_last_global_gc_;
4981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochintptr_t Heap::OldGenerationAllocationLimit(intptr_t old_gen_size,
4985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            int freed_global_handles) {
4986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kMaxHandles = 1000;
4987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kMinHandles = 100;
4988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  double min_factor = 1.1;
4989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  double max_factor = 4;
4990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We set the old generation growing factor to 2 to grow the heap slower on
4991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // memory-constrained devices.
4992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) {
4993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    max_factor = 2;
4994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If there are many freed global handles, then the next full GC will
4996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // likely collect a lot of garbage. Choose the heap growing factor
4997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // depending on freed global handles.
4998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(ulan, hpayer): Take into account mutator utilization.
4999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  double factor;
5000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (freed_global_handles <= kMinHandles) {
5001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    factor = max_factor;
5002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (freed_global_handles >= kMaxHandles) {
5003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    factor = min_factor;
5004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
5005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Compute factor using linear interpolation between points
5006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // (kMinHandles, max_factor) and (kMaxHandles, min_factor).
5007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    factor = max_factor -
5008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             (freed_global_handles - kMinHandles) * (max_factor - min_factor) /
5009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 (kMaxHandles - kMinHandles);
5010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_stress_compaction ||
5013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mark_compact_collector()->reduce_memory_footprint_) {
5014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    factor = min_factor;
5015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t limit = static_cast<intptr_t>(old_gen_size * factor);
5018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  limit = Max(limit, kMinimumOldGenerationAllocationLimit);
5019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  limit += new_space_.Capacity();
5020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2;
5021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Min(limit, halfway_to_the_max);
5022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::EnableInlineAllocation() {
5026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!inline_allocation_disabled_) return;
5027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline_allocation_disabled_ = false;
5028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update inline allocation limit for new space.
5030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space()->UpdateInlineAllocationLimit(0);
5031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::DisableInlineAllocation() {
5035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (inline_allocation_disabled_) return;
5036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline_allocation_disabled_ = true;
5037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update inline allocation limit for new space.
5039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space()->UpdateInlineAllocationLimit(0);
5040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update inline allocation limit for old spaces.
5042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PagedSpaces spaces(this);
5043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (PagedSpace* space = spaces.next(); space != NULL;
5044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       space = spaces.next()) {
5045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    space->EmptyAllocationInfo();
5046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochV8_DECLARE_ONCE(initialize_gc_once);
5051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InitializeGCOnce() {
5053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InitializeScavengingVisitorsTables();
5054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NewSpaceScavenger::Initialize();
5055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkCompactCollector::Initialize();
5056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::SetUp() {
5060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
5061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  allocation_timeout_ = FLAG_gc_interval;
5062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
5063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize heap spaces and initial maps and objects. Whenever something
5065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // goes wrong, just return false. The caller should check the results and
5066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // call Heap::TearDown() to release allocated memory.
5067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
5068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the heap is not yet configured (e.g. through the API), configure it.
5069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Configuration is based on the flags new-space-size (really the semispace
5070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // size) and old-space-size if set or the initial values of semispace_size_
5071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // and old_generation_size_ otherwise.
5072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!configured_) {
5073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!ConfigureHeapDefault()) return false;
5074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::CallOnce(&initialize_gc_once, &InitializeGCOnce);
5077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkMapPointersAsEncoded(false);
5079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set up memory allocator.
5081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!isolate_->memory_allocator()->SetUp(MaxReserved(), MaxExecutableSize()))
5082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return false;
5083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set up new space.
5085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!new_space_.SetUp(reserved_semispace_size_, max_semi_space_size_)) {
5086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return false;
5087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_top_after_last_gc_ = new_space()->top();
5089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize old pointer space.
5091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  old_pointer_space_ = new OldSpace(this, max_old_generation_size_,
5092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    OLD_POINTER_SPACE, NOT_EXECUTABLE);
5093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (old_pointer_space_ == NULL) return false;
5094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!old_pointer_space_->SetUp()) return false;
5095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize old data space.
5097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  old_data_space_ = new OldSpace(this, max_old_generation_size_, OLD_DATA_SPACE,
5098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 NOT_EXECUTABLE);
5099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (old_data_space_ == NULL) return false;
5100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!old_data_space_->SetUp()) return false;
5101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!isolate_->code_range()->SetUp(code_range_size_)) return false;
5103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize the code space, set its maximum capacity to the old
5105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // generation size. It needs executable memory.
5106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code_space_ =
5107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new OldSpace(this, max_old_generation_size_, CODE_SPACE, EXECUTABLE);
5108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (code_space_ == NULL) return false;
5109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!code_space_->SetUp()) return false;
5110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize map space.
5112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  map_space_ = new MapSpace(this, max_old_generation_size_, MAP_SPACE);
5113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (map_space_ == NULL) return false;
5114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!map_space_->SetUp()) return false;
5115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize simple cell space.
5117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  cell_space_ = new CellSpace(this, max_old_generation_size_, CELL_SPACE);
5118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cell_space_ == NULL) return false;
5119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!cell_space_->SetUp()) return false;
5120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize global property cell space.
5122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  property_cell_space_ = new PropertyCellSpace(this, max_old_generation_size_,
5123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               PROPERTY_CELL_SPACE);
5124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (property_cell_space_ == NULL) return false;
5125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!property_cell_space_->SetUp()) return false;
5126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The large object code space may contain code or data.  We set the memory
5128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to be non-executable here for safety, but this means we need to enable it
5129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // explicitly when allocating large code objects.
5130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  lo_space_ = new LargeObjectSpace(this, max_old_generation_size_, LO_SPACE);
5131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (lo_space_ == NULL) return false;
5132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!lo_space_->SetUp()) return false;
5133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set up the seed that is used to randomize the string hash function.
5135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(hash_seed() == 0);
5136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_randomize_hashes) {
5137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_hash_seed == 0) {
5138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int rnd = isolate()->random_number_generator()->NextInt();
5139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      set_hash_seed(Smi::FromInt(rnd & Name::kHashBitMask));
5140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
5141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      set_hash_seed(Smi::FromInt(FLAG_hash_seed));
5142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity()));
5146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOG(isolate_, IntPtrTEvent("heap-available", Available()));
5147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  store_buffer()->SetUp();
5149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mark_compact_collector()->SetUp();
5151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
5153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Heap::CreateHeapObjects() {
5157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create initial maps.
5158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!CreateInitialMaps()) return false;
5159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CreateApiObjects();
5160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create initial objects
5162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CreateInitialObjects();
5163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0, gc_count_);
5164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_native_contexts_list(undefined_value());
5166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_array_buffers_list(undefined_value());
5167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_allocation_sites_list(undefined_value());
5168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  weak_object_to_code_table_ = undefined_value();
5169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
5170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::SetStackLimits() {
5174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(isolate_ != NULL);
5175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(isolate_ == isolate());
5176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // On 64 bit machines, pointers are generally out of range of Smis.  We write
5177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // something that looks like an out of range Smi to the GC.
5178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set up the special root array entries containing the stack limits.
5180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // These are actually addresses, but the tag makes the GC ignore it.
5181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  roots_[kStackLimitRootIndex] = reinterpret_cast<Object*>(
5182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag);
5183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  roots_[kRealStackLimitRootIndex] = reinterpret_cast<Object*>(
5184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (isolate_->stack_guard()->real_jslimit() & ~kSmiTagMask) | kSmiTag);
5185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::TearDown() {
5189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
5190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_verify_heap) {
5191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Verify();
5192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
5194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UpdateMaximumCommitted();
5196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_print_cumulative_gc_stat) {
5198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("\n");
5199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("gc_count=%d ", gc_count_);
5200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("mark_sweep_count=%d ", ms_count_);
5201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("max_gc_pause=%.1f ", get_max_gc_pause());
5202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("total_gc_time=%.1f ", total_gc_time_ms_);
5203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("min_in_mutator=%.1f ", get_min_in_mutator());
5204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", get_max_alive_after_gc());
5205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("total_marking_time=%.1f ", tracer_.cumulative_sweeping_duration());
5206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("total_sweeping_time=%.1f ", tracer_.cumulative_sweeping_duration());
5207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("\n\n");
5208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_print_max_heap_committed) {
5211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("\n");
5212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("maximum_committed_by_heap=%" V8_PTR_PREFIX "d ",
5213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           MaximumCommittedMemory());
5214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("maximum_committed_by_new_space=%" V8_PTR_PREFIX "d ",
5215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           new_space_.MaximumCommittedMemory());
5216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("maximum_committed_by_old_pointer_space=%" V8_PTR_PREFIX "d ",
5217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           old_data_space_->MaximumCommittedMemory());
5218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("maximum_committed_by_old_data_space=%" V8_PTR_PREFIX "d ",
5219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           old_pointer_space_->MaximumCommittedMemory());
5220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("maximum_committed_by_old_data_space=%" V8_PTR_PREFIX "d ",
5221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           old_pointer_space_->MaximumCommittedMemory());
5222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("maximum_committed_by_code_space=%" V8_PTR_PREFIX "d ",
5223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           code_space_->MaximumCommittedMemory());
5224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("maximum_committed_by_map_space=%" V8_PTR_PREFIX "d ",
5225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           map_space_->MaximumCommittedMemory());
5226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("maximum_committed_by_cell_space=%" V8_PTR_PREFIX "d ",
5227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           cell_space_->MaximumCommittedMemory());
5228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("maximum_committed_by_property_space=%" V8_PTR_PREFIX "d ",
5229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           property_cell_space_->MaximumCommittedMemory());
5230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("maximum_committed_by_lo_space=%" V8_PTR_PREFIX "d ",
5231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           lo_space_->MaximumCommittedMemory());
5232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintF("\n\n");
5233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_verify_predictable) {
5236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintAlloctionsHash();
5237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TearDownArrayBuffers();
5240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->global_handles()->TearDown();
5242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  external_string_table_.TearDown();
5244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mark_compact_collector()->TearDown();
5246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_.TearDown();
5248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (old_pointer_space_ != NULL) {
5250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    old_pointer_space_->TearDown();
5251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    delete old_pointer_space_;
5252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    old_pointer_space_ = NULL;
5253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (old_data_space_ != NULL) {
5256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    old_data_space_->TearDown();
5257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    delete old_data_space_;
5258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    old_data_space_ = NULL;
5259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (code_space_ != NULL) {
5262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code_space_->TearDown();
5263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    delete code_space_;
5264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code_space_ = NULL;
5265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (map_space_ != NULL) {
5268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    map_space_->TearDown();
5269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    delete map_space_;
5270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    map_space_ = NULL;
5271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cell_space_ != NULL) {
5274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cell_space_->TearDown();
5275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    delete cell_space_;
5276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cell_space_ = NULL;
5277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (property_cell_space_ != NULL) {
5280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    property_cell_space_->TearDown();
5281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    delete property_cell_space_;
5282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    property_cell_space_ = NULL;
5283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (lo_space_ != NULL) {
5286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lo_space_->TearDown();
5287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    delete lo_space_;
5288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    lo_space_ = NULL;
5289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  store_buffer()->TearDown();
5292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  incremental_marking()->TearDown();
5293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->memory_allocator()->TearDown();
5295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::AddGCPrologueCallback(v8::Isolate::GCPrologueCallback callback,
5299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 GCType gc_type, bool pass_isolate) {
5300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(callback != NULL);
5301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GCPrologueCallbackPair pair(callback, gc_type, pass_isolate);
5302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!gc_prologue_callbacks_.Contains(pair));
5303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return gc_prologue_callbacks_.Add(pair);
5304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::RemoveGCPrologueCallback(v8::Isolate::GCPrologueCallback callback) {
5308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(callback != NULL);
5309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < gc_prologue_callbacks_.length(); ++i) {
5310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (gc_prologue_callbacks_[i].callback == callback) {
5311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      gc_prologue_callbacks_.Remove(i);
5312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
5313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UNREACHABLE();
5316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::AddGCEpilogueCallback(v8::Isolate::GCEpilogueCallback callback,
5320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 GCType gc_type, bool pass_isolate) {
5321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(callback != NULL);
5322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GCEpilogueCallbackPair pair(callback, gc_type, pass_isolate);
5323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!gc_epilogue_callbacks_.Contains(pair));
5324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return gc_epilogue_callbacks_.Add(pair);
5325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::RemoveGCEpilogueCallback(v8::Isolate::GCEpilogueCallback callback) {
5329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(callback != NULL);
5330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) {
5331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (gc_epilogue_callbacks_[i].callback == callback) {
5332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      gc_epilogue_callbacks_.Remove(i);
5333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
5334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UNREACHABLE();
5337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(ishell): Find a better place for this.
5341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::AddWeakObjectToCodeDependency(Handle<Object> obj,
5342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Handle<DependentCode> dep) {
5343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!InNewSpace(*obj));
5344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!InNewSpace(*dep));
5345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This handle scope keeps the table handle local to this function, which
5346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // allows us to safely skip write barriers in table update operations.
5347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate());
5348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<WeakHashTable> table(WeakHashTable::cast(weak_object_to_code_table_),
5349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              isolate());
5350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  table = WeakHashTable::Put(table, obj, dep);
5351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (ShouldZapGarbage() && weak_object_to_code_table_ != *table) {
5353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    WeakHashTable::cast(weak_object_to_code_table_)->Zap(the_hole_value());
5354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  set_weak_object_to_code_table(*table);
5356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(*dep, table->Lookup(obj));
5357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochDependentCode* Heap::LookupWeakObjectToCodeDependency(Handle<Object> obj) {
5361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* dep = WeakHashTable::cast(weak_object_to_code_table_)->Lookup(obj);
5362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (dep->IsDependentCode()) return DependentCode::cast(dep);
5363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return DependentCode::cast(empty_fixed_array());
5364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::EnsureWeakObjectToCodeTable() {
5368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!weak_object_to_code_table()->IsHashTable()) {
5369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    set_weak_object_to_code_table(
5370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        *WeakHashTable::New(isolate(), 16, USE_DEFAULT_MINIMUM_CAPACITY,
5371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            TENURED));
5372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
5377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::internal::V8::FatalProcessOutOfMemory(location, take_snapshot);
5378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
5381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass PrintHandleVisitor : public ObjectVisitor {
5383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
5384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitPointers(Object** start, Object** end) {
5385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (Object** p = start; p < end; p++)
5386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrintF("  handle %p to %p\n", reinterpret_cast<void*>(p),
5387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             reinterpret_cast<void*>(*p));
5388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
5390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::PrintHandles() {
5393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintF("Handles:\n");
5394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrintHandleVisitor v;
5395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->handle_scope_implementer()->Iterate(&v);
5396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
5399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSpace* AllSpaces::next() {
5402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (counter_++) {
5403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case NEW_SPACE:
5404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->new_space();
5405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case OLD_POINTER_SPACE:
5406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->old_pointer_space();
5407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case OLD_DATA_SPACE:
5408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->old_data_space();
5409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case CODE_SPACE:
5410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->code_space();
5411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case MAP_SPACE:
5412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->map_space();
5413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case CELL_SPACE:
5414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->cell_space();
5415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case PROPERTY_CELL_SPACE:
5416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->property_cell_space();
5417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case LO_SPACE:
5418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->lo_space();
5419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
5420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return NULL;
5421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochPagedSpace* PagedSpaces::next() {
5426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (counter_++) {
5427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case OLD_POINTER_SPACE:
5428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->old_pointer_space();
5429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case OLD_DATA_SPACE:
5430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->old_data_space();
5431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case CODE_SPACE:
5432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->code_space();
5433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case MAP_SPACE:
5434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->map_space();
5435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case CELL_SPACE:
5436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->cell_space();
5437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case PROPERTY_CELL_SPACE:
5438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->property_cell_space();
5439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
5440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return NULL;
5441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOldSpace* OldSpaces::next() {
5446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (counter_++) {
5447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case OLD_POINTER_SPACE:
5448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->old_pointer_space();
5449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case OLD_DATA_SPACE:
5450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->old_data_space();
5451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case CODE_SPACE:
5452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return heap_->code_space();
5453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
5454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return NULL;
5455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSpaceIterator::SpaceIterator(Heap* heap)
5460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : heap_(heap),
5461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      current_space_(FIRST_SPACE),
5462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      iterator_(NULL),
5463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      size_func_(NULL) {}
5464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSpaceIterator::SpaceIterator(Heap* heap, HeapObjectCallback size_func)
5467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : heap_(heap),
5468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      current_space_(FIRST_SPACE),
5469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      iterator_(NULL),
5470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      size_func_(size_func) {}
5471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSpaceIterator::~SpaceIterator() {
5474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Delete active iterator if any.
5475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete iterator_;
5476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool SpaceIterator::has_next() {
5480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Iterate until no more spaces.
5481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return current_space_ != LAST_SPACE;
5482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochObjectIterator* SpaceIterator::next() {
5486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (iterator_ != NULL) {
5487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    delete iterator_;
5488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    iterator_ = NULL;
5489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Move to the next space
5490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    current_space_++;
5491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (current_space_ > LAST_SPACE) {
5492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return NULL;
5493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return iterator for the new current space.
5497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return CreateIterator();
5498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Create an iterator for the space to iterate.
5502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochObjectIterator* SpaceIterator::CreateIterator() {
5503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(iterator_ == NULL);
5504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (current_space_) {
5506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case NEW_SPACE:
5507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      iterator_ = new SemiSpaceIterator(heap_->new_space(), size_func_);
5508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
5509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case OLD_POINTER_SPACE:
5510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      iterator_ =
5511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          new HeapObjectIterator(heap_->old_pointer_space(), size_func_);
5512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
5513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case OLD_DATA_SPACE:
5514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      iterator_ = new HeapObjectIterator(heap_->old_data_space(), size_func_);
5515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
5516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case CODE_SPACE:
5517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      iterator_ = new HeapObjectIterator(heap_->code_space(), size_func_);
5518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
5519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case MAP_SPACE:
5520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      iterator_ = new HeapObjectIterator(heap_->map_space(), size_func_);
5521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
5522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case CELL_SPACE:
5523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      iterator_ = new HeapObjectIterator(heap_->cell_space(), size_func_);
5524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
5525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case PROPERTY_CELL_SPACE:
5526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      iterator_ =
5527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          new HeapObjectIterator(heap_->property_cell_space(), size_func_);
5528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
5529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case LO_SPACE:
5530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      iterator_ = new LargeObjectIterator(heap_->lo_space(), size_func_);
5531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
5532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return the newly allocated iterator;
5535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(iterator_ != NULL);
5536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return iterator_;
5537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass HeapObjectsFilter {
5541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
5542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual ~HeapObjectsFilter() {}
5543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual bool SkipObject(HeapObject* object) = 0;
5544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
5545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass UnreachableObjectsFilter : public HeapObjectsFilter {
5548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
5549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit UnreachableObjectsFilter(Heap* heap) : heap_(heap) {
5550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MarkReachableObjects();
5551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ~UnreachableObjectsFilter() {
5554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    heap_->mark_compact_collector()->ClearMarkbits();
5555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool SkipObject(HeapObject* object) {
5558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MarkBit mark_bit = Marking::MarkBitFrom(object);
5559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return !mark_bit.Get();
5560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
5563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  class MarkingVisitor : public ObjectVisitor {
5564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
5565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MarkingVisitor() : marking_stack_(10) {}
5566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void VisitPointers(Object** start, Object** end) {
5568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (Object** p = start; p < end; p++) {
5569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (!(*p)->IsHeapObject()) continue;
5570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        HeapObject* obj = HeapObject::cast(*p);
5571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        MarkBit mark_bit = Marking::MarkBitFrom(obj);
5572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (!mark_bit.Get()) {
5573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          mark_bit.Set();
5574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          marking_stack_.Add(obj);
5575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
5576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
5577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    void TransitiveClosure() {
5580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      while (!marking_stack_.is_empty()) {
5581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        HeapObject* obj = marking_stack_.RemoveLast();
5582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        obj->Iterate(this);
5583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
5584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
5587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    List<HeapObject*> marking_stack_;
5588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
5589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MarkReachableObjects() {
5591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MarkingVisitor visitor;
5592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    heap_->IterateRoots(&visitor, VISIT_ALL);
5593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    visitor.TransitiveClosure();
5594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap* heap_;
5597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_allocation_;
5598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
5599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapIterator::HeapIterator(Heap* heap)
5602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : make_heap_iterable_helper_(heap),
5603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      no_heap_allocation_(),
5604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      heap_(heap),
5605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      filtering_(HeapIterator::kNoFiltering),
5606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      filter_(NULL) {
5607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Init();
5608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapIterator::HeapIterator(Heap* heap,
5612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           HeapIterator::HeapObjectsFiltering filtering)
5613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    : make_heap_iterable_helper_(heap),
5614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      no_heap_allocation_(),
5615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      heap_(heap),
5616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      filtering_(filtering),
5617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      filter_(NULL) {
5618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Init();
5619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapIterator::~HeapIterator() { Shutdown(); }
5623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapIterator::Init() {
5626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Start the iteration.
5627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  space_iterator_ = new SpaceIterator(heap_);
5628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (filtering_) {
5629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kFilterUnreachable:
5630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      filter_ = new UnreachableObjectsFilter(heap_);
5631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
5632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
5633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
5634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_iterator_ = space_iterator_->next();
5636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapIterator::Shutdown() {
5640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
5641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Assert that in filtering mode we have iterated through all
5642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // objects. Otherwise, heap will be left in an inconsistent state.
5643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (filtering_ != kNoFiltering) {
5644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(object_iterator_ == NULL);
5645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
5647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make sure the last iterator is deallocated.
5648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete space_iterator_;
5649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  space_iterator_ = NULL;
5650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_iterator_ = NULL;
5651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  delete filter_;
5652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  filter_ = NULL;
5653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapObject* HeapIterator::next() {
5657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (filter_ == NULL) return NextObject();
5658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* obj = NextObject();
5660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (obj != NULL && filter_->SkipObject(obj)) obj = NextObject();
5661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return obj;
5662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapObject* HeapIterator::NextObject() {
5666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // No iterator means we are done.
5667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (object_iterator_ == NULL) return NULL;
5668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (HeapObject* obj = object_iterator_->next_object()) {
5670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If the current iterator has more objects we are fine.
5671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return obj;
5672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
5673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Go though the spaces looking for one that has objects.
5674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    while (space_iterator_->has_next()) {
5675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      object_iterator_ = space_iterator_->next();
5676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (HeapObject* obj = object_iterator_->next_object()) {
5677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return obj;
5678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
5679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Done with the last space.
5682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_iterator_ = NULL;
5683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return NULL;
5684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapIterator::reset() {
5688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restart the iterator.
5689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Shutdown();
5690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Init();
5691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
5695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochObject* const PathTracer::kAnyGlobalObject = NULL;
5697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass PathTracer::MarkVisitor : public ObjectVisitor {
5699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
5700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit MarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
5701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitPointers(Object** start, Object** end) {
5702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Scan all HeapObject pointers in [start, end)
5703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (Object** p = start; !tracer_->found() && (p < end); p++) {
5704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if ((*p)->IsHeapObject()) tracer_->MarkRecursively(p, this);
5705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
5709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PathTracer* tracer_;
5710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
5711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass PathTracer::UnmarkVisitor : public ObjectVisitor {
5714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
5715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit UnmarkVisitor(PathTracer* tracer) : tracer_(tracer) {}
5716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitPointers(Object** start, Object** end) {
5717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Scan all HeapObject pointers in [start, end)
5718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (Object** p = start; p < end; p++) {
5719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if ((*p)->IsHeapObject()) tracer_->UnmarkRecursively(p, this);
5720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
5724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PathTracer* tracer_;
5725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
5726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PathTracer::VisitPointers(Object** start, Object** end) {
5729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool done = ((what_to_find_ == FIND_FIRST) && found_target_);
5730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Visit all HeapObject pointers in [start, end)
5731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (Object** p = start; !done && (p < end); p++) {
5732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if ((*p)->IsHeapObject()) {
5733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      TracePathFrom(p);
5734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      done = ((what_to_find_ == FIND_FIRST) && found_target_);
5735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PathTracer::Reset() {
5741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  found_target_ = false;
5742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_stack_.Clear();
5743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PathTracer::TracePathFrom(Object** root) {
5747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((search_target_ == kAnyGlobalObject) ||
5748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         search_target_->IsHeapObject());
5749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  found_target_in_trace_ = false;
5750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Reset();
5751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkVisitor mark_visitor(this);
5753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkRecursively(root, &mark_visitor);
5754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UnmarkVisitor unmark_visitor(this);
5756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UnmarkRecursively(root, &unmark_visitor);
5757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProcessResults();
5759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool SafeIsNativeContext(HeapObject* obj) {
5763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return obj->map() == obj->GetHeap()->raw_unchecked_native_context_map();
5764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PathTracer::MarkRecursively(Object** p, MarkVisitor* mark_visitor) {
5768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!(*p)->IsHeapObject()) return;
5769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* obj = HeapObject::cast(*p);
5771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MapWord map_word = obj->map_word();
5773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!map_word.ToMap()->IsHeapObject()) return;  // visited before
5774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (found_target_in_trace_) return;  // stop if target found
5776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  object_stack_.Add(obj);
5777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (((search_target_ == kAnyGlobalObject) && obj->IsJSGlobalObject()) ||
5778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (obj == search_target_)) {
5779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    found_target_in_trace_ = true;
5780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    found_target_ = true;
5781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
5782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_native_context = SafeIsNativeContext(obj);
5785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // not visited yet
5787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Map* map = Map::cast(map_word.ToMap());
5788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MapWord marked_map_word =
5790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MapWord::FromRawValue(obj->map_word().ToRawValue() + kMarkTag);
5791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->set_map_word(marked_map_word);
5792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Scan the object body.
5794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (is_native_context && (visit_mode_ == VISIT_ONLY_STRONG)) {
5795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This is specialized to scan Context's properly.
5796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object** start =
5797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        reinterpret_cast<Object**>(obj->address() + Context::kHeaderSize);
5798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object** end =
5799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        reinterpret_cast<Object**>(obj->address() + Context::kHeaderSize +
5800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Context::FIRST_WEAK_SLOT * kPointerSize);
5801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mark_visitor->VisitPointers(start, end);
5802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
5803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj->IterateBody(map->instance_type(), obj->SizeFromMap(map), mark_visitor);
5804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Scan the map after the body because the body is a lot more interesting
5807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // when doing leak detection.
5808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkRecursively(reinterpret_cast<Object**>(&map), mark_visitor);
5809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!found_target_in_trace_) {  // don't pop if found the target
5811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object_stack_.RemoveLast();
5812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PathTracer::UnmarkRecursively(Object** p, UnmarkVisitor* unmark_visitor) {
5817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!(*p)->IsHeapObject()) return;
5818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* obj = HeapObject::cast(*p);
5820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MapWord map_word = obj->map_word();
5822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (map_word.ToMap()->IsHeapObject()) return;  // unmarked already
5823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MapWord unmarked_map_word =
5825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MapWord::FromRawValue(map_word.ToRawValue() - kMarkTag);
5826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->set_map_word(unmarked_map_word);
5827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Map* map = Map::cast(unmarked_map_word.ToMap());
5829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UnmarkRecursively(reinterpret_cast<Object**>(&map), unmark_visitor);
5831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->IterateBody(map->instance_type(), obj->SizeFromMap(map), unmark_visitor);
5833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PathTracer::ProcessResults() {
5837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (found_target_) {
5838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OFStream os(stdout);
5839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    os << "=====================================\n"
5840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       << "====        Path to object       ====\n"
5841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       << "=====================================\n\n";
5842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!object_stack_.is_empty());
5844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < object_stack_.length(); i++) {
5845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (i > 0) os << "\n     |\n     |\n     V\n\n";
5846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      object_stack_[i]->Print(os);
5847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    os << "=====================================\n";
5849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Triggers a depth-first traversal of reachable objects from one
5854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// given root object and finds a path to a specific heap object and
5855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// prints it.
5856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::TracePathToObjectFrom(Object* target, Object* root) {
5857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PathTracer tracer(target, PathTracer::FIND_ALL, VISIT_ALL);
5858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  tracer.VisitPointer(&root);
5859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Triggers a depth-first traversal of reachable objects from roots
5863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// and finds a path to a specific heap object and prints it.
5864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::TracePathToObject(Object* target) {
5865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PathTracer tracer(target, PathTracer::FIND_ALL, VISIT_ALL);
5866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IterateRoots(&tracer, VISIT_ONLY_STRONG);
5867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Triggers a depth-first traversal of reachable objects from roots
5871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// and finds a path to any global object and prints it. Useful for
5872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// determining the source for leaks of global objects.
5873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::TracePathToGlobal() {
5874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PathTracer tracer(PathTracer::kAnyGlobalObject, PathTracer::FIND_ALL,
5875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    VISIT_ALL);
5876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  IterateRoots(&tracer, VISIT_ONLY_STRONG);
5877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
5879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::UpdateCumulativeGCStatistics(double duration,
5882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        double spent_in_mutator,
5883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        double marking_time) {
5884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_print_cumulative_gc_stat) {
5885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    total_gc_time_ms_ += duration;
5886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    max_gc_pause_ = Max(max_gc_pause_, duration);
5887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    max_alive_after_gc_ = Max(max_alive_after_gc_, SizeOfObjects());
5888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    min_in_mutator_ = Min(min_in_mutator_, spent_in_mutator);
5889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (FLAG_trace_gc_verbose) {
5890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    total_gc_time_ms_ += duration;
5891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  marking_time_ += marking_time;
5894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint KeyedLookupCache::Hash(Handle<Map> map, Handle<Name> name) {
5898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_gc;
5899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Uses only lower 32 bits if pointers are larger.
5900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uintptr_t addr_hash =
5901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<uint32_t>(reinterpret_cast<uintptr_t>(*map)) >> kMapHashShift;
5902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return static_cast<uint32_t>((addr_hash ^ name->Hash()) & kCapacityMask);
5903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint KeyedLookupCache::Lookup(Handle<Map> map, Handle<Name> name) {
5907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_gc;
5908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int index = (Hash(map, name) & kHashMask);
5909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < kEntriesPerBucket; i++) {
5910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Key& key = keys_[index + i];
5911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if ((key.map == *map) && key.name->Equals(*name)) {
5912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return field_offsets_[index + i];
5913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return kNotFound;
5916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid KeyedLookupCache::Update(Handle<Map> map, Handle<Name> name,
5920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              int field_offset) {
5921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_gc;
5922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!name->IsUniqueName()) {
5923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!StringTable::InternalizeStringIfExists(
5924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             name->GetIsolate(), Handle<String>::cast(name)).ToHandle(&name)) {
5925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
5926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This cache is cleared only between mark compact passes, so we expect the
5929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // cache to only contain old space names.
5930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!map->GetIsolate()->heap()->InNewSpace(*name));
5931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int index = (Hash(map, name) & kHashMask);
5933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // After a GC there will be free slots, so we use them in order (this may
5934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // help to get the most frequently used one in position 0).
5935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < kEntriesPerBucket; i++) {
5936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Key& key = keys_[index];
5937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* free_entry_indicator = NULL;
5938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (key.map == free_entry_indicator) {
5939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      key.map = *map;
5940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      key.name = *name;
5941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      field_offsets_[index + i] = field_offset;
5942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
5943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // No free entry found in this bucket, so we move them all down one and
5946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // put the new entry at position zero.
5947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = kEntriesPerBucket - 1; i > 0; i--) {
5948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Key& key = keys_[index + i];
5949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Key& key2 = keys_[index + i - 1];
5950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    key = key2;
5951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    field_offsets_[index + i] = field_offsets_[index + i - 1];
5952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Write the new first entry.
5955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Key& key = keys_[index];
5956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  key.map = *map;
5957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  key.name = *name;
5958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  field_offsets_[index] = field_offset;
5959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid KeyedLookupCache::Clear() {
5963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int index = 0; index < kLength; index++) keys_[index].map = NULL;
5964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid DescriptorLookupCache::Clear() {
5968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int index = 0; index < kLength; index++) keys_[index].source = NULL;
5969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ExternalStringTable::CleanUp() {
5973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int last = 0;
5974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < new_space_strings_.length(); ++i) {
5975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (new_space_strings_[i] == heap_->the_hole_value()) {
5976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      continue;
5977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(new_space_strings_[i]->IsExternalString());
5979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (heap_->InNewSpace(new_space_strings_[i])) {
5980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new_space_strings_[last++] = new_space_strings_[i];
5981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
5982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      old_space_strings_.Add(new_space_strings_[i]);
5983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_strings_.Rewind(last);
5986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_strings_.Trim();
5987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  last = 0;
5989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < old_space_strings_.length(); ++i) {
5990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (old_space_strings_[i] == heap_->the_hole_value()) {
5991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      continue;
5992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(old_space_strings_[i]->IsExternalString());
5994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!heap_->InNewSpace(old_space_strings_[i]));
5995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    old_space_strings_[last++] = old_space_strings_[i];
5996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  old_space_strings_.Rewind(last);
5998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  old_space_strings_.Trim();
5999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
6000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_verify_heap) {
6001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Verify();
6002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
6004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ExternalStringTable::TearDown() {
6008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < new_space_strings_.length(); ++i) {
6009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    heap_->FinalizeExternalString(ExternalString::cast(new_space_strings_[i]));
6010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  new_space_strings_.Free();
6012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < old_space_strings_.length(); ++i) {
6013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    heap_->FinalizeExternalString(ExternalString::cast(old_space_strings_[i]));
6014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  old_space_strings_.Free();
6016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) {
6020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  chunk->set_next_chunk(chunks_queued_for_free_);
6021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  chunks_queued_for_free_ = chunk;
6022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::FreeQueuedChunks() {
6026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (chunks_queued_for_free_ == NULL) return;
6027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryChunk* next;
6028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryChunk* chunk;
6029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) {
6030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    next = chunk->next_chunk();
6031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    chunk->SetFlag(MemoryChunk::ABOUT_TO_BE_FREED);
6032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (chunk->owner()->identity() == LO_SPACE) {
6034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // StoreBuffer::Filter relies on MemoryChunk::FromAnyPointerAddress.
6035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // If FromAnyPointerAddress encounters a slot that belongs to a large
6036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // chunk queued for deletion it will fail to find the chunk because
6037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // it try to perform a search in the list of pages owned by of the large
6038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // object space and queued chunks were detached from that list.
6039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // To work around this we split large chunk into normal kPageSize aligned
6040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // pieces and initialize size, owner and flags field of every piece.
6041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // If FromAnyPointerAddress encounters a slot that belongs to one of
6042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // these smaller pieces it will treat it as a slot on a normal Page.
6043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Address chunk_end = chunk->address() + chunk->size();
6044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MemoryChunk* inner =
6045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          MemoryChunk::FromAddress(chunk->address() + Page::kPageSize);
6046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MemoryChunk* inner_last = MemoryChunk::FromAddress(chunk_end - 1);
6047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      while (inner <= inner_last) {
6048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Size of a large chunk is always a multiple of
6049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // OS::AllocateAlignment() so there is always
6050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // enough space for a fake MemoryChunk header.
6051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Address area_end = Min(inner->address() + Page::kPageSize, chunk_end);
6052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Guard against overflow.
6053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (area_end < inner->address()) area_end = chunk_end;
6054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        inner->SetArea(inner->address(), area_end);
6055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        inner->set_size(Page::kPageSize);
6056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        inner->set_owner(lo_space());
6057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        inner->SetFlag(MemoryChunk::ABOUT_TO_BE_FREED);
6058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        inner = MemoryChunk::FromAddress(inner->address() + Page::kPageSize);
6059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
6060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
6061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->heap()->store_buffer()->Compact();
6063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED);
6064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) {
6065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    next = chunk->next_chunk();
6066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate_->memory_allocator()->Free(chunk);
6067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  chunks_queued_for_free_ = NULL;
6069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::RememberUnmappedPage(Address page, bool compacted) {
6073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uintptr_t p = reinterpret_cast<uintptr_t>(page);
6074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Tag the page pointer to make it findable in the dump file.
6075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (compacted) {
6076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    p ^= 0xc1ead & (Page::kPageSize - 1);  // Cleared.
6077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
6078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    p ^= 0x1d1ed & (Page::kPageSize - 1);  // I died.
6079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  remembered_unmapped_pages_[remembered_unmapped_pages_index_] =
6081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<Address>(p);
6082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  remembered_unmapped_pages_index_++;
6083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  remembered_unmapped_pages_index_ %= kRememberedUnmappedPages;
6084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::ClearObjectStats(bool clear_last_time_stats) {
6088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  memset(object_counts_, 0, sizeof(object_counts_));
6089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  memset(object_sizes_, 0, sizeof(object_sizes_));
6090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (clear_last_time_stats) {
6091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    memset(object_counts_last_time_, 0, sizeof(object_counts_last_time_));
6092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    memset(object_sizes_last_time_, 0, sizeof(object_sizes_last_time_));
6093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
6094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic base::LazyMutex checkpoint_object_stats_mutex = LAZY_MUTEX_INITIALIZER;
6098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Heap::CheckpointObjectStats() {
6101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::LockGuard<base::Mutex> lock_guard(
6102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      checkpoint_object_stats_mutex.Pointer());
6103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Counters* counters = isolate()->counters();
6104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ADJUST_LAST_TIME_OBJECT_COUNT(name)              \
6105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->count_of_##name()->Increment(                \
6106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_counts_[name]));           \
6107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->count_of_##name()->Decrement(                \
6108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_counts_last_time_[name])); \
6109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->size_of_##name()->Increment(                 \
6110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_sizes_[name]));            \
6111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->size_of_##name()->Decrement(                 \
6112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_sizes_last_time_[name]));
6113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT)
6114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ADJUST_LAST_TIME_OBJECT_COUNT
6115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int index;
6116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ADJUST_LAST_TIME_OBJECT_COUNT(name)               \
6117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  index = FIRST_CODE_KIND_SUB_TYPE + Code::name;          \
6118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->count_of_CODE_TYPE_##name()->Increment(       \
6119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_counts_[index]));           \
6120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->count_of_CODE_TYPE_##name()->Decrement(       \
6121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_counts_last_time_[index])); \
6122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->size_of_CODE_TYPE_##name()->Increment(        \
6123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_sizes_[index]));            \
6124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->size_of_CODE_TYPE_##name()->Decrement(        \
6125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_sizes_last_time_[index]));
6126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CODE_KIND_LIST(ADJUST_LAST_TIME_OBJECT_COUNT)
6127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ADJUST_LAST_TIME_OBJECT_COUNT
6128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ADJUST_LAST_TIME_OBJECT_COUNT(name)               \
6129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  index = FIRST_FIXED_ARRAY_SUB_TYPE + name;              \
6130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->count_of_FIXED_ARRAY_##name()->Increment(     \
6131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_counts_[index]));           \
6132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->count_of_FIXED_ARRAY_##name()->Decrement(     \
6133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_counts_last_time_[index])); \
6134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->size_of_FIXED_ARRAY_##name()->Increment(      \
6135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_sizes_[index]));            \
6136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->size_of_FIXED_ARRAY_##name()->Decrement(      \
6137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_sizes_last_time_[index]));
6138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT)
6139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ADJUST_LAST_TIME_OBJECT_COUNT
6140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ADJUST_LAST_TIME_OBJECT_COUNT(name)                                   \
6141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  index =                                                                     \
6142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FIRST_CODE_AGE_SUB_TYPE + Code::k##name##CodeAge - Code::kFirstCodeAge; \
6143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->count_of_CODE_AGE_##name()->Increment(                            \
6144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_counts_[index]));                               \
6145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->count_of_CODE_AGE_##name()->Decrement(                            \
6146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_counts_last_time_[index]));                     \
6147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->size_of_CODE_AGE_##name()->Increment(                             \
6148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_sizes_[index]));                                \
6149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  counters->size_of_CODE_AGE_##name()->Decrement(                             \
6150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<int>(object_sizes_last_time_[index]));
6151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT)
6152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ADJUST_LAST_TIME_OBJECT_COUNT
6153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_));
6155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_));
6156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ClearObjectStats();
6157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
6159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace v8::internal
6160