blob: c901480fe59684af8ffff32473e525c4d9b8fe87 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// 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 {
34namespace internal {
35
36// A TypeCode is used to distinguish different kinds of external reference.
37// It is a single bit to make testing for types easy.
38enum TypeCode {
39 UNCLASSIFIED, // One-of-a-kind references.
40 BUILTIN,
41 RUNTIME_FUNCTION,
42 IC_UTILITY,
43 DEBUG_ADDRESS,
44 STATS_COUNTER,
45 TOP_ADDRESS,
46 C_BUILTIN,
47 EXTENSION,
48 ACCESSOR,
49 RUNTIME_ENTRY,
50 STUB_CACHE_TABLE
51};
52
53const int kTypeCodeCount = STUB_CACHE_TABLE + 1;
54const int kFirstTypeCode = UNCLASSIFIED;
55
56const int kReferenceIdBits = 16;
57const int kReferenceIdMask = (1 << kReferenceIdBits) - 1;
58const int kReferenceTypeShift = kReferenceIdBits;
59const int kDebugRegisterBits = 4;
60const int kDebugIdShift = kDebugRegisterBits;
61
62
63class ExternalReferenceEncoder {
64 public:
65 ExternalReferenceEncoder();
66
67 uint32_t Encode(Address key) const;
68
69 const char* NameOfAddress(Address key) const;
70
71 private:
72 HashMap encodings_;
73 static uint32_t Hash(Address key) {
74 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >> 2);
75 }
76
77 int IndexOf(Address key) const;
78
79 static bool Match(void* key1, void* key2) { return key1 == key2; }
80
81 void Put(Address key, int index);
82};
83
84
85class ExternalReferenceDecoder {
86 public:
87 ExternalReferenceDecoder();
88 ~ExternalReferenceDecoder();
89
90 Address Decode(uint32_t key) const {
91 if (key == 0) return NULL;
92 return *Lookup(key);
93 }
94
95 private:
96 Address** encodings_;
97
98 Address* Lookup(uint32_t key) const {
99 int type = key >> kReferenceTypeShift;
100 ASSERT(kFirstTypeCode <= type && type < kTypeCodeCount);
101 int id = key & kReferenceIdMask;
102 return &encodings_[type][id];
103 }
104
105 void Put(uint32_t key, Address value) {
106 *Lookup(key) = value;
107 }
108};
109
110
111// A Serializer recursively visits objects to construct a serialized
112// representation of the Heap stored in a string. Serialization is
113// destructive. We use a similar mechanism to the GC to ensure that
114// each object is visited once, namely, we modify the map pointer of
115// each visited object to contain the relative address in the
116// appropriate space where that object will be allocated when the heap
117// is deserialized.
118
119
120// Helper classes defined in serialize.cc.
121class RelativeAddress;
122class SimulatedHeapSpace;
123class SnapshotWriter;
124class ReferenceUpdater;
125
126
127class Serializer: public ObjectVisitor {
128 public:
129 Serializer();
130
131 virtual ~Serializer();
132
133 // Serialize the current state of the heap. This operation destroys the
134 // heap contents and the contents of the roots into the heap.
135 void Serialize();
136
137 // Returns the serialized buffer. Ownership is transferred to the
138 // caller. Only the destructor and getters may be called after this call.
139 void Finalize(byte** str, int* len);
140
141 int roots() { return roots_; }
142 int objects() { return objects_; }
143
144#ifdef DEBUG
145 // insert "tag" into the serialized stream
146 virtual void Synchronize(const char* tag);
147#endif
148
149 static bool enabled() { return serialization_enabled_; }
150
151 static void Enable() { serialization_enabled_ = true; }
152 static void Disable() { serialization_enabled_ = false; }
153
154 private:
155 friend class ReferenceUpdater;
156
157 virtual void VisitPointers(Object** start, Object** end);
158 virtual void VisitCodeTarget(RelocInfo* rinfo);
159 bool IsVisited(HeapObject* obj);
160
161 Address GetSavedAddress(HeapObject* obj);
162
163 void SaveAddress(HeapObject* obj, Address addr);
164
165 void PutEncodedAddress(Address addr);
166 // Write the global flags into the file.
167 void PutFlags();
168 // Write global information into the header of the file.
169 void PutHeader();
170 // Write the contents of the log into the file.
171 void PutLog();
172 // Serialize 'obj', and return its encoded RelativeAddress.
173 Address PutObject(HeapObject* obj);
174 // Write a stack of handles to the file bottom first.
175 void PutGlobalHandleStack(const List<Handle<Object> >& stack);
176 // Write the context stack into the file.
177 void PutContextStack();
178
179 // Return the encoded RelativeAddress where this object will be
180 // allocated on deserialization. On the first visit of 'o',
181 // serialize its contents. On return, *serialized will be true iff
182 // 'o' has just been serialized.
183 Address Encode(Object* o, bool* serialized);
184
185 // Simulate the allocation of 'obj', returning the address where it will
186 // be allocated on deserialization
187 RelativeAddress Allocate(HeapObject* obj);
188
189 void InitializeAllocators();
190
191 SnapshotWriter* writer_;
192 bool root_; // serializing a root?
193 int roots_; // number of roots visited
194 int objects_; // number of objects serialized
195
196 static bool serialization_enabled_;
197
198 int flags_end_; // The position right after the flags.
199
200 // An array of per-space SimulatedHeapSpaces used as memory allocators.
201 SimulatedHeapSpace* allocator_[LAST_SPACE+1];
202 // A list of global handles at serialization time.
203 List<Object**> global_handles_;
204
205 ExternalReferenceEncoder* reference_encoder_;
206
207 HashMap saved_addresses_;
208
209 DISALLOW_COPY_AND_ASSIGN(Serializer);
210};
211
212// Helper class to read the bytes of the serialized heap.
213
214class SnapshotReader {
215 public:
216 SnapshotReader(const byte* str, int len): str_(str), end_(str + len) {}
217
218 void ExpectC(char expected) {
219 int c = GetC();
220 USE(c);
221 ASSERT(c == expected);
222 }
223
224 int GetC() {
225 if (str_ >= end_) return EOF;
226 return *str_++;
227 }
228
229 int GetInt() {
230 int result;
231 GetBytes(reinterpret_cast<Address>(&result), sizeof(result));
232 return result;
233 }
234
235 Address GetAddress() {
236 Address result;
237 GetBytes(reinterpret_cast<Address>(&result), sizeof(result));
238 return result;
239 }
240
241 void GetBytes(Address a, int size) {
242 ASSERT(str_ + size <= end_);
243 memcpy(a, str_, size);
244 str_ += size;
245 }
246
247 char* GetString() {
248 ExpectC('[');
249 int size = GetInt();
250 ExpectC(']');
251 char* s = NewArray<char>(size + 1);
252 GetBytes(reinterpret_cast<Address>(s), size);
253 s[size] = 0;
254 return s;
255 }
256
257 private:
258 const byte* str_;
259 const byte* end_;
260};
261
262
263// A Deserializer reads a snapshot and reconstructs the Object graph it defines.
264
265class Deserializer: public ObjectVisitor {
266 public:
267 // Create a deserializer. The snapshot is held in str and has size len.
268 Deserializer(const byte* str, int len);
269
270 virtual ~Deserializer();
271
272 // Read the flags from the header of the file, and set those that
273 // should be inherited from the snapshot.
274 void GetFlags();
275
276 // Read saved profiling information from the file and log it if required.
277 void GetLog();
278
279 // Deserialize the snapshot into an empty heap.
280 void Deserialize();
281
282 int roots() { return roots_; }
283 int objects() { return objects_; }
284
285#ifdef DEBUG
286 // Check for the presence of "tag" in the serialized stream
287 virtual void Synchronize(const char* tag);
288#endif
289
290 private:
291 virtual void VisitPointers(Object** start, Object** end);
292 virtual void VisitCodeTarget(RelocInfo* rinfo);
293 virtual void VisitExternalReferences(Address* start, Address* end);
294 virtual void VisitRuntimeEntry(RelocInfo* rinfo);
295
296 Address GetEncodedAddress();
297
298 // Read other global information (except flags) from the header of the file.
299 void GetHeader();
300 // Read a stack of handles from the file bottom first.
301 void GetGlobalHandleStack(List<Handle<Object> >* stack);
302 // Read the context stack from the file.
303 void GetContextStack();
304
305 Object* GetObject();
306
307 // Get the encoded address. In debug mode we make sure
308 // it matches the given expectations.
309 void ExpectEncodedAddress(Address expected);
310
311 // Given an encoded address (the result of
312 // RelativeAddress::Encode), return the object to which it points,
313 // which will be either an Smi or a HeapObject in the current heap.
314 Object* Resolve(Address encoded_address);
315
316 SnapshotReader reader_;
317 bool root_; // Deserializing a root?
318 int roots_; // number of roots visited
319 int objects_; // number of objects serialized
320
321 bool has_log_; // The file has log information.
322
323 // Resolve caches the following:
324 List<Page*> map_pages_; // All pages in the map space.
325 List<Page*> cell_pages_; // All pages in the cell space.
326 List<Page*> old_pointer_pages_; // All pages in the old pointer space.
327 List<Page*> old_data_pages_; // All pages in the old data space.
328 List<Page*> code_pages_; // All pages in the code space.
329 List<Object*> large_objects_; // All known large objects.
330 // A list of global handles at deserialization time.
331 List<Object**> global_handles_;
332
333 ExternalReferenceDecoder* reference_decoder_;
334
335#ifdef DEBUG
336 bool expect_debug_information_;
337#endif
338
339 DISALLOW_COPY_AND_ASSIGN(Deserializer);
340};
341
342} } // namespace v8::internal
343
344#endif // V8_SERIALIZE_H_