• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 
33 namespace v8 {
34 namespace 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.
38 enum 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 
53 const int kTypeCodeCount = STUB_CACHE_TABLE + 1;
54 const int kFirstTypeCode = UNCLASSIFIED;
55 
56 const int kReferenceIdBits = 16;
57 const int kReferenceIdMask = (1 << kReferenceIdBits) - 1;
58 const int kReferenceTypeShift = kReferenceIdBits;
59 const int kDebugRegisterBits = 4;
60 const int kDebugIdShift = kDebugRegisterBits;
61 
62 
63 class 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_;
Hash(Address key)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 
Match(void * key1,void * key2)79   static bool Match(void* key1, void* key2) { return key1 == key2; }
80 
81   void Put(Address key, int index);
82 };
83 
84 
85 class ExternalReferenceDecoder {
86  public:
87   ExternalReferenceDecoder();
88   ~ExternalReferenceDecoder();
89 
Decode(uint32_t key)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 
Lookup(uint32_t key)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 
Put(uint32_t key,Address value)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.
121 class RelativeAddress;
122 class SimulatedHeapSpace;
123 class SnapshotWriter;
124 class ReferenceUpdater;
125 
126 
127 class 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 
roots()141   int roots() { return roots_; }
objects()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 
enabled()149   static bool enabled() { return serialization_enabled_; }
150 
Enable()151   static void Enable() { serialization_enabled_ = true; }
Disable()152   static void Disable() { serialization_enabled_ = false; }
153 
154  private:
155   friend class ReferenceUpdater;
156 
157   virtual void VisitPointers(Object** start, Object** end);
158 
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 SimulatedHeapSpacees 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 
214 class SnapshotReader {
215  public:
SnapshotReader(const byte * str,int len)216   SnapshotReader(const byte* str, int len): str_(str), end_(str + len) {}
217 
ExpectC(char expected)218   void ExpectC(char expected) {
219     int c = GetC();
220     USE(c);
221     ASSERT(c == expected);
222   }
223 
GetC()224   int GetC() {
225     if (str_ >= end_) return EOF;
226     return *str_++;
227   }
228 
GetInt()229   int GetInt() {
230     int result;
231     GetBytes(reinterpret_cast<Address>(&result), sizeof(result));
232     return result;
233   }
234 
GetAddress()235   Address GetAddress() {
236     Address result;
237     GetBytes(reinterpret_cast<Address>(&result), sizeof(result));
238     return result;
239   }
240 
GetBytes(Address a,int size)241   void GetBytes(Address a, int size) {
242     ASSERT(str_ + size <= end_);
243     memcpy(a, str_, size);
244     str_ += size;
245   }
246 
GetString()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 
265 class 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 
roots()282   int roots() { return roots_; }
objects()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 VisitExternalReferences(Address* start, Address* end);
293   virtual void VisitRuntimeEntry(RelocInfo* rinfo);
294 
295   Address GetEncodedAddress();
296 
297   // Read other global information (except flags) from the header of the file.
298   void GetHeader();
299   // Read a stack of handles from the file bottom first.
300   void GetGlobalHandleStack(List<Handle<Object> >* stack);
301   // Read the context stack from the file.
302   void GetContextStack();
303 
304   Object* GetObject();
305 
306   // Get the encoded address. In debug mode we make sure
307   // it matches the given expectations.
308   void ExpectEncodedAddress(Address expected);
309 
310   // Given an encoded address (the result of
311   // RelativeAddress::Encode), return the object to which it points,
312   // which will be either an Smi or a HeapObject in the current heap.
313   Object* Resolve(Address encoded_address);
314 
315   SnapshotReader reader_;
316   bool root_;  // Deserializing a root?
317   int roots_;  // number of roots visited
318   int objects_;  // number of objects serialized
319 
320   bool has_log_;  // The file has log information.
321 
322   // Resolve caches the following:
323   List<Page*> map_pages_;  // All pages in the map space.
324   List<Page*> cell_pages_;  // All pages in the cell space.
325   List<Page*> old_pointer_pages_;  // All pages in the old pointer space.
326   List<Page*> old_data_pages_;  // All pages in the old data space.
327   List<Page*> code_pages_;  // All pages in the code space.
328   List<Object*> large_objects_;    // All known large objects.
329   // A list of global handles at deserialization time.
330   List<Object**> global_handles_;
331 
332   ExternalReferenceDecoder* reference_decoder_;
333 
334 #ifdef DEBUG
335   bool expect_debug_information_;
336 #endif
337 
338   DISALLOW_COPY_AND_ASSIGN(Deserializer);
339 };
340 
341 } }  // namespace v8::internal
342 
343 #endif  // V8_SERIALIZE_H_
344