13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "accessors.h"
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "api.h"
32257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "bootstrapper.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "execution.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "global-handles.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ic-inl.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "natives.h"
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h"
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "runtime.h"
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "serialize.h"
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "stub-cache.h"
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8threads.h"
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Coding of external references.
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The encoding of an external reference. The type is in the high word.
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The id is in the low word.
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic uint32_t EncodeExternal(TypeCode type, uint16_t id) {
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return static_cast<uint32_t>(type) << 16 | id;
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int* GetInternalPointer(StatsCounter* counter) {
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All counters refer to dummy_counter, if deserializing happens without
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // setting up counters.
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static int dummy_counter = 0;
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return counter->Enabled() ? counter->GetInternalPointer() : &dummy_counter;
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochExternalReferenceTable* ExternalReferenceTable::instance(Isolate* isolate) {
6669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ExternalReferenceTable* external_reference_table =
6769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      isolate->external_reference_table();
6869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (external_reference_table == NULL) {
6969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    external_reference_table = new ExternalReferenceTable(isolate);
7069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    isolate->set_external_reference_table(external_reference_table);
7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
7269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return external_reference_table;
7369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ExternalReferenceTable::AddFromId(TypeCode type,
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       uint16_t id,
7844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       const char* name,
7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       Isolate* isolate) {
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address address;
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (type) {
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case C_BUILTIN: {
8344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference ref(static_cast<Builtins::CFunctionId>(id), isolate);
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      address = ref.address();
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case BUILTIN: {
8844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference ref(static_cast<Builtins::Name>(id), isolate);
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      address = ref.address();
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case RUNTIME_FUNCTION: {
9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference ref(static_cast<Runtime::FunctionId>(id), isolate);
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      address = ref.address();
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case IC_UTILITY: {
9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReference ref(IC_Utility(static_cast<IC::UtilityId>(id)),
9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            isolate);
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      address = ref.address();
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNREACHABLE();
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Add(address, type, id, name);
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ExternalReferenceTable::Add(Address address,
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 TypeCode type,
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 uint16_t id,
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 const char* name) {
115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT_NE(NULL, address);
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReferenceEntry entry;
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  entry.address = address;
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  entry.code = EncodeExternal(type, id);
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  entry.name = name;
120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT_NE(0, entry.code);
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  refs_.Add(entry);
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (id > max_id_[type]) max_id_[type] = id;
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid ExternalReferenceTable::PopulateTable(Isolate* isolate) {
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int type_code = 0; type_code < kTypeCodeCount; type_code++) {
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    max_id_[type_code] = 0;
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The following populates all of the different type of external references
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // into the ExternalReferenceTable.
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // NOTE: This function was originally 100k of code.  It has since been
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rewritten to be mostly table driven, as the callback macro style tends to
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // very easily cause code bloat.  Please be careful in the future when adding
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // new references.
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  struct RefTableEntry {
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    TypeCode type;
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint16_t id;
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* name;
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const RefTableEntry ref_table[] = {
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Builtins
147e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#define DEF_ENTRY_C(name, ignored) \
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { C_BUILTIN, \
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Builtins::c_##name, \
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "Builtins::" #name },
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BUILTIN_LIST_C(DEF_ENTRY_C)
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DEF_ENTRY_C
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
155e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#define DEF_ENTRY_C(name, ignored) \
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { BUILTIN, \
15744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Builtins::k##name, \
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "Builtins::" #name },
1591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#define DEF_ENTRY_A(name, kind, state, extra) DEF_ENTRY_C(name, ignored)
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BUILTIN_LIST_C(DEF_ENTRY_C)
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BUILTIN_LIST_A(DEF_ENTRY_A)
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BUILTIN_LIST_DEBUG_A(DEF_ENTRY_A)
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DEF_ENTRY_C
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DEF_ENTRY_A
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Runtime functions
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define RUNTIME_ENTRY(name, nargs, ressize) \
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { RUNTIME_FUNCTION, \
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Runtime::k##name, \
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "Runtime::" #name },
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RUNTIME_FUNCTION_LIST(RUNTIME_ENTRY)
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef RUNTIME_ENTRY
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // IC utilities
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define IC_ENTRY(name) \
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { IC_UTILITY, \
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    IC::k##name, \
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "IC::" #name },
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  IC_UTIL_LIST(IC_ENTRY)
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef IC_ENTRY
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };  // end of ref_table[].
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (size_t i = 0; i < ARRAY_SIZE(ref_table); ++i) {
18744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    AddFromId(ref_table[i].type,
18844f0eee88ff00398ff7f715fab053374d808c90dSteve Block              ref_table[i].id,
18944f0eee88ff00398ff7f715fab053374d808c90dSteve Block              ref_table[i].name,
19044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              isolate);
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Debug addresses
19544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(Debug_Address(Debug::k_after_break_target_address).address(isolate),
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      DEBUG_ADDRESS,
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Debug::k_after_break_target_address << kDebugIdShift,
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Debug::after_break_target_address()");
19944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(Debug_Address(Debug::k_debug_break_slot_address).address(isolate),
2007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      DEBUG_ADDRESS,
2017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      Debug::k_debug_break_slot_address << kDebugIdShift,
2027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      "Debug::debug_break_slot_address()");
20344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(Debug_Address(Debug::k_debug_break_return_address).address(isolate),
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      DEBUG_ADDRESS,
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Debug::k_debug_break_return_address << kDebugIdShift,
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Debug::debug_break_return_address()");
20744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(Debug_Address(Debug::k_restarter_frame_function_pointer).address(isolate),
208bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      DEBUG_ADDRESS,
209bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      Debug::k_restarter_frame_function_pointer << kDebugIdShift,
210bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      "Debug::restarter_frame_function_pointer_address()");
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stat counters
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  struct StatsRefTableEntry {
21544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    StatsCounter* (Counters::*counter)();
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint16_t id;
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const char* name;
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const StatsRefTableEntry stats_ref_table[] = {
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define COUNTER_ENTRY(name, caption) \
22244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  { &Counters::name,    \
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Counters::k_##name, \
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "Counters::" #name },
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  STATS_COUNTER_LIST_1(COUNTER_ENTRY)
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  STATS_COUNTER_LIST_2(COUNTER_ENTRY)
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef COUNTER_ENTRY
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };  // end of stats_ref_table[].
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Counters* counters = isolate->counters();
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (size_t i = 0; i < ARRAY_SIZE(stats_ref_table); ++i) {
23344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Add(reinterpret_cast<Address>(GetInternalPointer(
23444f0eee88ff00398ff7f715fab053374d808c90dSteve Block            (counters->*(stats_ref_table[i].counter))())),
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        STATS_COUNTER,
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        stats_ref_table[i].id,
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        stats_ref_table[i].name);
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Top addresses
2413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  const char* AddressNames[] = {
243589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#define BUILD_NAME_LITERAL(CamelName, hacker_name)      \
244589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    "Isolate::" #hacker_name "_address",
245589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    FOR_EACH_ISOLATE_ADDRESS_NAME(BUILD_NAME_LITERAL)
2463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    NULL
2473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#undef C
2483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  };
2493ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
250589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  for (uint16_t i = 0; i < Isolate::kIsolateAddressCount; ++i) {
25144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Add(isolate->get_address_from_id((Isolate::AddressId)i),
25244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        TOP_ADDRESS, i, AddressNames[i]);
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Accessors
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESSOR_DESCRIPTOR_DECLARATION(name) \
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Add((Address)&Accessors::name, \
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ACCESSOR, \
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Accessors::k##name, \
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Accessors::" #name);
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ACCESSOR_DESCRIPTOR_LIST(ACCESSOR_DESCRIPTOR_DECLARATION)
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef ACCESSOR_DESCRIPTOR_DECLARATION
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  StubCache* stub_cache = isolate->stub_cache();
26644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Stub cache tables
26844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(stub_cache->key_reference(StubCache::kPrimary).address(),
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      STUB_CACHE_TABLE,
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      1,
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "StubCache::primary_->key");
27244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(stub_cache->value_reference(StubCache::kPrimary).address(),
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      STUB_CACHE_TABLE,
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      2,
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "StubCache::primary_->value");
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Add(stub_cache->map_reference(StubCache::kPrimary).address(),
2775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      STUB_CACHE_TABLE,
27885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      3,
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "StubCache::primary_->map");
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Add(stub_cache->key_reference(StubCache::kSecondary).address(),
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      STUB_CACHE_TABLE,
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      4,
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "StubCache::secondary_->key");
28444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(stub_cache->value_reference(StubCache::kSecondary).address(),
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      STUB_CACHE_TABLE,
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      5,
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "StubCache::secondary_->value");
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Add(stub_cache->map_reference(StubCache::kSecondary).address(),
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      STUB_CACHE_TABLE,
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      6,
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "StubCache::secondary_->map");
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Runtime entries
29444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::perform_gc_function(isolate).address(),
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      RUNTIME_ENTRY,
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      1,
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Runtime::PerformGC");
29844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::fill_heap_number_with_random_function(
29944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          isolate).address(),
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      RUNTIME_ENTRY,
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      2,
3026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "V8::FillHeapNumberWithRandom");
30344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::random_uint32_function(isolate).address(),
3046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      RUNTIME_ENTRY,
3056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      3,
3066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      "V8::Random");
30744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::delete_handle_scope_extensions(isolate).address(),
3085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      RUNTIME_ENTRY,
3091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      4,
3105913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      "HandleScope::DeleteExtensions");
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Add(ExternalReference::
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          incremental_marking_record_write_function(isolate).address(),
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RUNTIME_ENTRY,
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      5,
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "IncrementalMarking::RecordWrite");
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Add(ExternalReference::store_buffer_overflow_function(isolate).address(),
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RUNTIME_ENTRY,
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      6,
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "StoreBuffer::StoreBufferOverflow");
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Add(ExternalReference::
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          incremental_evacuation_record_write_function(isolate).address(),
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RUNTIME_ENTRY,
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      7,
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "IncrementalMarking::RecordWrite");
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3275913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Miscellaneous
3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Add(ExternalReference::roots_array_start(isolate).address(),
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      3,
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "Heap::roots_array_start()");
33344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::address_of_stack_limit(isolate).address(),
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      4,
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "StackGuard::address_of_jslimit()");
33744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::address_of_real_stack_limit(isolate).address(),
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      5,
340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      "StackGuard::address_of_real_jslimit()");
3413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch#ifndef V8_INTERPRETED_REGEXP
34244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::address_of_regexp_stack_limit(isolate).address(),
343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNCLASSIFIED,
344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      6,
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "RegExpStack::limit_address()");
34644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::address_of_regexp_stack_memory_address(
34744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          isolate).address(),
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
349d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      7,
3509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "RegExpStack::memory_address()");
35144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::address_of_regexp_stack_memory_size(isolate).address(),
3529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      UNCLASSIFIED,
3539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      8,
3549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "RegExpStack::memory_size()");
35544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::address_of_static_offsets_vector(isolate).address(),
3569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      UNCLASSIFIED,
3579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      9,
3589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "OffsetsVector::static_offsets_vector");
3593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch#endif  // V8_INTERPRETED_REGEXP
36044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::new_space_start(isolate).address(),
3619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      UNCLASSIFIED,
3629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      10,
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Heap::NewSpaceStart()");
36444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::new_space_mask(isolate).address(),
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
3669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      11,
367402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "Heap::NewSpaceMask()");
36844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::heap_always_allocate_scope_depth(isolate).address(),
369402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      UNCLASSIFIED,
3709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      12,
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Heap::always_allocate_scope_depth()");
37244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::new_space_allocation_limit_address(isolate).address(),
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      14,
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Heap::NewSpaceAllocationLimitAddress()");
37644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::new_space_allocation_top_address(isolate).address(),
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      15,
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Heap::NewSpaceAllocationTopAddress()");
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
38144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::debug_break(isolate).address(),
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      16,
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Debug::Break()");
38544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::debug_step_in_fp_address(isolate).address(),
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      17,
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "Debug::step_in_fp_addr()");
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
39044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::double_fp_operation(Token::ADD, isolate).address(),
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      18,
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "add_two_doubles");
39444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::double_fp_operation(Token::SUB, isolate).address(),
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      19,
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "sub_two_doubles");
39844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::double_fp_operation(Token::MUL, isolate).address(),
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      20,
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "mul_two_doubles");
40244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::double_fp_operation(Token::DIV, isolate).address(),
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      21,
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "div_two_doubles");
40644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::double_fp_operation(Token::MOD, isolate).address(),
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      22,
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "mod_two_doubles");
41044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::compare_doubles(isolate).address(),
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      23,
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "compare_doubles");
4146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifndef V8_INTERPRETED_REGEXP
41544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::re_case_insensitive_compare_uc16(isolate).address(),
4166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      UNCLASSIFIED,
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      24,
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()");
41944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::re_check_stack_guard_state(isolate).address(),
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      25,
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "RegExpMacroAssembler*::CheckStackGuardState()");
42344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::re_grow_stack(isolate).address(),
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      UNCLASSIFIED,
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      26,
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      "NativeRegExpMacroAssembler::GrowStack()");
427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Add(ExternalReference::re_word_character_map().address(),
428e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNCLASSIFIED,
4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      27,
430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "NativeRegExpMacroAssembler::word_character_map");
4316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif  // V8_INTERPRETED_REGEXP
432e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Keyed lookup cache.
43344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::keyed_lookup_cache_keys(isolate).address(),
434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNCLASSIFIED,
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      28,
436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "KeyedLookupCache::keys()");
43744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::keyed_lookup_cache_field_offsets(isolate).address(),
438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      UNCLASSIFIED,
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      29,
440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      "KeyedLookupCache::field_offsets()");
44144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::transcendental_cache_array_address(isolate).address(),
442402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      UNCLASSIFIED,
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      30,
444402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      "TranscendentalCache::caches()");
4455913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Add(ExternalReference::handle_scope_next_address().address(),
4465913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      UNCLASSIFIED,
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      31,
4485913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      "HandleScope::next");
4495913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Add(ExternalReference::handle_scope_limit_address().address(),
4505913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      UNCLASSIFIED,
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      32,
4525913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      "HandleScope::limit");
4535913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  Add(ExternalReference::handle_scope_level_address().address(),
4545913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      UNCLASSIFIED,
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      33,
4565913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      "HandleScope::level");
45744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::new_deoptimizer_function(isolate).address(),
458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNCLASSIFIED,
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      34,
460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "Deoptimizer::New()");
46144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::compute_output_frames_function(isolate).address(),
462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNCLASSIFIED,
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      35,
464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "Deoptimizer::ComputeOutputFrames()");
465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Add(ExternalReference::address_of_min_int().address(),
466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNCLASSIFIED,
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      36,
468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "LDoubleConstant::min_int");
469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Add(ExternalReference::address_of_one_half().address(),
470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNCLASSIFIED,
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      37,
472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "LDoubleConstant::one_half");
47344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::isolate_address().address(),
474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNCLASSIFIED,
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      38,
47644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      "isolate");
47744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::address_of_minus_zero().address(),
47844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      UNCLASSIFIED,
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      39,
480b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      "LDoubleConstant::minus_zero");
481b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Add(ExternalReference::address_of_negative_infinity().address(),
482b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      UNCLASSIFIED,
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      40,
484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "LDoubleConstant::negative_infinity");
48544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::power_double_double_function(isolate).address(),
486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNCLASSIFIED,
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      41,
488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "power_double_double_function");
48944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Add(ExternalReference::power_double_int_function(isolate).address(),
490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNCLASSIFIED,
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      42,
492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      "power_double_int_function");
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Add(ExternalReference::store_buffer_top(isolate).address(),
494592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      UNCLASSIFIED,
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      43,
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "store_buffer_top");
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Add(ExternalReference::address_of_canonical_non_hole_nan().address(),
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNCLASSIFIED,
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      44,
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "canonical_nan");
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Add(ExternalReference::address_of_the_hole_nan().address(),
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNCLASSIFIED,
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      45,
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "the_hole_nan");
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Add(ExternalReference::get_date_field_function(isolate).address(),
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNCLASSIFIED,
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      46,
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "JSDate::GetField");
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Add(ExternalReference::date_cache_stamp(isolate).address(),
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNCLASSIFIED,
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      47,
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "date_cache_stamp");
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExternalReferenceEncoder::ExternalReferenceEncoder()
51744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : encodings_(Match),
51844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate_(Isolate::Current()) {
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReferenceTable* external_references =
52044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReferenceTable::instance(isolate_);
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < external_references->size(); ++i) {
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Put(external_references->address(i), i);
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuint32_t ExternalReferenceEncoder::Encode(Address key) const {
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int index = IndexOf(key);
529bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT(key == NULL || index >= 0);
53044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return index >=0 ?
53144f0eee88ff00398ff7f715fab053374d808c90dSteve Block         ExternalReferenceTable::instance(isolate_)->code(index) : 0;
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* ExternalReferenceEncoder::NameOfAddress(Address key) const {
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int index = IndexOf(key);
53744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return index >= 0 ?
53844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReferenceTable::instance(isolate_)->name(index) : NULL;
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint ExternalReferenceEncoder::IndexOf(Address key) const {
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (key == NULL) return -1;
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HashMap::Entry* entry =
54544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      const_cast<HashMap&>(encodings_).Lookup(key, Hash(key), false);
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return entry == NULL
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ? -1
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ExternalReferenceEncoder::Put(Address key, int index) {
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HashMap::Entry* entry = encodings_.Lookup(key, Hash(key), true);
5546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  entry->value = reinterpret_cast<void*>(index);
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExternalReferenceDecoder::ExternalReferenceDecoder()
55944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : encodings_(NewArray<Address*>(kTypeCodeCount)),
56044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate_(Isolate::Current()) {
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReferenceTable* external_references =
56244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ExternalReferenceTable::instance(isolate_);
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int max = external_references->max_id(type) + 1;
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    encodings_[type] = NewArray<Address>(max + 1);
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < external_references->size(); ++i) {
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Put(external_references->code(i), external_references->address(i));
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExternalReferenceDecoder::~ExternalReferenceDecoder() {
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    DeleteArray(encodings_[type]);
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DeleteArray(encodings_);
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool Serializer::serialization_enabled_ = false;
582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool Serializer::too_late_to_enable_now_ = false;
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
58544f0eee88ff00398ff7f715fab053374d808c90dSteve BlockDeserializer::Deserializer(SnapshotByteSource* source)
58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : isolate_(NULL),
58744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      source_(source),
58844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      external_reference_decoder_(NULL) {
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// This routine both allocates a new object, and also keeps
593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// track of where objects have been allocated so that we can
594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// fix back references when deserializing.
595d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockAddress Deserializer::Allocate(int space_index, Space* space, int size) {
596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address address;
597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (!SpaceIsLarge(space_index)) {
598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(!SpaceIsPaged(space_index) ||
599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block           size <= Page::kPageSize - Page::kObjectStartOffset);
6005913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    MaybeObject* maybe_new_allocation;
601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (space_index == NEW_SPACE) {
6025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      maybe_new_allocation =
6035913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck          reinterpret_cast<NewSpace*>(space)->AllocateRaw(size);
604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
6055913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      maybe_new_allocation =
6065913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck          reinterpret_cast<PagedSpace*>(space)->AllocateRaw(size);
607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
6083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!maybe_new_allocation->IsFailure());
6095913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Object* new_allocation = maybe_new_allocation->ToObjectUnchecked();
610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    HeapObject* new_object = HeapObject::cast(new_allocation);
611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    address = new_object->address();
612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    high_water_[space_index] = address + size;
613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(SpaceIsLarge(space_index));
615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    LargeObjectSpace* lo_space = reinterpret_cast<LargeObjectSpace*>(space);
616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Object* new_allocation;
6173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (space_index == kLargeData || space_index == kLargeFixedArray) {
6185913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck      new_allocation =
6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          lo_space->AllocateRaw(size, NOT_EXECUTABLE)->ToObjectUnchecked();
620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
621d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      ASSERT_EQ(kLargeCode, space_index);
6223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new_allocation =
6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          lo_space->AllocateRaw(size, EXECUTABLE)->ToObjectUnchecked();
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    HeapObject* new_object = HeapObject::cast(new_allocation);
626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Record all large objects in the same space.
627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    address = new_object->address();
6283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    pages_[LO_SPACE].Add(address);
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  last_object_address_ = address;
631d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return address;
632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
635d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// This returns the address of an object that has been described in the
636d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// snapshot as being offset bytes back in a particular space.
637d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockHeapObject* Deserializer::GetAddressFromEnd(int space) {
638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int offset = source_->GetInt();
639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(!SpaceIsLarge(space));
640d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  offset <<= kObjectAlignmentBits;
641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return HeapObject::FromAddress(high_water_[space] - offset);
642d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// This returns the address of an object that has been described in the
646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// snapshot as being offset bytes into a particular space.
647d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockHeapObject* Deserializer::GetAddressFromStart(int space) {
648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int offset = source_->GetInt();
649d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (SpaceIsLarge(space)) {
650d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Large spaces have one object per 'page'.
651d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return HeapObject::FromAddress(pages_[LO_SPACE][offset]);
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  offset <<= kObjectAlignmentBits;
654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (space == NEW_SPACE) {
655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // New space has only one space - numbered 0.
656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return HeapObject::FromAddress(pages_[space][0] + offset);
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(SpaceIsPaged(space));
659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  int page_of_pointee = offset >> kPageSizeBits;
660d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address object_address = pages_[space][page_of_pointee] +
661d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           (offset & Page::kPageAlignmentMask);
662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return HeapObject::FromAddress(object_address);
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Deserializer::Deserialize() {
66744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_ = Isolate::Current();
6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(isolate_ != NULL);
669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Don't GC while deserializing - just expand the heap.
670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  AlwaysAllocateScope always_allocate;
671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Don't use the free lists while deserializing.
672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  LinearAllocationScope allocate_linearly;
673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // No active threads.
67444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse());
675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // No active handles.
67644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(isolate_->handle_scope_implementer()->blocks()->is_empty());
677d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Make sure the entire partial snapshot cache is traversed, filling it with
678d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // valid object pointers.
67944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_->set_serialize_partial_snapshot_cache_length(
68044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Isolate::kPartialSnapshotCacheCapacity);
681d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT_EQ(NULL, external_reference_decoder_);
682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  external_reference_decoder_ = new ExternalReferenceDecoder();
68344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
68444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_->heap()->IterateWeakRoots(this, VISIT_ALL);
685f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
68644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_->heap()->set_global_contexts_list(
68744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate_->heap()->undefined_value());
6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Update data pointers to the external strings containing natives sources.
6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Object* source = isolate_->heap()->natives_source_cache()->get(i);
6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!source->IsUndefined()) {
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExternalAsciiString::cast(source)->update_data_cache();
6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Deserializer::DeserializePartial(Object** root) {
70044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_ = Isolate::Current();
701e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Don't GC while deserializing - just expand the heap.
702e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  AlwaysAllocateScope always_allocate;
703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Don't use the free lists while deserializing.
704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  LinearAllocationScope allocate_linearly;
705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (external_reference_decoder_ == NULL) {
706e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    external_reference_decoder_ = new ExternalReferenceDecoder();
707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
708e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  VisitPointer(root);
709e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
710e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
711e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
712d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeDeserializer::~Deserializer() {
713d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(source_->AtEOF());
71444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (external_reference_decoder_) {
715e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    delete external_reference_decoder_;
716e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    external_reference_decoder_ = NULL;
717e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// This is called on the roots.  It is the driver of the deserialization
722d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// process.  It is also called on the body of each function.
723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Deserializer::VisitPointers(Object** start, Object** end) {
724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // The space must be new space.  Any other space would cause ReadChunk to try
725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // to update the remembered using NULL as the address.
726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ReadChunk(start, end, NEW_SPACE, NULL);
727d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
728d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// This routine writes the new object into the pointer provided and then
731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// returns true if the new object was in young space and false otherwise.
732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// The reason for this strange interface is that otherwise the object is
7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// written very late, which means the FreeSpace map is not set up by the
7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// time we need to use it to mark the space at the end of a page free.
735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Deserializer::ReadObject(int space_number,
736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                              Space* space,
737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                              Object** write_back) {
738d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int size = source_->GetInt() << kObjectAlignmentBits;
739d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address address = Allocate(space_number, space, size);
740d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  *write_back = HeapObject::FromAddress(address);
741d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Object** current = reinterpret_cast<Object**>(address);
742d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Object** limit = current + (size >> kPointerSizeLog2);
743e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (FLAG_log_snapshot_positions) {
74444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LOG(isolate_, SnapshotPositionEvent(address, source_->position()));
745e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
746d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ReadChunk(current, limit, space_number, address);
74744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
74844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool is_codespace = (space == HEAP->code_space()) ||
74944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ((space == HEAP->lo_space()) && (space_number == kLargeCode));
75044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(HeapObject::FromAddress(address)->IsCode() == is_codespace);
75144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
752d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
753d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
754d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// This macro is always used with a constant argument so it should all fold
756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// away to almost nothing in the generated code.  It might be nicer to do this
757f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// with the ternary operator but there are type issues with that.
758f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#define ASSIGN_DEST_SPACE(space_number)                                        \
759f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Space* dest_space;                                                           \
760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (space_number == NEW_SPACE) {                                             \
76144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    dest_space = isolate->heap()->new_space();                                \
762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (space_number == OLD_POINTER_SPACE) {                              \
76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    dest_space = isolate->heap()->old_pointer_space();                         \
764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (space_number == OLD_DATA_SPACE) {                                 \
76544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    dest_space = isolate->heap()->old_data_space();                            \
766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (space_number == CODE_SPACE) {                                     \
76744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    dest_space = isolate->heap()->code_space();                                \
768f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (space_number == MAP_SPACE) {                                      \
76944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    dest_space = isolate->heap()->map_space();                                 \
770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if (space_number == CELL_SPACE) {                                     \
77144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    dest_space = isolate->heap()->cell_space();                                \
772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {                                                                     \
773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    ASSERT(space_number >= LO_SPACE);                                          \
77444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    dest_space = isolate->heap()->lo_space();                                  \
775f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
776f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkestatic const int kUnknownOffsetFromStart = -1;
779d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
781d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Deserializer::ReadChunk(Object** current,
782d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                             Object** limit,
783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                             int source_space,
7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             Address current_object_address) {
78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* const isolate = isolate_;
7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool write_barrier_needed = (current_object_address != NULL &&
7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               source_space != NEW_SPACE &&
7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               source_space != CELL_SPACE &&
7893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               source_space != CODE_SPACE &&
7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               source_space != OLD_DATA_SPACE);
791d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  while (current < limit) {
792d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    int data = source_->Get();
793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    switch (data) {
794f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#define CASE_STATEMENT(where, how, within, space_number)                       \
795f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      case where + how + within + space_number:                                \
796f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      ASSERT((where & ~kPointedToMask) == 0);                                  \
797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      ASSERT((how & ~kHowToCodeMask) == 0);                                    \
798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      ASSERT((within & ~kWhereToPointMask) == 0);                              \
799f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      ASSERT((space_number & ~kSpaceMask) == 0);
800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
801f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#define CASE_BODY(where, how, within, space_number_if_any, offset_from_start)  \
802f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      {                                                                        \
803f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        bool emit_write_barrier = false;                                       \
804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        bool current_was_incremented = false;                                  \
805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        int space_number =  space_number_if_any == kAnyOldSpace ?              \
806f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                            (data & kSpaceMask) : space_number_if_any;         \
807f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (where == kNewObject && how == kPlain && within == kStartOfObject) {\
808f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          ASSIGN_DEST_SPACE(space_number)                                      \
809f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          ReadObject(space_number, dest_space, current);                       \
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          emit_write_barrier = (space_number == NEW_SPACE);                    \
811f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        } else {                                                               \
812f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          Object* new_object = NULL;  /* May not be a real Object pointer. */  \
813f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (where == kNewObject) {                                           \
814f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            ASSIGN_DEST_SPACE(space_number)                                    \
815f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            ReadObject(space_number, dest_space, &new_object);                 \
816f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          } else if (where == kRootArray) {                                    \
817f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            int root_id = source_->GetInt();                                   \
8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            new_object = isolate->heap()->roots_array_start()[root_id];        \
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            emit_write_barrier = isolate->heap()->InNewSpace(new_object);      \
820f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          } else if (where == kPartialSnapshotCache) {                         \
821f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            int cache_index = source_->GetInt();                               \
82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block            new_object = isolate->serialize_partial_snapshot_cache()           \
82344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                [cache_index];                                                 \
8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            emit_write_barrier = isolate->heap()->InNewSpace(new_object);      \
825f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          } else if (where == kExternalReference) {                            \
826f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            int reference_id = source_->GetInt();                              \
82744f0eee88ff00398ff7f715fab053374d808c90dSteve Block            Address address = external_reference_decoder_->                    \
82844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                Decode(reference_id);                                          \
829f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            new_object = reinterpret_cast<Object*>(address);                   \
830f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          } else if (where == kBackref) {                                      \
8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            emit_write_barrier = (space_number == NEW_SPACE);                  \
832f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            new_object = GetAddressFromEnd(data & kSpaceMask);                 \
833f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          } else {                                                             \
834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            ASSERT(where == kFromStart);                                       \
835f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            if (offset_from_start == kUnknownOffsetFromStart) {                \
8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              emit_write_barrier = (space_number == NEW_SPACE);                \
837f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke              new_object = GetAddressFromStart(data & kSpaceMask);             \
838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            } else {                                                           \
839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke              Address object_address = pages_[space_number][0] +               \
840f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                  (offset_from_start << kObjectAlignmentBits);                 \
841f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke              new_object = HeapObject::FromAddress(object_address);            \
842f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            }                                                                  \
843f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          }                                                                    \
844f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (within == kFirstInstruction) {                                   \
845f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Code* new_code_object = reinterpret_cast<Code*>(new_object);       \
846f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            new_object = reinterpret_cast<Object*>(                            \
847f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                new_code_object->instruction_start());                         \
848f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          }                                                                    \
849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          if (how == kFromCode) {                                              \
850f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            Address location_of_branch_data =                                  \
851f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                reinterpret_cast<Address>(current);                            \
8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Assembler::deserialization_set_special_target_at(                  \
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                location_of_branch_data,                                       \
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                reinterpret_cast<Address>(new_object));                        \
8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            location_of_branch_data += Assembler::kSpecialTargetSize;          \
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            current = reinterpret_cast<Object**>(location_of_branch_data);     \
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            current_was_incremented = true;                                    \
858f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          } else {                                                             \
859f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke            *current = new_object;                                             \
860f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke          }                                                                    \
861f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }                                                                      \
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (emit_write_barrier && write_barrier_needed) {                      \
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Address current_address = reinterpret_cast<Address>(current);        \
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          isolate->heap()->RecordWrite(                                        \
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              current_object_address,                                          \
8663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              static_cast<int>(current_address - current_object_address));     \
867f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }                                                                      \
868f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        if (!current_was_incremented) {                                        \
8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          current++;                                                           \
870f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        }                                                                      \
871f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        break;                                                                 \
872f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      }                                                                        \
873f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
874f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// This generates a case and a body for each space.  The large object spaces are
875f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// very rare in snapshots so they are grouped in one body.
876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#define ONE_PER_SPACE(where, how, within)                                      \
877f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, NEW_SPACE)                                \
878f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_BODY(where, how, within, NEW_SPACE, kUnknownOffsetFromStart)            \
879f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, OLD_DATA_SPACE)                           \
880f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_BODY(where, how, within, OLD_DATA_SPACE, kUnknownOffsetFromStart)       \
881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE)                        \
882f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_BODY(where, how, within, OLD_POINTER_SPACE, kUnknownOffsetFromStart)    \
883f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, CODE_SPACE)                               \
884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_BODY(where, how, within, CODE_SPACE, kUnknownOffsetFromStart)           \
885f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, CELL_SPACE)                               \
886f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_BODY(where, how, within, CELL_SPACE, kUnknownOffsetFromStart)           \
887f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, MAP_SPACE)                                \
888f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_BODY(where, how, within, MAP_SPACE, kUnknownOffsetFromStart)            \
889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, kLargeData)                               \
890f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, kLargeCode)                               \
891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, kLargeFixedArray)                         \
892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_BODY(where, how, within, kAnyOldSpace, kUnknownOffsetFromStart)
893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// This generates a case and a body for the new space (which has to do extra
895f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// write barrier handling) and handles the other spaces with 8 fall-through
896f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// cases and one body.
897f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#define ALL_SPACES(where, how, within)                                         \
898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, NEW_SPACE)                                \
899f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_BODY(where, how, within, NEW_SPACE, kUnknownOffsetFromStart)            \
900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, OLD_DATA_SPACE)                           \
901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE)                        \
902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, CODE_SPACE)                               \
903f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, CELL_SPACE)                               \
904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, MAP_SPACE)                                \
905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, kLargeData)                               \
906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, kLargeCode)                               \
907f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_STATEMENT(where, how, within, kLargeFixedArray)                         \
908f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  CASE_BODY(where, how, within, kAnyOldSpace, kUnknownOffsetFromStart)
909f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
910791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block#define ONE_PER_CODE_SPACE(where, how, within)                                 \
911791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  CASE_STATEMENT(where, how, within, CODE_SPACE)                               \
912791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  CASE_BODY(where, how, within, CODE_SPACE, kUnknownOffsetFromStart)           \
913791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  CASE_STATEMENT(where, how, within, kLargeCode)                               \
91444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CASE_BODY(where, how, within, kLargeCode, kUnknownOffsetFromStart)
915791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define FOUR_CASES(byte_code)             \
9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  case byte_code:                         \
9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  case byte_code + 1:                     \
9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  case byte_code + 2:                     \
9203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  case byte_code + 3:
9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define SIXTEEN_CASES(byte_code)          \
9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FOUR_CASES(byte_code)                   \
9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FOUR_CASES(byte_code + 4)               \
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FOUR_CASES(byte_code + 8)               \
9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FOUR_CASES(byte_code + 12)
927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // We generate 15 cases and bodies that process special tags that combine
929f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // the raw data tag and the length into one byte.
930d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#define RAW_CASE(index, size)                                      \
931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      case kRawData + index: {                                     \
932d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        byte* raw_data_out = reinterpret_cast<byte*>(current);     \
933d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        source_->CopyRaw(raw_data_out, size);                      \
934d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        current = reinterpret_cast<Object**>(raw_data_out + size); \
935d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;                                                     \
936d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      COMMON_RAW_LENGTHS(RAW_CASE)
938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef RAW_CASE
939f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Deserialize a chunk of raw data that doesn't have one of the popular
941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // lengths.
942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      case kRawData: {
943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        int size = source_->GetInt();
944d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        byte* raw_data_out = reinterpret_cast<byte*>(current);
945d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        source_->CopyRaw(raw_data_out, size);
946d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        current = reinterpret_cast<Object**>(raw_data_out + size);
947d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
948d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
949f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SIXTEEN_CASES(kRootArrayLowConstants)
9513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SIXTEEN_CASES(kRootArrayHighConstants) {
9523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int root_id = RootArrayConstantFromByteCode(data);
9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Object* object = isolate->heap()->roots_array_start()[root_id];
9543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(!isolate->heap()->InNewSpace(object));
9553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *current++ = object;
9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case kRepeat: {
9603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int repeats = source_->GetInt();
9613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Object* object = current[-1];
9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(!isolate->heap()->InNewSpace(object));
9633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for (int i = 0; i < repeats; i++) current[i] = object;
9643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        current += repeats;
9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
9663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
9673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      STATIC_ASSERT(kRootArrayNumberOfConstantEncodings ==
9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    Heap::kOldSpaceRoots);
9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      STATIC_ASSERT(kMaxRepeats == 12);
9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FOUR_CASES(kConstantRepeat)
9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FOUR_CASES(kConstantRepeat + 4)
9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FOUR_CASES(kConstantRepeat + 8) {
9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int repeats = RepeatsForCode(data);
9753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Object* object = current[-1];
9763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(!isolate->heap()->InNewSpace(object));
9773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for (int i = 0; i < repeats; i++) current[i] = object;
9783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        current += repeats;
9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
9803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
982f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Deserialize a new object and write a pointer to it to the current
983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // object.
984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      ONE_PER_SPACE(kNewObject, kPlain, kStartOfObject)
985791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      // Support for direct instruction pointers in functions
986791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      ONE_PER_CODE_SPACE(kNewObject, kPlain, kFirstInstruction)
987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Deserialize a new code object and write a pointer to its first
988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // instruction to the current code object.
989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      ONE_PER_SPACE(kNewObject, kFromCode, kFirstInstruction)
990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Find a recently deserialized object using its offset from the current
991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // allocation point and write a pointer to it to the current object.
992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      ALL_SPACES(kBackref, kPlain, kStartOfObject)
9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#if V8_TARGET_ARCH_MIPS
9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Deserialize a new object from pointer found in code and write
9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a pointer to it to the current object. Required only for MIPS, and
9963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // omitted on the other architectures because it is fully unrolled and
9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // would cause bloat.
9983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ONE_PER_SPACE(kNewObject, kFromCode, kStartOfObject)
9993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Find a recently deserialized code object using its offset from the
10003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // current allocation point and write a pointer to it to the current
10013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // object. Required only for MIPS.
10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ALL_SPACES(kBackref, kFromCode, kStartOfObject)
10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Find an already deserialized code object using its offset from
10043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the start and write a pointer to it to the current object.
10053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Required only for MIPS.
10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ALL_SPACES(kFromStart, kFromCode, kStartOfObject)
10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
1008f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Find a recently deserialized code object using its offset from the
1009f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // current allocation point and write a pointer to its first instruction
1010791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      // to the current code object or the instruction pointer in a function
1011791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      // object.
1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      ALL_SPACES(kBackref, kFromCode, kFirstInstruction)
1013791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      ALL_SPACES(kBackref, kPlain, kFirstInstruction)
1014f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Find an already deserialized object using its offset from the start
1015f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // and write a pointer to it to the current object.
1016f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      ALL_SPACES(kFromStart, kPlain, kStartOfObject)
1017791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      ALL_SPACES(kFromStart, kPlain, kFirstInstruction)
1018f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Find an already deserialized code object using its offset from the
1019f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // start and write a pointer to its first instruction to the current code
1020f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // object.
1021f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      ALL_SPACES(kFromStart, kFromCode, kFirstInstruction)
1022f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Find an object in the roots array and write a pointer to it to the
1023f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // current object.
1024f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      CASE_STATEMENT(kRootArray, kPlain, kStartOfObject, 0)
1025f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      CASE_BODY(kRootArray, kPlain, kStartOfObject, 0, kUnknownOffsetFromStart)
1026f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Find an object in the partial snapshots cache and write a pointer to it
1027f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // to the current object.
1028f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      CASE_STATEMENT(kPartialSnapshotCache, kPlain, kStartOfObject, 0)
1029f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      CASE_BODY(kPartialSnapshotCache,
1030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                kPlain,
1031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                kStartOfObject,
1032f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                0,
1033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                kUnknownOffsetFromStart)
1034791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      // Find an code entry in the partial snapshots cache and
1035791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      // write a pointer to it to the current object.
1036791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      CASE_STATEMENT(kPartialSnapshotCache, kPlain, kFirstInstruction, 0)
1037791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      CASE_BODY(kPartialSnapshotCache,
1038791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                kPlain,
1039791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                kFirstInstruction,
1040791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                0,
1041791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                kUnknownOffsetFromStart)
1042f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Find an external reference and write a pointer to it to the current
1043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // object.
1044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      CASE_STATEMENT(kExternalReference, kPlain, kStartOfObject, 0)
1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      CASE_BODY(kExternalReference,
1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                kPlain,
1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                kStartOfObject,
1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                0,
1049f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                kUnknownOffsetFromStart)
1050f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // Find an external reference and write a pointer to it in the current
1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      // code object.
1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      CASE_STATEMENT(kExternalReference, kFromCode, kStartOfObject, 0)
1053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      CASE_BODY(kExternalReference,
1054f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                kFromCode,
1055f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                kStartOfObject,
1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                0,
1057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                kUnknownOffsetFromStart)
1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#undef CASE_STATEMENT
1060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#undef CASE_BODY
1061f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#undef ONE_PER_SPACE
1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#undef ALL_SPACES
1063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#undef ASSIGN_DEST_SPACE
1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      case kNewPage: {
1066d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        int space = source_->Get();
1067d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        pages_[space].Add(last_object_address_);
10686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (space == CODE_SPACE) {
10696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          CPU::FlushICache(last_object_address_, Page::kPageSize);
10706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
1071d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1072d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1073f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
10743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case kSkip: {
10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        current++;
10763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
10773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1079f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      case kNativesStringResource: {
1080d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        int index = source_->Get();
10813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Vector<const char> source_vector = Natives::GetRawScriptSource(index);
1082d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        NativesExternalStringResource* resource =
10833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            new NativesExternalStringResource(isolate->bootstrapper(),
10843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              source_vector.start(),
10853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              source_vector.length());
1086d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        *current++ = reinterpret_cast<Object*>(resource);
1087d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        break;
1088d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1089f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      case kSynchronize: {
1091d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        // If we get here then that indicates that you have a mismatch between
1092d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        // the number of GC roots when serializing and deserializing.
1093d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        UNREACHABLE();
1094d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      }
1095f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1096d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      default:
1097d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        UNREACHABLE();
1098d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1100d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT_EQ(current, limit);
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1104d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid SnapshotByteSink::PutInt(uintptr_t integer, const char* description) {
1105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const int max_shift = ((kPointerSize * kBitsPerByte) / 7) * 7;
1106d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int shift = max_shift; shift > 0; shift -= 7) {
1107d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (integer >= static_cast<uintptr_t>(1u) << shift) {
1108402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu      Put((static_cast<int>((integer >> shift)) & 0x7f) | 0x80, "IntPart");
1109d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1111402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  PutSection(static_cast<int>(integer & 0x7f), "IntLastPart");
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1115d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockSerializer::Serializer(SnapshotByteSink* sink)
1116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    : sink_(sink),
1117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      current_root_index_(0),
11183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      external_reference_encoder_(new ExternalReferenceEncoder),
11193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      large_object_total_(0),
11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      root_index_wave_front_(0) {
11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  isolate_ = Isolate::Current();
112244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The serializer is meant to be used only to generate initial heap images
112344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // from a context in which there is only one isolate.
11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(isolate_->IsDefaultIsolate());
1125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i <= LAST_SPACE; i++) {
1126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    fullness_[i] = 0;
1127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei PopescuSerializer::~Serializer() {
11323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  delete external_reference_encoder_;
11333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
11343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
11353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1136d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid StartupSerializer::SerializeStrongReferences() {
113744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = Isolate::Current();
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // No active threads.
113944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(NULL, Isolate::Current()->thread_manager()->FirstThreadStateInUse());
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // No active or weak handles.
114144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(isolate->handle_scope_implementer()->blocks()->is_empty());
114244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles());
1143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // We don't support serializing installed extensions.
11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!isolate->has_installed_extensions());
11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
114644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->IterateStrongRoots(this, VISIT_ONLY_STRONG);
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1150d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid PartialSerializer::Serialize(Object** object) {
1151e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  this->VisitPointer(object);
115244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = Isolate::Current();
1153d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1154d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // After we have done the partial serialization the partial snapshot cache
1155d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // will contain some references needed to decode the partial snapshot.  We
1156d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // fill it up with undefineds so it has a predictable length so the
1157d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // deserialization code doesn't need to know the length.
115844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int index = isolate->serialize_partial_snapshot_cache_length();
115944f0eee88ff00398ff7f715fab053374d808c90dSteve Block       index < Isolate::kPartialSnapshotCacheCapacity;
1160d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke       index++) {
116144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    isolate->serialize_partial_snapshot_cache()[index] =
116244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate->heap()->undefined_value();
116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    startup_serializer_->VisitPointer(
116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        &isolate->serialize_partial_snapshot_cache()[index]);
1165d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
116644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate->set_serialize_partial_snapshot_cache_length(
116744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Isolate::kPartialSnapshotCacheCapacity);
1168e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1169e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1170e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Serializer::VisitPointers(Object** start, Object** end) {
11723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Isolate* isolate = Isolate::Current();
11733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (Object** current = start; current < end; current++) {
11753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (start == isolate->heap()->roots_array_start()) {
11763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      root_index_wave_front_ =
11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Max(root_index_wave_front_, static_cast<intptr_t>(current - start));
11783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
11793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (reinterpret_cast<Address>(current) ==
11803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate->heap()->store_buffer()->TopAddress()) {
11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      sink_->Put(kSkip, "Skip");
11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if ((*current)->IsSmi()) {
1183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      sink_->Put(kRawData, "RawData");
1184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      sink_->PutInt(kPointerSize, "length");
1185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      for (int i = 0; i < kPointerSize; i++) {
1186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte");
1187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else {
1189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      SerializeObject(*current, kPlain, kStartOfObject);
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1195d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// This ensures that the partial snapshot cache keeps things alive during GC and
1196d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// tracks their movement.  When it is called during serialization of the startup
1197d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// snapshot the partial snapshot is empty, so nothing happens.  When the partial
1198d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// (context) snapshot is created, this array is populated with the pointers that
1199d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// the partial snapshot will need. As that happens we emit serialized objects to
1200d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// the startup snapshot that correspond to the elements of this cache array.  On
1201d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// deserialization we therefore need to visit the cache array.  This fills it up
1202d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// with pointers to deserialized objects.
12036ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid SerializerDeserializer::Iterate(ObjectVisitor* visitor) {
120444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = Isolate::Current();
1205d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  visitor->VisitPointers(
120644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate->serialize_partial_snapshot_cache(),
120744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &isolate->serialize_partial_snapshot_cache()[
120844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          isolate->serialize_partial_snapshot_cache_length()]);
1209d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1210d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1211d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1212d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// When deserializing we need to set the size of the snapshot cache.  This means
1213d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// the root iteration code (above) will iterate over array elements, writing the
1214d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// references to deserialized objects in them.
1215d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid SerializerDeserializer::SetSnapshotCacheSize(int size) {
121644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->set_serialize_partial_snapshot_cache_length(size);
1217d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1218d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1219d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1220d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeint PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) {
122144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = Isolate::Current();
122244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
122344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0;
122444f0eee88ff00398ff7f715fab053374d808c90dSteve Block       i < isolate->serialize_partial_snapshot_cache_length();
122544f0eee88ff00398ff7f715fab053374d808c90dSteve Block       i++) {
122644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object* entry = isolate->serialize_partial_snapshot_cache()[i];
1227d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (entry == heap_object) return i;
1228d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
12293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
1230d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // We didn't find the object in the cache.  So we add it to the cache and
1231d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // then visit the pointer so that it becomes part of the startup snapshot
1232d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // and we can refer to it from the partial snapshot.
123344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int length = isolate->serialize_partial_snapshot_cache_length();
123444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK(length < Isolate::kPartialSnapshotCacheCapacity);
123544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate->serialize_partial_snapshot_cache()[length] = heap_object;
123644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  startup_serializer_->VisitPointer(
123744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &isolate->serialize_partial_snapshot_cache()[length]);
1238d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // We don't recurse from the startup snapshot generator into the partial
1239d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // snapshot generator.
124044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(length == isolate->serialize_partial_snapshot_cache_length());
124144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate->set_serialize_partial_snapshot_cache_length(length + 1);
124244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return length;
1243d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1244d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1245d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
12463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint Serializer::RootIndex(HeapObject* heap_object, HowToCode from) {
12473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Heap* heap = HEAP;
12483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (heap->InNewSpace(heap_object)) return kInvalidRootIndex;
12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < root_index_wave_front_; i++) {
12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Object* root = heap->roots_array_start()[i];
12513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!root->IsSmi() && root == heap_object) {
12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#if V8_TARGET_ARCH_MIPS
12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (from == kFromCode) {
12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // In order to avoid code bloat in the deserializer we don't have
12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // support for the encoding that specifies a particular root should
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // be written into the lui/ori instructions on MIPS.  Therefore we
12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // should not generate such serialization data for MIPS.
12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return kInvalidRootIndex;
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return i;
12623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1263e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
1264e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return kInvalidRootIndex;
1265e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1266e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1267e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1268d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Encode the location of an already deserialized object in order to write its
1269d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// location into a later object.  We can encode the location as an offset from
1270d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// the start of the deserialized objects or as an offset backwards from the
1271d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// current allocation pointer.
1272d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Serializer::SerializeReferenceToPreviousObject(
1273d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    int space,
1274d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    int address,
1275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    HowToCode how_to_code,
1276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    WhereToPoint where_to_point) {
1277d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int offset = CurrentAllocationAddress(space) - address;
1278d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  bool from_start = true;
1279d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (SpaceIsPaged(space)) {
1280d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // For paged space it is simple to encode back from current allocation if
1281d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // the object is on the same page as the current allocation pointer.
1282d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if ((CurrentAllocationAddress(space) >> kPageSizeBits) ==
1283d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        (address >> kPageSizeBits)) {
1284d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      from_start = false;
1285d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      address = offset;
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1287d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else if (space == NEW_SPACE) {
1288d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // For new space it is always simple to encode back from current allocation.
1289d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (offset < address) {
1290d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      from_start = false;
1291d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      address = offset;
1292888f6729be6a6f6fbe246cb5a9f122e2dbe455b7Leon Clarke    }
1293d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1294d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // If we are actually dealing with real offsets (and not a numbering of
1295d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // all objects) then we should shift out the bits that are always 0.
1296d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (!SpaceIsLarge(space)) address >>= kObjectAlignmentBits;
1297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (from_start) {
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sink_->Put(kFromStart + how_to_code + where_to_point + space, "RefSer");
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sink_->PutInt(address, "address");
1300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer");
1302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    sink_->PutInt(address, "address");
1303d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1304d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1305d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1306d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1307d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid StartupSerializer::SerializeObject(
1308d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Object* o,
1309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    HowToCode how_to_code,
1310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    WhereToPoint where_to_point) {
1311d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CHECK(o->IsHeapObject());
1312d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  HeapObject* heap_object = HeapObject::cast(o);
1313d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int root_index;
13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PutRoot(root_index, heap_object, how_to_code, where_to_point);
13173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
13183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1320d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (address_mapper_.IsMapped(heap_object)) {
1321d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    int space = SpaceOfAlreadySerializedObject(heap_object);
1322d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    int address = address_mapper_.MappedTo(heap_object);
1323d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    SerializeReferenceToPreviousObject(space,
1324d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                       address,
1325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                       how_to_code,
1326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                       where_to_point);
1327d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else {
1328d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Object has not yet been serialized.  Serialize it here.
1329d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ObjectSerializer object_serializer(this,
1330d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                       heap_object,
1331d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                       sink_,
1332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                       how_to_code,
1333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                       where_to_point);
1334d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    object_serializer.Serialize();
1335d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1336d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1337d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1338d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1339d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid StartupSerializer::SerializeWeakReferences() {
134044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = Isolate::Current()->serialize_partial_snapshot_cache_length();
134144f0eee88ff00398ff7f715fab053374d808c90dSteve Block       i < Isolate::kPartialSnapshotCacheCapacity;
1342d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke       i++) {
1343f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    sink_->Put(kRootArray + kPlain + kStartOfObject, "RootSerialization");
1344d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    sink_->PutInt(Heap::kUndefinedValueRootIndex, "root_index");
1345d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
134644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->IterateWeakRoots(this, VISIT_ALL);
1347d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1348d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1349d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
13503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Serializer::PutRoot(int root_index,
13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         HeapObject* object,
13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         SerializerDeserializer::HowToCode how_to_code,
13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         SerializerDeserializer::WhereToPoint where_to_point) {
13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (how_to_code == kPlain &&
13553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      where_to_point == kStartOfObject &&
13563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      root_index < kRootArrayNumberOfConstantEncodings &&
13573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      !HEAP->InNewSpace(object)) {
13583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (root_index < kRootArrayNumberOfLowConstantEncodings) {
13593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      sink_->Put(kRootArrayLowConstants + root_index, "RootLoConstant");
13603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
13613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      sink_->Put(kRootArrayHighConstants + root_index -
13623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     kRootArrayNumberOfLowConstantEncodings,
13633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 "RootHiConstant");
13643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
13653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
13663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization");
13673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sink_->PutInt(root_index, "root_index");
13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1372d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid PartialSerializer::SerializeObject(
1373d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Object* o,
1374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    HowToCode how_to_code,
1375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    WhereToPoint where_to_point) {
1376d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CHECK(o->IsHeapObject());
1377d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  HeapObject* heap_object = HeapObject::cast(o);
1378d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (heap_object->IsMap()) {
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The code-caches link to context-specific code objects, which
13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // the startup and context serializes cannot currently handle.
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(Map::cast(heap_object)->code_cache() ==
13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           heap_object->GetHeap()->raw_unchecked_empty_fixed_array());
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1386d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int root_index;
13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PutRoot(root_index, heap_object, how_to_code, where_to_point);
1389d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return;
1390d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1391d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1392d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (ShouldBeInThePartialSnapshotCache(heap_object)) {
1393d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    int cache_index = PartialSnapshotCacheIndex(heap_object);
1394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    sink_->Put(kPartialSnapshotCache + how_to_code + where_to_point,
1395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke               "PartialSnapshotCache");
1396d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    sink_->PutInt(cache_index, "partial_snapshot_cache_index");
1397d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return;
1398d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1399d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1400d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Pointers from the partial snapshot to the objects in the startup snapshot
1401d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // should go through the root array or through the partial snapshot cache.
1402d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // If this is not the case you may have to add something to the root array.
1403d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(!startup_serializer_->address_mapper()->IsMapped(heap_object));
1404d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // All the symbols that the partial snapshot needs should be either in the
1405d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // root table or in the partial snapshot cache.
1406d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(!heap_object->IsSymbol());
1407d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1408d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (address_mapper_.IsMapped(heap_object)) {
1409d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    int space = SpaceOfAlreadySerializedObject(heap_object);
1410d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    int address = address_mapper_.MappedTo(heap_object);
1411d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    SerializeReferenceToPreviousObject(space,
1412d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                       address,
1413f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                       how_to_code,
1414f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                       where_to_point);
1415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else {
1416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Object has not yet been serialized.  Serialize it here.
1417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectSerializer serializer(this,
1418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                heap_object,
1419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                sink_,
1420f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                how_to_code,
1421f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                where_to_point);
1422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    serializer.Serialize();
1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Serializer::ObjectSerializer::Serialize() {
1428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int space = Serializer::SpaceOfObject(object_);
1429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int size = object_->Size();
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  sink_->Put(kNewObject + reference_representation_ + space,
1432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke             "ObjectSerialization");
1433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  sink_->PutInt(size >> kObjectAlignmentBits, "Size in words");
1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
143544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LOG(i::Isolate::Current(),
143644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      SnapshotPositionEvent(object_->address(), sink_->Position()));
1437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Mark this object as already serialized.
1439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool start_new_page;
1440d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int offset = serializer_->Allocate(space, size, &start_new_page);
1441d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  serializer_->address_mapper()->AddMapping(object_, offset);
1442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (start_new_page) {
1443f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    sink_->Put(kNewPage, "NewPage");
1444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    sink_->PutSection(space, "NewPageSpace");
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Serialize the map (first word of the object).
1448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  serializer_->SerializeObject(object_->map(), kPlain, kStartOfObject);
1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Serialize the rest of the object.
1451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK_EQ(0, bytes_processed_so_far_);
1452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bytes_processed_so_far_ = kPointerSize;
1453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  object_->IterateBody(object_->map()->instance_type(), size, this);
1454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  OutputRawData(object_->address() + size);
1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Serializer::ObjectSerializer::VisitPointers(Object** start,
1459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                                 Object** end) {
1460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Object** current = start;
1461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  while (current < end) {
1462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    while (current < end && (*current)->IsSmi()) current++;
1463d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (current < end) OutputRawData(reinterpret_cast<Address>(current));
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    while (current < end && !(*current)->IsSmi()) {
14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HeapObject* current_contents = HeapObject::cast(*current);
14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int root_index = serializer_->RootIndex(current_contents, kPlain);
14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Repeats are not subject to the write barrier so there are only some
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // objects that can be used in a repeat encoding.  These are the early
14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // ones in the root array that are never in new space.
14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (current != start &&
14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          root_index != kInvalidRootIndex &&
14733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          root_index < kRootArrayNumberOfConstantEncodings &&
14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          current_contents == current[-1]) {
14753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(!HEAP->InNewSpace(current_contents));
14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int repeat_count = 1;
14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        while (current < end - 1 && current[repeat_count] == current_contents) {
14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          repeat_count++;
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        current += repeat_count;
14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bytes_processed_so_far_ += repeat_count * kPointerSize;
14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (repeat_count > kMaxRepeats) {
14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          sink_->Put(kRepeat, "SerializeRepeats");
14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          sink_->PutInt(repeat_count, "SerializeRepeats");
14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          sink_->Put(CodeForRepeats(repeat_count), "SerializeRepeats");
14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        serializer_->SerializeObject(current_contents, kPlain, kStartOfObject);
14903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        bytes_processed_so_far_ += kPointerSize;
14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        current++;
14923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Serializer::ObjectSerializer::VisitEmbeddedPointer(RelocInfo* rinfo) {
14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Object** current = rinfo->target_object_address();
15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  OutputRawData(rinfo->target_address_address());
15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HowToCode representation = rinfo->IsCodedSpecially() ? kFromCode : kPlain;
15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  serializer_->SerializeObject(*current, representation, kStartOfObject);
15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bytes_processed_so_far_ += rinfo->target_address_size();
15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Serializer::ObjectSerializer::VisitExternalReferences(Address* start,
1509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                                                           Address* end) {
1510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address references_start = reinterpret_cast<Address>(start);
1511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  OutputRawData(references_start);
1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (Address* current = start; current < end; current++) {
1514f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    sink_->Put(kExternalReference + kPlain + kStartOfObject, "ExternalRef");
1515d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    int reference_id = serializer_->EncodeExternalReference(*current);
1516d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    sink_->PutInt(reference_id, "reference id");
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bytes_processed_so_far_ += static_cast<int>((end - start) * kPointerSize);
1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Serializer::ObjectSerializer::VisitExternalReference(RelocInfo* rinfo) {
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address references_start = rinfo->target_address_address();
15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  OutputRawData(references_start);
15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address* current = rinfo->target_reference_address();
15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int representation = rinfo->IsCodedSpecially() ?
15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       kFromCode + kStartOfObject : kPlain + kStartOfObject;
15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sink_->Put(kExternalReference + representation, "ExternalRef");
15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int reference_id = serializer_->EncodeExternalReference(*current);
15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  sink_->PutInt(reference_id, "reference id");
15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bytes_processed_so_far_ += rinfo->target_address_size();
15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1536d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) {
1537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address target_start = rinfo->target_address_address();
1538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  OutputRawData(target_start);
1539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address target = rinfo->target_address();
1540d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  uint32_t encoding = serializer_->EncodeExternalReference(target);
1541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(target == NULL ? encoding == 0 : encoding != 0);
1542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int representation;
1543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Can't use a ternary operator because of gcc.
1544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (rinfo->IsCodedSpecially()) {
1545f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    representation = kStartOfObject + kFromCode;
1546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
1547f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    representation = kStartOfObject + kPlain;
1548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
1549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  sink_->Put(kExternalReference + representation, "ExternalReference");
1550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  sink_->PutInt(encoding, "reference id");
1551f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  bytes_processed_so_far_ += rinfo->target_address_size();
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Serializer::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) {
1556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
1557d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address target_start = rinfo->target_address_address();
1558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  OutputRawData(target_start);
1559d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
1560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  serializer_->SerializeObject(target, kFromCode, kFirstInstruction);
1561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  bytes_processed_so_far_ += rinfo->target_address_size();
1562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1564d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1565791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid Serializer::ObjectSerializer::VisitCodeEntry(Address entry_address) {
1566791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  Code* target = Code::cast(Code::GetObjectFromEntryAddress(entry_address));
1567791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  OutputRawData(entry_address);
1568791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  serializer_->SerializeObject(target, kPlain, kFirstInstruction);
1569791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  bytes_processed_so_far_ += kPointerSize;
1570791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
1571791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1572791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Serializer::ObjectSerializer::VisitGlobalPropertyCell(RelocInfo* rinfo) {
1574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We shouldn't have any global property cell references in code
1575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // objects in the snapshot.
1576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UNREACHABLE();
1577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1580d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Serializer::ObjectSerializer::VisitExternalAsciiString(
1581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    v8::String::ExternalAsciiStringResource** resource_pointer) {
1582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address references_start = reinterpret_cast<Address>(resource_pointer);
1583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  OutputRawData(references_start);
1584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
158544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object* source = HEAP->natives_source_cache()->get(i);
1586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!source->IsUndefined()) {
1587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      ExternalAsciiString* string = ExternalAsciiString::cast(source);
1588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      typedef v8::String::ExternalAsciiStringResource Resource;
15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      const Resource* resource = string->resource();
1590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (resource == *resource_pointer) {
1591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        sink_->Put(kNativesStringResource, "NativesStringResource");
1592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        sink_->PutSection(i, "NativesStringResourceEnd");
1593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        bytes_processed_so_far_ += sizeof(resource);
1594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        return;
1595d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // One of the strings in the natives cache should match the resource.  We
1599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // can't serialize any other kinds of external strings.
1600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  UNREACHABLE();
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Serializer::ObjectSerializer::OutputRawData(Address up_to) {
1605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address object_start = object_->address();
1606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int up_to_offset = static_cast<int>(up_to - object_start);
1607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int skipped = up_to_offset - bytes_processed_so_far_;
1608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This assert will fail if the reloc info gives us the target_address_address
1609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // locations in a non-ascending order.  Luckily that doesn't happen.
1610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ASSERT(skipped >= 0);
1611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (skipped != 0) {
1612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Address base = object_start + bytes_processed_so_far_;
1613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#define RAW_CASE(index, length)                                                \
1614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (skipped == length) {                                                   \
1615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      sink_->PutSection(kRawData + index, "RawDataFixed");                     \
1616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else  /* NOLINT */
1617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    COMMON_RAW_LENGTHS(RAW_CASE)
1618d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef RAW_CASE
1619d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    {  /* NOLINT */
1620f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      sink_->Put(kRawData, "RawData");
1621d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      sink_->PutInt(skipped, "length");
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    for (int i = 0; i < skipped; i++) {
1624d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      unsigned int data = base[i];
1625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      sink_->PutSection(data, "Byte");
1626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    bytes_processed_so_far_ += skipped;
1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint Serializer::SpaceOfObject(HeapObject* object) {
1633d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
1634d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    AllocationSpace s = static_cast<AllocationSpace>(i);
163544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (HEAP->InSpace(object, s)) {
1636d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      if (i == LO_SPACE) {
1637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        if (object->IsCode()) {
1638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          return kLargeCode;
1639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else if (object->IsFixedArray()) {
1640d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          return kLargeFixedArray;
1641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        } else {
1642d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          return kLargeData;
1643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        }
1644d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
1645d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      return i;
1646d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1648d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  UNREACHABLE();
1649d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return 0;
1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint Serializer::SpaceOfAlreadySerializedObject(HeapObject* object) {
1654d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
1655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    AllocationSpace s = static_cast<AllocationSpace>(i);
165644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (HEAP->InSpace(object, s)) {
1657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      return i;
1658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
1661d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return 0;
1662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
1663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1664d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint Serializer::Allocate(int space, int size, bool* new_page) {
1666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  CHECK(space >= 0 && space < kNumberOfSpaces);
1667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (SpaceIsLarge(space)) {
1668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // In large object space we merely number the objects instead of trying to
1669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // determine some sort of address.
1670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    *new_page = true;
1671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    large_object_total_ += size;
1672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return fullness_[LO_SPACE]++;
1673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  *new_page = false;
1675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (fullness_[space] == 0) {
1676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    *new_page = true;
1677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (SpaceIsPaged(space)) {
1679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Paged spaces are a little special.  We encode their addresses as if the
1680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // pages were all contiguous and each page were filled up in the range
1681d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // 0 - Page::kObjectAreaSize.  In practice the pages may not be contiguous
1682d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // and allocation does not start at offset 0 in the page, but this scheme
1683d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // means the deserializer can get the page number quickly by shifting the
1684d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // serialized address.
1685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    CHECK(IsPowerOf2(Page::kPageSize));
1686d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    int used_in_this_page = (fullness_[space] & (Page::kPageSize - 1));
16873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK(size <= SpaceAreaSize(space));
16883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (used_in_this_page + size > SpaceAreaSize(space)) {
1689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      *new_page = true;
1690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      fullness_[space] = RoundUp(fullness_[space], Page::kPageSize);
1691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
1692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
1693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int allocation_address = fullness_[space];
1694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  fullness_[space] = allocation_address + size;
1695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return allocation_address;
1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint Serializer::SpaceAreaSize(int space) {
17003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (space == CODE_SPACE) {
17013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return isolate_->memory_allocator()->CodePageAreaSize();
17023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
17033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Page::kPageSize - Page::kObjectStartOffset;
17043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
17053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
17063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1709