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