serialize.h revision b0fe1620dcb4135ac3ab2d66ff93072373911299
1d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Copyright 2006-2009 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
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ExternalReferenceEncoder {
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReferenceEncoder();
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uint32_t Encode(Address key) const;
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* NameOfAddress(Address key) const;
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HashMap encodings_;
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static uint32_t Hash(Address key) {
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >> 2);
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int IndexOf(Address key) const;
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static bool Match(void* key1, void* key2) { return key1 == key2; }
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Put(Address key, int index);
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ExternalReferenceDecoder {
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExternalReferenceDecoder();
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~ExternalReferenceDecoder();
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address Decode(uint32_t key) const {
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (key == 0) return NULL;
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return *Lookup(key);
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address** encodings_;
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address* Lookup(uint32_t key) const {
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int type = key >> kReferenceTypeShift;
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(kFirstTypeCode <= type && type < kTypeCodeCount);
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int id = key & kReferenceIdMask;
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return &encodings_[type][id];
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Put(uint32_t key, Address value) {
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *Lookup(key) = value;
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
111d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockclass SnapshotByteSource {
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
113d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SnapshotByteSource(const byte* array, int length)
114d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    : data_(array), length_(length), position_(0) { }
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool HasMore() { return position_ < length_; }
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int Get() {
119d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ASSERT(position_ < length_);
120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return data_[position_++];
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  inline void CopyRaw(byte* to, int number_of_bytes);
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  inline int GetInt();
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  bool AtEOF() {
128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return position_ == length_;
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
131d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int position() { return position_; }
132e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
134d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const byte* data_;
135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int length_;
136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int position_;
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// It is very common to have a reference to objects at certain offsets in the
141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// heap.  These offsets have been determined experimentally.  We code
142f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// references to such objects in a single byte that encodes the way the pointer
143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// is written (only plain pointers allowed), the space number and the offset.
144f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// This only works for objects in the first page of a space.  Don't use this for
145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// things in newspace since it bypasses the write barrier.
146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkestatic const int k64 = (sizeof(uintptr_t) - 4) / 4;
148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
149f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#define COMMON_REFERENCE_PATTERNS(f)                               \
150f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  f(kNumberOfSpaces, 2, (11 - k64))                                \
151f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  f((kNumberOfSpaces + 1), 2, 0)                                   \
152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  f((kNumberOfSpaces + 2), 2, (142 - 16 * k64))                    \
153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  f((kNumberOfSpaces + 3), 2, (74 - 15 * k64))                     \
154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  f((kNumberOfSpaces + 4), 2, 5)                                   \
155f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  f((kNumberOfSpaces + 5), 1, 135)                                 \
156f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  f((kNumberOfSpaces + 6), 2, (228 - 39 * k64))
157d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#define COMMON_RAW_LENGTHS(f)        \
159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(1, 1)  \
160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(2, 2)  \
161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(3, 3)  \
162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(4, 4)  \
163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(5, 5)  \
164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(6, 6)  \
165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(7, 7)  \
166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(8, 8)  \
167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(9, 12)  \
168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(10, 16) \
169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(11, 20) \
170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(12, 24) \
171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(13, 28) \
172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(14, 32) \
173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  f(15, 36)
174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
175d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// The Serializer/Deserializer class is a common superclass for Serializer and
176d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Deserializer which is used to store common constants and methods used by
177d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// both.
178d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass SerializerDeserializer: public ObjectVisitor {
179d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public:
180d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static void Iterate(ObjectVisitor* visitor);
181d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static void SetSnapshotCacheSize(int size);
182d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block protected:
184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Where the pointed-to object can be found:
185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum Where {
186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kNewObject = 0,                 // Object is next in snapshot.
187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 1-8                             One per space.
188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kRootArray = 0x9,               // Object is found in root array.
189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kPartialSnapshotCache = 0xa,    // Object is in the cache.
190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kExternalReference = 0xb,       // Pointer to an external reference.
191f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0xc-0xf                         Free.
192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kBackref = 0x10,                 // Object is described relative to end.
193f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x11-0x18                       One per space.
194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x19-0x1f                       Common backref offsets.
195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kFromStart = 0x20,              // Object is described relative to start.
196f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x21-0x28                       One per space.
197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x29-0x2f                       Free.
198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // 0x30-0x3f                       Used by misc tags below.
199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kPointedToMask = 0x3f
200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  };
201f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // How to code the pointer to the object.
203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum HowToCode {
204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kPlain = 0,                          // Straight pointer.
205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // What this means depends on the architecture:
206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kFromCode = 0x40,                    // A pointer inlined in code.
207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kHowToCodeMask = 0x40
208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  };
209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Where to point within the object.
211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  enum WhereToPoint {
212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kStartOfObject = 0,
213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kFirstInstruction = 0x80,
214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    kWhereToPointMask = 0x80
215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  };
216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Misc.
218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Raw data to be copied from the snapshot.
219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  static const int kRawData = 0x30;
220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Some common raw lengths: 0x31-0x3f
221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // A tag emitted at strategic points in the snapshot to delineate sections.
222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // If the deserializer does not find these at the expected moments then it
223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // is an indication that the snapshot and the VM do not fit together.
224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Examine the build process for architecture, version or configuration
225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // mismatches.
226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  static const int kSynchronize = 0x70;
227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Used for the source code of the natives, which is in the executable, but
228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // is referred to from external strings in the snapshot.
229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  static const int kNativesStringResource = 0x71;
230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  static const int kNewPage = 0x72;
231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // 0x73-0x7f                            Free.
232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // 0xb0-0xbf                            Free.
233f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // 0xf0-0xff                            Free.
234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const int kLargeData = LAST_SPACE;
237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const int kLargeCode = kLargeData + 1;
238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const int kLargeFixedArray = kLargeCode + 1;
239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const int kNumberOfSpaces = kLargeFixedArray + 1;
240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  static const int kAnyOldSpace = -1;
241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // A bitmask for getting the space out of an instruction.
243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static const int kSpaceMask = 15;
244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static inline bool SpaceIsLarge(int space) { return space >= kLargeData; }
246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static inline bool SpaceIsPaged(int space) {
247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE;
248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
249d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
250d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static int partial_snapshot_cache_length_;
251756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kPartialSnapshotCacheCapacity = 1400;
252d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static Object* partial_snapshot_cache_[];
253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block};
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2563100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint SnapshotByteSource::GetInt() {
2573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // A little unwind to catch the really small ints.
2583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  int snapshot_byte = Get();
2593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  if ((snapshot_byte & 0x80) == 0) {
2603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    return snapshot_byte;
2613100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
2623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  int accumulator = (snapshot_byte & 0x7f) << 7;
2633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  while (true) {
2643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    snapshot_byte = Get();
2653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    if ((snapshot_byte & 0x80) == 0) {
2663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      return accumulator | snapshot_byte;
2673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    }
2683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    accumulator = (accumulator | (snapshot_byte & 0x7f)) << 7;
2693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  }
2703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  UNREACHABLE();
2713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  return accumulator;
2723100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
2733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2743100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
2753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid SnapshotByteSource::CopyRaw(byte* to, int number_of_bytes) {
2763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  memcpy(to, data_ + position_, number_of_bytes);
2773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  position_ += number_of_bytes;
2783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu}
2793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// A Deserializer reads a snapshot and reconstructs the Object graph it defines.
282d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass Deserializer: public SerializerDeserializer {
283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public:
284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Create a deserializer from a snapshot byte source.
285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  explicit Deserializer(SnapshotByteSource* source);
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
287d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual ~Deserializer();
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Deserialize the snapshot into an empty heap.
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Deserialize();
291e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
292e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Deserialize a single object and the objects reachable from it.
293e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void DeserializePartial(Object** root);
294e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Synchronize(const char* tag);
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void VisitPointers(Object** start, Object** end);
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  virtual void VisitExternalReferences(Address* start, Address* end) {
303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    UNREACHABLE();
304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  virtual void VisitRuntimeEntry(RelocInfo* rinfo) {
307d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    UNREACHABLE();
308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void ReadChunk(Object** start, Object** end, int space, Address address);
311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  HeapObject* GetAddressFromStart(int space);
312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  inline HeapObject* GetAddressFromEnd(int space);
313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address Allocate(int space_number, Space* space, int size);
314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void ReadObject(int space_number, Space* space, Object** write_back);
315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Keep track of the pages in the paged spaces.
317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // (In large object space we are keeping track of individual objects
318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // rather than pages.)  In new space we just need the address of the
319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // first object and the others will flow from that.
320d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  List<Address> pages_[SerializerDeserializer::kNumberOfSpaces];
321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
322d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SnapshotByteSource* source_;
323e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  static ExternalReferenceDecoder* external_reference_decoder_;
324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This is the address of the next object that will be allocated in each
325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // space.  It is used to calculate the addresses of back-references.
326d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address high_water_[LAST_SPACE + 1];
327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This is the address of the most recent object that was allocated.  It
328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // is used to set the location of the new page when we encounter a
329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // START_NEW_PAGE_SERIALIZATION tag.
330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  Address last_object_address_;
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  DISALLOW_COPY_AND_ASSIGN(Deserializer);
333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block};
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockclass SnapshotByteSink {
337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public:
338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  virtual ~SnapshotByteSink() { }
339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  virtual void Put(int byte, const char* description) = 0;
340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  virtual void PutSection(int byte, const char* description) {
341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Put(byte, description);
342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void PutInt(uintptr_t integer, const char* description);
344e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  virtual int Position() = 0;
345d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block};
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
348d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Mapping objects to their location after deserialization.
349d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// This is used during building, but not at runtime by V8.
350d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass SerializationAddressMapper {
351d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public:
352d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SerializationAddressMapper()
353d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      : serialization_map_(new HashMap(&SerializationMatchFun)),
354d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        no_allocation_(new AssertNoAllocation()) { }
355d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
356d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ~SerializationAddressMapper() {
357d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    delete serialization_map_;
358d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    delete no_allocation_;
359d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
360d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
361d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  bool IsMapped(HeapObject* obj) {
362d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return serialization_map_->Lookup(Key(obj), Hash(obj), false) != NULL;
363d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
364d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
365d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int MappedTo(HeapObject* obj) {
366d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT(IsMapped(obj));
367d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return static_cast<int>(reinterpret_cast<intptr_t>(
368d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        serialization_map_->Lookup(Key(obj), Hash(obj), false)->value));
369d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
370d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
371d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void AddMapping(HeapObject* obj, int to) {
372d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT(!IsMapped(obj));
373d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    HashMap::Entry* entry =
374d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        serialization_map_->Lookup(Key(obj), Hash(obj), true);
375d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    entry->value = Value(to);
376d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
377d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
378d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private:
379d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static bool SerializationMatchFun(void* key1, void* key2) {
380d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return key1 == key2;
381d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
382d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
383d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static uint32_t Hash(HeapObject* obj) {
384d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
385d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
386d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
387d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static void* Key(HeapObject* obj) {
388d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return reinterpret_cast<void*>(obj->address());
389d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
390d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
391d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static void* Value(int v) {
392d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return reinterpret_cast<void*>(v);
393d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
394d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
395d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  HashMap* serialization_map_;
396d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  AssertNoAllocation* no_allocation_;
397d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  DISALLOW_COPY_AND_ASSIGN(SerializationAddressMapper);
398d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke};
399d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
400d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
401d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass Serializer : public SerializerDeserializer {
402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public:
403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  explicit Serializer(SnapshotByteSink* sink);
4043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  ~Serializer();
405d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void VisitPointers(Object** start, Object** end);
406e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // You can call this after serialization to find out how much space was used
407e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // in each space.
408e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  int CurrentAllocationAddress(int space) {
409e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (SpaceIsLarge(space)) return large_object_total_;
410e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    return fullness_[space];
411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
413d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static void Enable() {
414d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!serialization_enabled_) {
415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      ASSERT(!too_late_to_enable_now_);
416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    serialization_enabled_ = true;
418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static void Disable() { serialization_enabled_ = false; }
421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Call this when you have made use of the fact that there is no serialization
422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // going on.
423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static bool enabled() { return serialization_enabled_; }
425d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SerializationAddressMapper* address_mapper() { return &address_mapper_; }
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  virtual void Synchronize(const char* tag);
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
430d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke protected:
431d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  static const int kInvalidRootIndex = -1;
432d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual int RootIndex(HeapObject* heap_object) = 0;
433d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) = 0;
434d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  class ObjectSerializer : public ObjectVisitor {
436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block   public:
437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    ObjectSerializer(Serializer* serializer,
438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     Object* o,
439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                     SnapshotByteSink* sink,
440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                     HowToCode how_to_code,
441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                     WhereToPoint where_to_point)
442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      : serializer_(serializer),
443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        object_(HeapObject::cast(o)),
444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        sink_(sink),
445f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke        reference_representation_(how_to_code + where_to_point),
446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        bytes_processed_so_far_(0) { }
447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void Serialize();
448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void VisitPointers(Object** start, Object** end);
449d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void VisitExternalReferences(Address* start, Address* end);
450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void VisitCodeTarget(RelocInfo* target);
451791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    void VisitCodeEntry(Address entry_address);
452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    void VisitGlobalPropertyCell(RelocInfo* rinfo);
453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void VisitRuntimeEntry(RelocInfo* reloc);
454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Used for seralizing the external strings that hold the natives source.
455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void VisitExternalAsciiString(
456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        v8::String::ExternalAsciiStringResource** resource);
457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // We can't serialize a heap with external two byte strings.
458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void VisitExternalTwoByteString(
459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        v8::String::ExternalStringResource** resource) {
460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      UNREACHABLE();
461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
463d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block   private:
464d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    void OutputRawData(Address up_to);
465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    Serializer* serializer_;
467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    HeapObject* object_;
468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    SnapshotByteSink* sink_;
469f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    int reference_representation_;
470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    int bytes_processed_so_far_;
471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  };
472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
473d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual void SerializeObject(Object* o,
474f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               HowToCode how_to_code,
475f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               WhereToPoint where_to_point) = 0;
476d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void SerializeReferenceToPreviousObject(
477d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      int space,
478d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      int address,
479f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      HowToCode how_to_code,
480f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke      WhereToPoint where_to_point);
481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void InitializeAllocators();
482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This will return the space for an object.  If the object is in large
483d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // object space it may return kLargeCode or kLargeFixedArray in order
484d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // to indicate to the deserializer what kind of large object allocation
485d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // to make.
486d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static int SpaceOfObject(HeapObject* object);
487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // This just returns the space of the object.  It will return LO_SPACE
488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // for all large objects since you can't check the type of the object
489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // once the map has been used for the serialization address.
490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static int SpaceOfAlreadySerializedObject(HeapObject* object);
491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int Allocate(int space, int size, bool* new_page_started);
492d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int EncodeExternalReference(Address addr) {
493d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return external_reference_encoder_->Encode(addr);
494d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
495d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Keep track of the fullness of each space in order to generate
497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // relative addresses for back references.  Large objects are
498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // just numbered sequentially since relative addresses make no
499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // sense in large object space.
500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int fullness_[LAST_SPACE + 1];
501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  SnapshotByteSink* sink_;
502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  int current_root_index_;
503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ExternalReferenceEncoder* external_reference_encoder_;
504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static bool serialization_enabled_;
505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Did we already make use of the fact that serialization was not enabled?
506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  static bool too_late_to_enable_now_;
507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  int large_object_total_;
508d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SerializationAddressMapper address_mapper_;
509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  friend class ObjectSerializer;
511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  friend class Deserializer;
512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  DISALLOW_COPY_AND_ASSIGN(Serializer);
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
516d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
517d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass PartialSerializer : public Serializer {
518d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public:
519d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  PartialSerializer(Serializer* startup_snapshot_serializer,
520d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                    SnapshotByteSink* sink)
521d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    : Serializer(sink),
522d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      startup_serializer_(startup_snapshot_serializer) {
523d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
524d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
525d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Serialize the objects reachable from a single object pointer.
526d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual void Serialize(Object** o);
527d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual void SerializeObject(Object* o,
528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               HowToCode how_to_code,
529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               WhereToPoint where_to_point);
530d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
531d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke protected:
532d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual int RootIndex(HeapObject* o);
533d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual int PartialSnapshotCacheIndex(HeapObject* o);
534d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
5353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // Scripts should be referred only through shared function infos.  We can't
5363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // allow them to be part of the partial snapshot because they contain a
5373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // unique ID, and deserializing several partial snapshots containing script
5383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    // would cause dupes.
5393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu    ASSERT(!o->IsScript());
5406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return o->IsString() || o->IsSharedFunctionInfo() ||
541756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           o->IsHeapNumber() || o->IsCode() ||
542756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick           o->map() == Heap::fixed_cow_array_map();
543d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
544d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
545d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private:
546d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Serializer* startup_serializer_;
547d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  DISALLOW_COPY_AND_ASSIGN(PartialSerializer);
548d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke};
549d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
550d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
551d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass StartupSerializer : public Serializer {
552d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public:
553d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  explicit StartupSerializer(SnapshotByteSink* sink) : Serializer(sink) {
554d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Clear the cache of objects used by the partial snapshot.  After the
555d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // strong roots have been serialized we can create a partial snapshot
556d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // which will repopulate the cache with objects neede by that partial
557d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // snapshot.
558d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    partial_snapshot_cache_length_ = 0;
559d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
560d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Serialize the current state of the heap.  The order is:
561d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // 1) Strong references.
562d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // 2) Partial snapshot cache.
563d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // 3) Weak references (eg the symbol table).
564d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual void SerializeStrongReferences();
565d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual void SerializeObject(Object* o,
566f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               HowToCode how_to_code,
567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                               WhereToPoint where_to_point);
568d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void SerializeWeakReferences();
569d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void Serialize() {
570d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    SerializeStrongReferences();
571d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    SerializeWeakReferences();
572d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
573d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
574d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private:
575d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual int RootIndex(HeapObject* o) { return kInvalidRootIndex; }
576d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
577d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return false;
578d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
579d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke};
580d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
5813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_SERIALIZE_H_
585