blob: e17ee151d23b75c454c53e2c008610c0a057c966 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_SERIALIZE_H_
29#define V8_SERIALIZE_H_
30
31#include "hashmap.h"
32
33namespace v8 { namespace internal {
34
35// A TypeCode is used to distinguish different kinds of external reference.
36// It is a single bit to make testing for types easy.
37enum TypeCode {
38 UNCLASSIFIED, // One-of-a-kind references.
39 BUILTIN,
40 RUNTIME_FUNCTION,
41 IC_UTILITY,
42 DEBUG_ADDRESS,
43 STATS_COUNTER,
44 TOP_ADDRESS,
45 C_BUILTIN,
46 EXTENSION,
47 ACCESSOR,
48 RUNTIME_ENTRY,
49 STUB_CACHE_TABLE
50};
51
52const int kTypeCodeCount = STUB_CACHE_TABLE + 1;
53const int kFirstTypeCode = UNCLASSIFIED;
54
55const int kReferenceIdBits = 16;
56const int kReferenceIdMask = (1 << kReferenceIdBits) - 1;
57const int kReferenceTypeShift = kReferenceIdBits;
58const int kDebugRegisterBits = 4;
59const int kDebugIdShift = kDebugRegisterBits;
60
61
62class ExternalReferenceEncoder {
63 public:
64 ExternalReferenceEncoder();
65
66 uint32_t Encode(Address key) const;
67
68 const char* NameOfAddress(Address key) const;
69
70 private:
71 HashMap encodings_;
72 static uint32_t Hash(Address key) {
73 return reinterpret_cast<uint32_t>(key) >> 2;
74 }
75
76 int IndexOf(Address key) const;
77
78 static bool Match(void* key1, void* key2) { return key1 == key2; }
79
80 void Put(Address key, int index);
81};
82
83
84class ExternalReferenceDecoder {
85 public:
86 ExternalReferenceDecoder();
87 ~ExternalReferenceDecoder();
88
89 Address Decode(uint32_t key) const {
90 if (key == 0) return NULL;
91 return *Lookup(key);
92 }
93
94 private:
95 Address** encodings_;
96
97 Address* Lookup(uint32_t key) const {
98 int type = key >> kReferenceTypeShift;
99 ASSERT(kFirstTypeCode <= type && type < kTypeCodeCount);
100 int id = key & kReferenceIdMask;
101 return &encodings_[type][id];
102 }
103
104 void Put(uint32_t key, Address value) {
105 *Lookup(key) = value;
106 }
107};
108
109
110// A Serializer recursively visits objects to construct a serialized
111// representation of the Heap stored in a string. Serialization is
112// destructive. We use a similar mechanism to the GC to ensure that
113// each object is visited once, namely, we modify the map pointer of
114// each visited object to contain the relative address in the
115// appropriate space where that object will be allocated when the heap
116// is deserialized.
117
118
119// Helper classes defined in serialize.cc.
120class RelativeAddress;
121class SimulatedHeapSpace;
122class SnapshotWriter;
kasper.lund7276f142008-07-30 08:49:36 +0000123class ReferenceUpdater;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000124
125
126class Serializer: public ObjectVisitor {
127 public:
128 Serializer();
129
130 virtual ~Serializer();
131
132 // Serialize the current state of the heap. This operation destroys the
133 // heap contents and the contents of the roots into the heap.
134 void Serialize();
135
136 // Returns the serialized buffer. Ownership is transferred to the
137 // caller. Only the destructor and getters may be called after this call.
138 void Finalize(char** str, int* len);
139
140 int roots() { return roots_; }
141 int objects() { return objects_; }
142
143#ifdef DEBUG
144 // insert "tag" into the serialized stream
145 virtual void Synchronize(const char* tag);
146#endif
147
148 static bool enabled() { return serialization_enabled_; }
149
150 static void disable() { serialization_enabled_ = false; }
151
152 private:
kasper.lund7276f142008-07-30 08:49:36 +0000153 friend class ReferenceUpdater;
154
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000155 virtual void VisitPointers(Object** start, Object** end);
kasper.lund7276f142008-07-30 08:49:36 +0000156
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000157 bool IsVisited(HeapObject* obj);
kasper.lund7276f142008-07-30 08:49:36 +0000158
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000159 Address GetSavedAddress(HeapObject* obj);
kasper.lund7276f142008-07-30 08:49:36 +0000160
161 void SaveAddress(HeapObject* obj, Address addr);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000162
163 void PutEncodedAddress(Address addr);
164 // Write the global flags into the file.
165 void PutFlags();
166 // Write global information into the header of the file.
167 void PutHeader();
168 // Write the contents of the log into the file.
169 void PutLog();
170 // Serialize 'obj', and return its encoded RelativeAddress.
171 Address PutObject(HeapObject* obj);
172 // Write a stack of handles to the file bottom first.
173 void PutGlobalHandleStack(const List<Handle<Object> >& stack);
174 // Write the context stack into the file.
175 void PutContextStack();
176
177 // Return the encoded RelativeAddress where this object will be
178 // allocated on deserialization. On the first visit of 'o',
179 // serialize its contents. On return, *serialized will be true iff
180 // 'o' has just been serialized.
181 Address Encode(Object* o, bool* serialized);
182
183 // Simulate the allocation of 'obj', returning the address where it will
184 // be allocated on deserialization
185 RelativeAddress Allocate(HeapObject* obj);
186
187 void InitializeAllocators();
188
189 SnapshotWriter* writer_;
190 bool root_; // serializing a root?
191 int roots_; // number of roots visited
192 int objects_; // number of objects serialized
193
194 static bool serialization_enabled_;
195
196 int flags_end_; // The position right after the flags.
197
198 // An array of per-space SimulatedHeapSpacees used as memory allocators.
199 SimulatedHeapSpace* allocator_[LAST_SPACE+1];
200 // A list of global handles at serialization time.
201 List<Object**> global_handles_;
202
203 ExternalReferenceEncoder* reference_encoder_;
204
kasper.lund7276f142008-07-30 08:49:36 +0000205 HashMap saved_addresses_;
206
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000207 DISALLOW_COPY_AND_ASSIGN(Serializer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000208};
209
210// Helper class to read the bytes of the serialized heap.
211
212class SnapshotReader {
213 public:
kasper.lund44510672008-07-25 07:37:58 +0000214 SnapshotReader(const char* str, int len): str_(str), end_(str + len) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000215
216 void ExpectC(char expected) {
217 int c = GetC();
218 USE(c);
219 ASSERT(c == expected);
220 }
221
222 int GetC() {
223 if (str_ >= end_) return EOF;
224 return *str_++;
225 }
226
227 int GetInt() {
kasper.lund44510672008-07-25 07:37:58 +0000228 int result = *reinterpret_cast<const int*>(str_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000229 str_ += sizeof(result);
230 return result;
231 }
232
233 void GetBytes(Address a, int size) {
234 ASSERT(str_ + size <= end_);
235 memcpy(a, str_, size);
236 str_ += size;
237 }
238
239 char* GetString() {
240 ExpectC('[');
241 int size = GetInt();
242 ExpectC(']');
243 char* s = NewArray<char>(size + 1);
244 GetBytes(reinterpret_cast<Address>(s), size);
245 s[size] = 0;
246 return s;
247 }
248
249 private:
kasper.lund44510672008-07-25 07:37:58 +0000250 const char* str_;
251 const char* end_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000252};
253
254
255// A Deserializer reads a snapshot and reconstructs the Object graph it defines.
256
257class Deserializer: public ObjectVisitor {
258 public:
259 // Create a deserializer. The snapshot is held in str and has size len.
kasper.lund44510672008-07-25 07:37:58 +0000260 Deserializer(const char* str, int len);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000261
262 virtual ~Deserializer();
263
264 // Read the flags from the header of the file, and set those that
265 // should be inhereted from the snapshot.
266 void GetFlags();
267
268 // Read saved profiling information from the file and log it if required.
269 void GetLog();
270
271 // Deserialize the snapshot into an empty heap.
272 void Deserialize();
273
274 int roots() { return roots_; }
275 int objects() { return objects_; }
276
277#ifdef DEBUG
278 // Check for the presence of "tag" in the serialized stream
279 virtual void Synchronize(const char* tag);
280#endif
281
282 private:
283 virtual void VisitPointers(Object** start, Object** end);
284 virtual void VisitExternalReferences(Address* start, Address* end);
285 virtual void VisitRuntimeEntry(RelocInfo* rinfo);
286
287 Address GetEncodedAddress();
288
289 // Read other global information (except flags) from the header of the file.
290 void GetHeader();
291 // Read a stack of handles from the file bottom first.
292 void GetGlobalHandleStack(List<Handle<Object> >* stack);
293 // Read the context stack from the file.
294 void GetContextStack();
295
296 Object* GetObject();
297
298 // Get the encoded address. In debug mode we make sure
299 // it matches the given expectations.
300 void ExpectEncodedAddress(Address expected);
301
302 // Given an encoded address (the result of
303 // RelativeAddress::Encode), return the object to which it points,
304 // which will be either an Smi or a HeapObject in the current heap.
305 Object* Resolve(Address encoded_address);
306
307 SnapshotReader reader_;
308 bool root_; // Deserializing a root?
309 int roots_; // number of roots visited
310 int objects_; // number of objects serialized
311
312 bool has_log_; // The file has log information.
313
314 // Resolve caches the following:
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000315 List<Page*> map_pages_; // All pages in the map space.
316 List<Page*> old_pointer_pages_; // All pages in the old pointer space.
317 List<Page*> old_data_pages_; // All pages in the old data space.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000318 List<Page*> code_pages_;
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000319 List<Object*> large_objects_; // All known large objects.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000320 // A list of global handles at deserialization time.
321 List<Object**> global_handles_;
322
323 ExternalReferenceDecoder* reference_decoder_;
324
325#ifdef DEBUG
326 bool expect_debug_information_;
327#endif
328
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000329 DISALLOW_COPY_AND_ASSIGN(Deserializer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000330};
331
332} } // namespace v8::internal
333
334#endif // V8_SERIALIZE_H_