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#ifndef V8_SERIALIZE_H_
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_SERIALIZE_H_
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "hashmap.h"
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A TypeCode is used to distinguish different kinds of external reference.
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// It is a single bit to make testing for types easy.
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum TypeCode {
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNCLASSIFIED,        // One-of-a-kind references.
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BUILTIN,
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RUNTIME_FUNCTION,
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  IC_UTILITY,
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DEBUG_ADDRESS,
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  STATS_COUNTER,
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TOP_ADDRESS,
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  C_BUILTIN,
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EXTENSION,
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ACCESSOR,
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RUNTIME_ENTRY,
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  STUB_CACHE_TABLE
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kTypeCodeCount = STUB_CACHE_TABLE + 1;
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kFirstTypeCode = UNCLASSIFIED;
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kReferenceIdBits = 16;
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kReferenceIdMask = (1 << kReferenceIdBits) - 1;
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kReferenceTypeShift = kReferenceIdBits;
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kDebugRegisterBits = 4;
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kDebugIdShift = kDebugRegisterBits;
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// ExternalReferenceTable is a helper class that defines the relationship
6469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// between external references and their encodings. It is used to build
6569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder.
6669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalReferenceTable {
6769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch public:
6869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  static ExternalReferenceTable* instance(Isolate* isolate);
6969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
7069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ~ExternalReferenceTable() { }
7169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
7269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int size() const { return refs_.length(); }
7369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
7469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Address address(int i) { return refs_[i].address; }
7569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
7669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  uint32_t code(int i) { return refs_[i].code; }
7769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
7869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const char* name(int i) { return refs_[i].name; }
7969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
8069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int max_id(int code) { return max_id_[code]; }
8169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
8269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch private:
8369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  explicit ExternalReferenceTable(Isolate* isolate) : refs_(64) {
8469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      PopulateTable(isolate);
8569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
8669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
8769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  struct ExternalReferenceEntry {
8869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Address address;
8969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    uint32_t code;
9069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    const char* name;
9169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  };
9269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
9369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void PopulateTable(Isolate* isolate);
9469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
9569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // For a few types of references, we can get their address from their id.
9669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void AddFromId(TypeCode type,
9769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                 uint16_t id,
9869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                 const char* name,
9969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                 Isolate* isolate);
10069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
10169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // For other types of references, the caller will figure out the address.
10269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void Add(Address address, TypeCode type, uint16_t id, const char* name);
10369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
10469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  List<ExternalReferenceEntry> refs_;
10569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int max_id_[kTypeCodeCount];
10669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
10769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
10869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ExternalReferenceEncoder {
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReferenceEncoder();
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t Encode(Address key) const;
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfAddress(Address key) const;
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HashMap encodings_;
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static uint32_t Hash(Address key) {
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >> 2);
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int IndexOf(Address key) const;
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static bool Match(void* key1, void* key2) { return key1 == key2; }
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Put(Address key, int index);
12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate_;
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ExternalReferenceDecoder {
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReferenceDecoder();
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~ExternalReferenceDecoder();
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address Decode(uint32_t key) const {
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (key == 0) return NULL;
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return *Lookup(key);
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address** encodings_;
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address* Lookup(uint32_t key) const {
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int type = key >> kReferenceTypeShift;
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(kFirstTypeCode <= type && type < kTypeCodeCount);
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int id = key & kReferenceIdMask;
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return &encodings_[type][id];
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Put(uint32_t key, Address value) {
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *Lookup(key) = value;
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
15744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate_;
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockclass SnapshotByteSource {
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SnapshotByteSource(const byte* array, int length)
164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    : data_(array), length_(length), position_(0) { }
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool HasMore() { return position_ < length_; }
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int Get() {
169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(position_ < length_);
170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return data_[position_++];
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  inline void CopyRaw(byte* to, int number_of_bytes);
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  inline int GetInt();
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool AtEOF() {
178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return position_ == length_;
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
181d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int position() { return position_; }
182e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const byte* data_;
185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int length_;
186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int position_;
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#define COMMON_RAW_LENGTHS(f)        \
191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(1, 1)  \
192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(2, 2)  \
193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(3, 3)  \
194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(4, 4)  \
195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(5, 5)  \
196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(6, 6)  \
197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(7, 7)  \
198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(8, 8)  \
199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(9, 12)  \
200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(10, 16) \
201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(11, 20) \
202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(12, 24) \
203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(13, 28) \
204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(14, 32) \
205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(15, 36)
206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
207d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// The Serializer/Deserializer class is a common superclass for Serializer and
208d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Deserializer which is used to store common constants and methods used by
209d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// both.
210d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass SerializerDeserializer: public ObjectVisitor {
211d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public:
212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void Iterate(ObjectVisitor* visitor);
213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void SetSnapshotCacheSize(int size);
214d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block protected:
216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Where the pointed-to object can be found:
217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum Where {
218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kNewObject = 0,                 // Object is next in snapshot.
219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 1-8                             One per space.
220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kRootArray = 0x9,               // Object is found in root array.
221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kPartialSnapshotCache = 0xa,    // Object is in the cache.
222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kExternalReference = 0xb,       // Pointer to an external reference.
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    kSkip = 0xc,                    // Skip a pointer sized cell.
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // 0xd-0xf                         Free.
225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kBackref = 0x10,                 // Object is described relative to end.
226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x11-0x18                       One per space.
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // 0x19-0x1f                       Free.
228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kFromStart = 0x20,              // Object is described relative to start.
229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x21-0x28                       One per space.
230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x29-0x2f                       Free.
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // 0x30-0x3f                       Used by misc. tags below.
232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kPointedToMask = 0x3f
233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  };
234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // How to code the pointer to the object.
236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum HowToCode {
237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kPlain = 0,                          // Straight pointer.
238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // What this means depends on the architecture:
239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kFromCode = 0x40,                    // A pointer inlined in code.
240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kHowToCodeMask = 0x40
241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  };
242f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Where to point within the object.
244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum WhereToPoint {
245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kStartOfObject = 0,
246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kFirstInstruction = 0x80,
247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kWhereToPointMask = 0x80
248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  };
249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Misc.
251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Raw data to be copied from the snapshot.
252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kRawData = 0x30;
253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Some common raw lengths: 0x31-0x3f
254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // A tag emitted at strategic points in the snapshot to delineate sections.
255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the deserializer does not find these at the expected moments then it
256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // is an indication that the snapshot and the VM do not fit together.
257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Examine the build process for architecture, version or configuration
258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // mismatches.
259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kSynchronize = 0x70;
260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Used for the source code of the natives, which is in the executable, but
261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // is referred to from external strings in the snapshot.
262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kNativesStringResource = 0x71;
263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kNewPage = 0x72;
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kRepeat = 0x73;
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kConstantRepeat = 0x74;
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 0x74-0x7f            Repeat last word (subtract 0x73 to get the count).
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kMaxRepeats = 0x7f - 0x73;
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static int CodeForRepeats(int repeats) {
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(repeats >= 1 && repeats <= kMaxRepeats);
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return 0x73 + repeats;
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static int RepeatsForCode(int byte_code) {
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(byte_code >= kConstantRepeat && byte_code <= 0x7f);
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return byte_code - 0x73;
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kRootArrayLowConstants = 0xb0;
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 0xb0-0xbf            Things from the first 16 elements of the root array.
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kRootArrayHighConstants = 0xf0;
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 0xf0-0xff            Things from the next 16 elements of the root array.
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kRootArrayNumberOfConstantEncodings = 0x20;
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kRootArrayNumberOfLowConstantEncodings = 0x10;
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static int RootArrayConstantFromByteCode(int byte_code) {
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int constant = (byte_code & 0xf) | ((byte_code & 0x40) >> 2);
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(constant >= 0 && constant < kRootArrayNumberOfConstantEncodings);
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return constant;
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kLargeData = LAST_SPACE;
290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kLargeCode = kLargeData + 1;
291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kLargeFixedArray = kLargeCode + 1;
292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kNumberOfSpaces = kLargeFixedArray + 1;
293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kAnyOldSpace = -1;
294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // A bitmask for getting the space out of an instruction.
296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kSpaceMask = 15;
297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static inline bool SpaceIsLarge(int space) { return space >= kLargeData; }
299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static inline bool SpaceIsPaged(int space) {
300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE;
301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block};
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint SnapshotByteSource::GetInt() {
3063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // A little unwind to catch the really small ints.
3073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  int snapshot_byte = Get();
3083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if ((snapshot_byte & 0x80) == 0) {
3093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    return snapshot_byte;
3103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
3113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  int accumulator = (snapshot_byte & 0x7f) << 7;
3123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  while (true) {
3133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    snapshot_byte = Get();
3143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if ((snapshot_byte & 0x80) == 0) {
3153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      return accumulator | snapshot_byte;
3163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
3173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    accumulator = (accumulator | (snapshot_byte & 0x7f)) << 7;
3183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
3193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  UNREACHABLE();
3203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return accumulator;
3213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
3223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
3243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid SnapshotByteSource::CopyRaw(byte* to, int number_of_bytes) {
3253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  memcpy(to, data_ + position_, number_of_bytes);
3263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  position_ += number_of_bytes;
3273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
3283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// A Deserializer reads a snapshot and reconstructs the Object graph it defines.
331d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass Deserializer: public SerializerDeserializer {
332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public:
333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Create a deserializer from a snapshot byte source.
334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  explicit Deserializer(SnapshotByteSource* source);
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
336d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual ~Deserializer();
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Deserialize the snapshot into an empty heap.
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Deserialize();
340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Deserialize a single object and the objects reachable from it.
342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void DeserializePartial(Object** root);
343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void VisitPointers(Object** start, Object** end);
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
347d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  virtual void VisitExternalReferences(Address* start, Address* end) {
348d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    UNREACHABLE();
349d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
351d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  virtual void VisitRuntimeEntry(RelocInfo* rinfo) {
352d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    UNREACHABLE();
353d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Fills in some heap data in an area from start to end (non-inclusive).  The
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // space id is used for the write barrier.  The object_address is the address
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // of the object we are writing into, or NULL if we are not writing into an
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // object, i.e. if we are writing a series of tagged values that are not on
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the heap.
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ReadChunk(
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Object** start, Object** end, int space, Address object_address);
362d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  HeapObject* GetAddressFromStart(int space);
363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  inline HeapObject* GetAddressFromEnd(int space);
364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address Allocate(int space_number, Space* space, int size);
365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void ReadObject(int space_number, Space* space, Object** write_back);
366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
36744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Cached current isolate.
36844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate_;
36944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Keep track of the pages in the paged spaces.
371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // (In large object space we are keeping track of individual objects
372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // rather than pages.)  In new space we just need the address of the
373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // first object and the others will flow from that.
374d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  List<Address> pages_[SerializerDeserializer::kNumberOfSpaces];
375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SnapshotByteSource* source_;
377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This is the address of the next object that will be allocated in each
378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // space.  It is used to calculate the addresses of back-references.
379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address high_water_[LAST_SPACE + 1];
380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This is the address of the most recent object that was allocated.  It
381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // is used to set the location of the new page when we encounter a
382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // START_NEW_PAGE_SERIALIZATION tag.
383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address last_object_address_;
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
38544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReferenceDecoder* external_reference_decoder_;
38644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  DISALLOW_COPY_AND_ASSIGN(Deserializer);
388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block};
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockclass SnapshotByteSink {
392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public:
393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  virtual ~SnapshotByteSink() { }
394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  virtual void Put(int byte, const char* description) = 0;
395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  virtual void PutSection(int byte, const char* description) {
396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Put(byte, description);
397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void PutInt(uintptr_t integer, const char* description);
399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  virtual int Position() = 0;
400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block};
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
403d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Mapping objects to their location after deserialization.
404d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// This is used during building, but not at runtime by V8.
405d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass SerializationAddressMapper {
406d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public:
407d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SerializationAddressMapper()
408d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      : serialization_map_(new HashMap(&SerializationMatchFun)),
409d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        no_allocation_(new AssertNoAllocation()) { }
410d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
411d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ~SerializationAddressMapper() {
412d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    delete serialization_map_;
413d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    delete no_allocation_;
414d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
415d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
416d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  bool IsMapped(HeapObject* obj) {
417d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return serialization_map_->Lookup(Key(obj), Hash(obj), false) != NULL;
418d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
419d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
420d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int MappedTo(HeapObject* obj) {
421d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT(IsMapped(obj));
422d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return static_cast<int>(reinterpret_cast<intptr_t>(
423d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        serialization_map_->Lookup(Key(obj), Hash(obj), false)->value));
424d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
425d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
426d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void AddMapping(HeapObject* obj, int to) {
427d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT(!IsMapped(obj));
428d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    HashMap::Entry* entry =
429d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        serialization_map_->Lookup(Key(obj), Hash(obj), true);
430d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    entry->value = Value(to);
431d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
432d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
433d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private:
434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static bool SerializationMatchFun(void* key1, void* key2) {
435d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return key1 == key2;
436d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
437d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static uint32_t Hash(HeapObject* obj) {
439d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
440d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
441d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void* Key(HeapObject* obj) {
443d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return reinterpret_cast<void*>(obj->address());
444d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
445d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void* Value(int v) {
447d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return reinterpret_cast<void*>(v);
448d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
449d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
450d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  HashMap* serialization_map_;
451d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  AssertNoAllocation* no_allocation_;
452d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  DISALLOW_COPY_AND_ASSIGN(SerializationAddressMapper);
453d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke};
454d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
455d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
45644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// There can be only one serializer per V8 process.
457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass Serializer : public SerializerDeserializer {
458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public:
459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  explicit Serializer(SnapshotByteSink* sink);
4603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ~Serializer();
461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void VisitPointers(Object** start, Object** end);
462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // You can call this after serialization to find out how much space was used
463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // in each space.
464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  int CurrentAllocationAddress(int space) {
465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (SpaceIsLarge(space)) return large_object_total_;
466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return fullness_[space];
467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void Enable() {
470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!serialization_enabled_) {
471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      ASSERT(!too_late_to_enable_now_);
472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    serialization_enabled_ = true;
474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void Disable() { serialization_enabled_ = false; }
477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call this when you have made use of the fact that there is no serialization
478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // going on.
479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static bool enabled() { return serialization_enabled_; }
481d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SerializationAddressMapper* address_mapper() { return &address_mapper_; }
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void PutRoot(
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int index, HeapObject* object, HowToCode how, WhereToPoint where);
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
485d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke protected:
486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static const int kInvalidRootIndex = -1;
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int RootIndex(HeapObject* heap_object, HowToCode from);
489d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) = 0;
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t root_index_wave_front() { return root_index_wave_front_; }
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void set_root_index_wave_front(intptr_t value) {
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(value >= root_index_wave_front_);
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    root_index_wave_front_ = value;
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
495d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  class ObjectSerializer : public ObjectVisitor {
497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block   public:
498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectSerializer(Serializer* serializer,
499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     Object* o,
500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     SnapshotByteSink* sink,
501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                     HowToCode how_to_code,
502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                     WhereToPoint where_to_point)
503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      : serializer_(serializer),
504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        object_(HeapObject::cast(o)),
505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        sink_(sink),
506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        reference_representation_(how_to_code + where_to_point),
507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        bytes_processed_so_far_(0) { }
508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void Serialize();
509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void VisitPointers(Object** start, Object** end);
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    void VisitEmbeddedPointer(RelocInfo* target);
511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void VisitExternalReferences(Address* start, Address* end);
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    void VisitExternalReference(RelocInfo* rinfo);
513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void VisitCodeTarget(RelocInfo* target);
514791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    void VisitCodeEntry(Address entry_address);
515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    void VisitGlobalPropertyCell(RelocInfo* rinfo);
516d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void VisitRuntimeEntry(RelocInfo* reloc);
517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Used for seralizing the external strings that hold the natives source.
518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void VisitExternalAsciiString(
519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        v8::String::ExternalAsciiStringResource** resource);
520d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // We can't serialize a heap with external two byte strings.
521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void VisitExternalTwoByteString(
522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        v8::String::ExternalStringResource** resource) {
523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block   private:
527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void OutputRawData(Address up_to);
528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Serializer* serializer_;
530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    HeapObject* object_;
531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    SnapshotByteSink* sink_;
532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int reference_representation_;
533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    int bytes_processed_so_far_;
534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  };
535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
536d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual void SerializeObject(Object* o,
537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               HowToCode how_to_code,
538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               WhereToPoint where_to_point) = 0;
539d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void SerializeReferenceToPreviousObject(
540d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      int space,
541d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      int address,
542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      HowToCode how_to_code,
543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      WhereToPoint where_to_point);
544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void InitializeAllocators();
545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This will return the space for an object.  If the object is in large
546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // object space it may return kLargeCode or kLargeFixedArray in order
547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // to indicate to the deserializer what kind of large object allocation
548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // to make.
549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static int SpaceOfObject(HeapObject* object);
550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This just returns the space of the object.  It will return LO_SPACE
551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // for all large objects since you can't check the type of the object
552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // once the map has been used for the serialization address.
553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static int SpaceOfAlreadySerializedObject(HeapObject* object);
554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int Allocate(int space, int size, bool* new_page_started);
555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int EncodeExternalReference(Address addr) {
556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return external_reference_encoder_->Encode(addr);
557d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int SpaceAreaSize(int space);
5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Isolate* isolate_;
562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Keep track of the fullness of each space in order to generate
563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // relative addresses for back references.  Large objects are
564d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // just numbered sequentially since relative addresses make no
565d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // sense in large object space.
566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int fullness_[LAST_SPACE + 1];
567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SnapshotByteSink* sink_;
568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int current_root_index_;
569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ExternalReferenceEncoder* external_reference_encoder_;
570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static bool serialization_enabled_;
571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Did we already make use of the fact that serialization was not enabled?
572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  static bool too_late_to_enable_now_;
573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  int large_object_total_;
574d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SerializationAddressMapper address_mapper_;
5753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t root_index_wave_front_;
576d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  friend class ObjectSerializer;
578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  friend class Deserializer;
579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  DISALLOW_COPY_AND_ASSIGN(Serializer);
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
584d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
585d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass PartialSerializer : public Serializer {
586d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public:
587d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  PartialSerializer(Serializer* startup_snapshot_serializer,
588d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                    SnapshotByteSink* sink)
589d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    : Serializer(sink),
590d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      startup_serializer_(startup_snapshot_serializer) {
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    set_root_index_wave_front(Heap::kStrongRootListLength);
592d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
593d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
594d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Serialize the objects reachable from a single object pointer.
595d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual void Serialize(Object** o);
596d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual void SerializeObject(Object* o,
597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               HowToCode how_to_code,
598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               WhereToPoint where_to_point);
599d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
600d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke protected:
601d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual int PartialSnapshotCacheIndex(HeapObject* o);
602d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
6033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Scripts should be referred only through shared function infos.  We can't
6043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // allow them to be part of the partial snapshot because they contain a
6053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // unique ID, and deserializing several partial snapshots containing script
6063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // would cause dupes.
6073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    ASSERT(!o->IsScript());
6086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return o->IsString() || o->IsSharedFunctionInfo() ||
609756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           o->IsHeapNumber() || o->IsCode() ||
6103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           o->IsScopeInfo() ||
61144f0eee88ff00398ff7f715fab053374d808c90dSteve Block           o->map() == HEAP->fixed_cow_array_map();
612d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
613d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
614d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private:
615d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Serializer* startup_serializer_;
616d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  DISALLOW_COPY_AND_ASSIGN(PartialSerializer);
617d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke};
618d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
619d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
620d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass StartupSerializer : public Serializer {
621d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public:
622d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  explicit StartupSerializer(SnapshotByteSink* sink) : Serializer(sink) {
623d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Clear the cache of objects used by the partial snapshot.  After the
624d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // strong roots have been serialized we can create a partial snapshot
6253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // which will repopulate the cache with objects needed by that partial
626d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // snapshot.
62744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Isolate::Current()->set_serialize_partial_snapshot_cache_length(0);
628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
629d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Serialize the current state of the heap.  The order is:
630d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // 1) Strong references.
631d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // 2) Partial snapshot cache.
6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 3) Weak references (e.g. the symbol table).
633d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual void SerializeStrongReferences();
634d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual void SerializeObject(Object* o,
635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               HowToCode how_to_code,
636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               WhereToPoint where_to_point);
637d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void SerializeWeakReferences();
638d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void Serialize() {
639d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    SerializeStrongReferences();
640d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    SerializeWeakReferences();
641d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
642d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
643d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private:
644d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
645d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return false;
646d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
647d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke};
648d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_SERIALIZE_H_
653