OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 f(7, 7) \ | 178 f(7, 7) \ |
179 f(8, 8) \ | 179 f(8, 8) \ |
180 f(9, 12) \ | 180 f(9, 12) \ |
181 f(10, 16) \ | 181 f(10, 16) \ |
182 f(11, 20) \ | 182 f(11, 20) \ |
183 f(12, 24) \ | 183 f(12, 24) \ |
184 f(13, 28) \ | 184 f(13, 28) \ |
185 f(14, 32) \ | 185 f(14, 32) \ |
186 f(15, 36) | 186 f(15, 36) |
187 | 187 |
188 // The SerDes class is a common superclass for Serializer and Deserializer | 188 // The Serializer/Deserializer class is a common superclass for Serializer and |
189 // which is used to store common constants and methods used by both. | 189 // Deserializer which is used to store common constants and methods used by |
190 class SerDes: public ObjectVisitor { | 190 // both. |
| 191 class SerializerDeserializer: public ObjectVisitor { |
| 192 public: |
| 193 static void Iterate(ObjectVisitor* visitor); |
| 194 static void SetSnapshotCacheSize(int size); |
| 195 |
191 protected: | 196 protected: |
192 enum DataType { | 197 enum DataType { |
193 RAW_DATA_SERIALIZATION = 0, | 198 RAW_DATA_SERIALIZATION = 0, |
194 // And 15 common raw lengths. | 199 // And 15 common raw lengths. |
195 OBJECT_SERIALIZATION = 16, | 200 OBJECT_SERIALIZATION = 16, |
196 // One variant per space. | 201 // One variant per space. |
197 CODE_OBJECT_SERIALIZATION = 25, | 202 CODE_OBJECT_SERIALIZATION = 25, |
198 // One per space (only code spaces in use). | 203 // One per space (only code spaces in use). |
199 EXTERNAL_REFERENCE_SERIALIZATION = 34, | 204 EXTERNAL_REFERENCE_SERIALIZATION = 34, |
200 EXTERNAL_BRANCH_TARGET_SERIALIZATION = 35, | 205 EXTERNAL_BRANCH_TARGET_SERIALIZATION = 35, |
201 SYNCHRONIZE = 36, | 206 SYNCHRONIZE = 36, |
202 START_NEW_PAGE_SERIALIZATION = 37, | 207 START_NEW_PAGE_SERIALIZATION = 37, |
203 NATIVES_STRING_RESOURCE = 38, | 208 NATIVES_STRING_RESOURCE = 38, |
204 ROOT_SERIALIZATION = 39, | 209 ROOT_SERIALIZATION = 39, |
205 // Free: 40-47. | 210 PARTIAL_SNAPSHOT_CACHE_ENTRY = 40, |
| 211 // Free: 41-47. |
206 BACKREF_SERIALIZATION = 48, | 212 BACKREF_SERIALIZATION = 48, |
207 // One per space, must be kSpaceMask aligned. | 213 // One per space, must be kSpaceMask aligned. |
208 // Free: 57-63. | 214 // Free: 57-63. |
209 REFERENCE_SERIALIZATION = 64, | 215 REFERENCE_SERIALIZATION = 64, |
210 // One per space and common references. Must be kSpaceMask aligned. | 216 // One per space and common references. Must be kSpaceMask aligned. |
211 CODE_BACKREF_SERIALIZATION = 80, | 217 CODE_BACKREF_SERIALIZATION = 80, |
212 // One per space, must be kSpaceMask aligned. | 218 // One per space, must be kSpaceMask aligned. |
213 // Free: 89-95. | 219 // Free: 89-95. |
214 CODE_REFERENCE_SERIALIZATION = 96 | 220 CODE_REFERENCE_SERIALIZATION = 96 |
215 // One per space, must be kSpaceMask aligned. | 221 // One per space, must be kSpaceMask aligned. |
216 // Free: 105-255. | 222 // Free: 105-255. |
217 }; | 223 }; |
218 static const int kLargeData = LAST_SPACE; | 224 static const int kLargeData = LAST_SPACE; |
219 static const int kLargeCode = kLargeData + 1; | 225 static const int kLargeCode = kLargeData + 1; |
220 static const int kLargeFixedArray = kLargeCode + 1; | 226 static const int kLargeFixedArray = kLargeCode + 1; |
221 static const int kNumberOfSpaces = kLargeFixedArray + 1; | 227 static const int kNumberOfSpaces = kLargeFixedArray + 1; |
222 | 228 |
223 // A bitmask for getting the space out of an instruction. | 229 // A bitmask for getting the space out of an instruction. |
224 static const int kSpaceMask = 15; | 230 static const int kSpaceMask = 15; |
225 | 231 |
226 static inline bool SpaceIsLarge(int space) { return space >= kLargeData; } | 232 static inline bool SpaceIsLarge(int space) { return space >= kLargeData; } |
227 static inline bool SpaceIsPaged(int space) { | 233 static inline bool SpaceIsPaged(int space) { |
228 return space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE; | 234 return space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE; |
229 } | 235 } |
| 236 |
| 237 static int partial_snapshot_cache_length_; |
| 238 static const int kPartialSnapshotCacheCapacity = 1024; |
| 239 static Object* partial_snapshot_cache_[]; |
230 }; | 240 }; |
231 | 241 |
232 | 242 |
233 | 243 |
234 // A Deserializer reads a snapshot and reconstructs the Object graph it defines. | 244 // A Deserializer reads a snapshot and reconstructs the Object graph it defines. |
235 class Deserializer: public SerDes { | 245 class Deserializer: public SerializerDeserializer { |
236 public: | 246 public: |
237 // Create a deserializer from a snapshot byte source. | 247 // Create a deserializer from a snapshot byte source. |
238 explicit Deserializer(SnapshotByteSource* source); | 248 explicit Deserializer(SnapshotByteSource* source); |
239 | 249 |
240 virtual ~Deserializer() { } | 250 virtual ~Deserializer(); |
241 | 251 |
242 // Deserialize the snapshot into an empty heap. | 252 // Deserialize the snapshot into an empty heap. |
243 void Deserialize(); | 253 void Deserialize(); |
244 | 254 |
245 // Deserialize a single object and the objects reachable from it. | 255 // Deserialize a single object and the objects reachable from it. |
246 void DeserializePartial(Object** root); | 256 void DeserializePartial(Object** root); |
247 | 257 |
248 #ifdef DEBUG | 258 #ifdef DEBUG |
249 virtual void Synchronize(const char* tag); | 259 virtual void Synchronize(const char* tag); |
250 #endif | 260 #endif |
251 | 261 |
252 static void TearDown(); | |
253 | |
254 private: | 262 private: |
255 virtual void VisitPointers(Object** start, Object** end); | 263 virtual void VisitPointers(Object** start, Object** end); |
256 | 264 |
257 virtual void VisitExternalReferences(Address* start, Address* end) { | 265 virtual void VisitExternalReferences(Address* start, Address* end) { |
258 UNREACHABLE(); | 266 UNREACHABLE(); |
259 } | 267 } |
260 | 268 |
261 virtual void VisitRuntimeEntry(RelocInfo* rinfo) { | 269 virtual void VisitRuntimeEntry(RelocInfo* rinfo) { |
262 UNREACHABLE(); | 270 UNREACHABLE(); |
263 } | 271 } |
264 | 272 |
265 void ReadChunk(Object** start, Object** end, int space, Address address); | 273 void ReadChunk(Object** start, Object** end, int space, Address address); |
266 HeapObject* GetAddressFromStart(int space); | 274 HeapObject* GetAddressFromStart(int space); |
267 inline HeapObject* GetAddressFromEnd(int space); | 275 inline HeapObject* GetAddressFromEnd(int space); |
268 Address Allocate(int space_number, Space* space, int size); | 276 Address Allocate(int space_number, Space* space, int size); |
269 void ReadObject(int space_number, Space* space, Object** write_back); | 277 void ReadObject(int space_number, Space* space, Object** write_back); |
270 | 278 |
271 // Keep track of the pages in the paged spaces. | 279 // Keep track of the pages in the paged spaces. |
272 // (In large object space we are keeping track of individual objects | 280 // (In large object space we are keeping track of individual objects |
273 // rather than pages.) In new space we just need the address of the | 281 // rather than pages.) In new space we just need the address of the |
274 // first object and the others will flow from that. | 282 // first object and the others will flow from that. |
275 List<Address> pages_[SerDes::kNumberOfSpaces]; | 283 List<Address> pages_[SerializerDeserializer::kNumberOfSpaces]; |
276 | 284 |
277 SnapshotByteSource* source_; | 285 SnapshotByteSource* source_; |
278 static ExternalReferenceDecoder* external_reference_decoder_; | 286 static ExternalReferenceDecoder* external_reference_decoder_; |
279 // This is the address of the next object that will be allocated in each | 287 // This is the address of the next object that will be allocated in each |
280 // space. It is used to calculate the addresses of back-references. | 288 // space. It is used to calculate the addresses of back-references. |
281 Address high_water_[LAST_SPACE + 1]; | 289 Address high_water_[LAST_SPACE + 1]; |
282 // This is the address of the most recent object that was allocated. It | 290 // This is the address of the most recent object that was allocated. It |
283 // is used to set the location of the new page when we encounter a | 291 // is used to set the location of the new page when we encounter a |
284 // START_NEW_PAGE_SERIALIZATION tag. | 292 // START_NEW_PAGE_SERIALIZATION tag. |
285 Address last_object_address_; | 293 Address last_object_address_; |
286 | 294 |
287 DISALLOW_COPY_AND_ASSIGN(Deserializer); | 295 DISALLOW_COPY_AND_ASSIGN(Deserializer); |
288 }; | 296 }; |
289 | 297 |
290 | 298 |
291 class SnapshotByteSink { | 299 class SnapshotByteSink { |
292 public: | 300 public: |
293 virtual ~SnapshotByteSink() { } | 301 virtual ~SnapshotByteSink() { } |
294 virtual void Put(int byte, const char* description) = 0; | 302 virtual void Put(int byte, const char* description) = 0; |
295 virtual void PutSection(int byte, const char* description) { | 303 virtual void PutSection(int byte, const char* description) { |
296 Put(byte, description); | 304 Put(byte, description); |
297 } | 305 } |
298 void PutInt(uintptr_t integer, const char* description); | 306 void PutInt(uintptr_t integer, const char* description); |
299 virtual int Position() = 0; | 307 virtual int Position() = 0; |
300 }; | 308 }; |
301 | 309 |
302 | 310 |
303 class Serializer : public SerDes { | 311 // Mapping objects to their location after deserialization. |
| 312 // This is used during building, but not at runtime by V8. |
| 313 class SerializationAddressMapper { |
| 314 public: |
| 315 SerializationAddressMapper() |
| 316 : serialization_map_(new HashMap(&SerializationMatchFun)), |
| 317 no_allocation_(new AssertNoAllocation()) { } |
| 318 |
| 319 ~SerializationAddressMapper() { |
| 320 delete serialization_map_; |
| 321 delete no_allocation_; |
| 322 } |
| 323 |
| 324 bool IsMapped(HeapObject* obj) { |
| 325 return serialization_map_->Lookup(Key(obj), Hash(obj), false) != NULL; |
| 326 } |
| 327 |
| 328 int MappedTo(HeapObject* obj) { |
| 329 ASSERT(IsMapped(obj)); |
| 330 return static_cast<int>(reinterpret_cast<intptr_t>( |
| 331 serialization_map_->Lookup(Key(obj), Hash(obj), false)->value)); |
| 332 } |
| 333 |
| 334 void AddMapping(HeapObject* obj, int to) { |
| 335 ASSERT(!IsMapped(obj)); |
| 336 HashMap::Entry* entry = |
| 337 serialization_map_->Lookup(Key(obj), Hash(obj), true); |
| 338 entry->value = Value(to); |
| 339 } |
| 340 |
| 341 private: |
| 342 static bool SerializationMatchFun(void* key1, void* key2) { |
| 343 return key1 == key2; |
| 344 } |
| 345 |
| 346 static uint32_t Hash(HeapObject* obj) { |
| 347 return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address())); |
| 348 } |
| 349 |
| 350 static void* Key(HeapObject* obj) { |
| 351 return reinterpret_cast<void*>(obj->address()); |
| 352 } |
| 353 |
| 354 static void* Value(int v) { |
| 355 return reinterpret_cast<void*>(v); |
| 356 } |
| 357 |
| 358 HashMap* serialization_map_; |
| 359 AssertNoAllocation* no_allocation_; |
| 360 DISALLOW_COPY_AND_ASSIGN(SerializationAddressMapper); |
| 361 }; |
| 362 |
| 363 |
| 364 class Serializer : public SerializerDeserializer { |
304 public: | 365 public: |
305 explicit Serializer(SnapshotByteSink* sink); | 366 explicit Serializer(SnapshotByteSink* sink); |
306 // Serialize the current state of the heap. | |
307 void Serialize(); | |
308 // Serialize a single object and the objects reachable from it. | |
309 void SerializePartial(Object** obj); | |
310 void VisitPointers(Object** start, Object** end); | 367 void VisitPointers(Object** start, Object** end); |
311 // You can call this after serialization to find out how much space was used | 368 // You can call this after serialization to find out how much space was used |
312 // in each space. | 369 // in each space. |
313 int CurrentAllocationAddress(int space) { | 370 int CurrentAllocationAddress(int space) { |
314 if (SpaceIsLarge(space)) return large_object_total_; | 371 if (SpaceIsLarge(space)) return large_object_total_; |
315 return fullness_[space]; | 372 return fullness_[space]; |
316 } | 373 } |
317 | 374 |
318 static void Enable() { | 375 static void Enable() { |
319 if (!serialization_enabled_) { | 376 if (!serialization_enabled_) { |
320 ASSERT(!too_late_to_enable_now_); | 377 ASSERT(!too_late_to_enable_now_); |
321 } | 378 } |
322 serialization_enabled_ = true; | 379 serialization_enabled_ = true; |
323 } | 380 } |
324 | 381 |
325 static void Disable() { serialization_enabled_ = false; } | 382 static void Disable() { serialization_enabled_ = false; } |
326 // Call this when you have made use of the fact that there is no serialization | 383 // Call this when you have made use of the fact that there is no serialization |
327 // going on. | 384 // going on. |
328 static void TooLateToEnableNow() { too_late_to_enable_now_ = true; } | 385 static void TooLateToEnableNow() { too_late_to_enable_now_ = true; } |
329 static bool enabled() { return serialization_enabled_; } | 386 static bool enabled() { return serialization_enabled_; } |
| 387 SerializationAddressMapper* address_mapper() { return &address_mapper_; } |
330 #ifdef DEBUG | 388 #ifdef DEBUG |
331 virtual void Synchronize(const char* tag); | 389 virtual void Synchronize(const char* tag); |
332 #endif | 390 #endif |
333 | 391 |
334 private: | 392 protected: |
335 enum ReferenceRepresentation { | 393 enum ReferenceRepresentation { |
336 TAGGED_REPRESENTATION, // A tagged object reference. | 394 TAGGED_REPRESENTATION, // A tagged object reference. |
337 CODE_TARGET_REPRESENTATION // A reference to first instruction in target. | 395 CODE_TARGET_REPRESENTATION // A reference to first instruction in target. |
338 }; | 396 }; |
| 397 static const int kInvalidRootIndex = -1; |
| 398 virtual int RootIndex(HeapObject* heap_object) = 0; |
| 399 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) = 0; |
| 400 |
339 class ObjectSerializer : public ObjectVisitor { | 401 class ObjectSerializer : public ObjectVisitor { |
340 public: | 402 public: |
341 ObjectSerializer(Serializer* serializer, | 403 ObjectSerializer(Serializer* serializer, |
342 Object* o, | 404 Object* o, |
343 SnapshotByteSink* sink, | 405 SnapshotByteSink* sink, |
344 ReferenceRepresentation representation) | 406 ReferenceRepresentation representation) |
345 : serializer_(serializer), | 407 : serializer_(serializer), |
346 object_(HeapObject::cast(o)), | 408 object_(HeapObject::cast(o)), |
347 sink_(sink), | 409 sink_(sink), |
348 reference_representation_(representation), | 410 reference_representation_(representation), |
(...skipping 15 matching lines...) Expand all Loading... |
364 private: | 426 private: |
365 void OutputRawData(Address up_to); | 427 void OutputRawData(Address up_to); |
366 | 428 |
367 Serializer* serializer_; | 429 Serializer* serializer_; |
368 HeapObject* object_; | 430 HeapObject* object_; |
369 SnapshotByteSink* sink_; | 431 SnapshotByteSink* sink_; |
370 ReferenceRepresentation reference_representation_; | 432 ReferenceRepresentation reference_representation_; |
371 int bytes_processed_so_far_; | 433 int bytes_processed_so_far_; |
372 }; | 434 }; |
373 | 435 |
374 void SerializeObject(Object* o, ReferenceRepresentation representation); | 436 virtual void SerializeObject(Object* o, |
| 437 ReferenceRepresentation representation) = 0; |
| 438 void SerializeReferenceToPreviousObject( |
| 439 int space, |
| 440 int address, |
| 441 ReferenceRepresentation reference_representation); |
375 void InitializeAllocators(); | 442 void InitializeAllocators(); |
376 // This will return the space for an object. If the object is in large | 443 // This will return the space for an object. If the object is in large |
377 // object space it may return kLargeCode or kLargeFixedArray in order | 444 // object space it may return kLargeCode or kLargeFixedArray in order |
378 // to indicate to the deserializer what kind of large object allocation | 445 // to indicate to the deserializer what kind of large object allocation |
379 // to make. | 446 // to make. |
380 static int SpaceOfObject(HeapObject* object); | 447 static int SpaceOfObject(HeapObject* object); |
381 // This just returns the space of the object. It will return LO_SPACE | 448 // This just returns the space of the object. It will return LO_SPACE |
382 // for all large objects since you can't check the type of the object | 449 // for all large objects since you can't check the type of the object |
383 // once the map has been used for the serialization address. | 450 // once the map has been used for the serialization address. |
384 static int SpaceOfAlreadySerializedObject(HeapObject* object); | 451 static int SpaceOfAlreadySerializedObject(HeapObject* object); |
385 int Allocate(int space, int size, bool* new_page_started); | 452 int Allocate(int space, int size, bool* new_page_started); |
386 int EncodeExternalReference(Address addr) { | 453 int EncodeExternalReference(Address addr) { |
387 return external_reference_encoder_->Encode(addr); | 454 return external_reference_encoder_->Encode(addr); |
388 } | 455 } |
389 int RootIndex(HeapObject* heap_object); | |
390 static const int kInvalidRootIndex = -1; | |
391 | 456 |
392 // Keep track of the fullness of each space in order to generate | 457 // Keep track of the fullness of each space in order to generate |
393 // relative addresses for back references. Large objects are | 458 // relative addresses for back references. Large objects are |
394 // just numbered sequentially since relative addresses make no | 459 // just numbered sequentially since relative addresses make no |
395 // sense in large object space. | 460 // sense in large object space. |
396 int fullness_[LAST_SPACE + 1]; | 461 int fullness_[LAST_SPACE + 1]; |
397 SnapshotByteSink* sink_; | 462 SnapshotByteSink* sink_; |
398 int current_root_index_; | 463 int current_root_index_; |
399 ExternalReferenceEncoder* external_reference_encoder_; | 464 ExternalReferenceEncoder* external_reference_encoder_; |
400 bool partial_; | |
401 static bool serialization_enabled_; | 465 static bool serialization_enabled_; |
402 // Did we already make use of the fact that serialization was not enabled? | 466 // Did we already make use of the fact that serialization was not enabled? |
403 static bool too_late_to_enable_now_; | 467 static bool too_late_to_enable_now_; |
404 int large_object_total_; | 468 int large_object_total_; |
| 469 SerializationAddressMapper address_mapper_; |
405 | 470 |
406 friend class ObjectSerializer; | 471 friend class ObjectSerializer; |
407 friend class Deserializer; | 472 friend class Deserializer; |
408 | 473 |
409 DISALLOW_COPY_AND_ASSIGN(Serializer); | 474 DISALLOW_COPY_AND_ASSIGN(Serializer); |
410 }; | 475 }; |
411 | 476 |
| 477 |
| 478 class PartialSerializer : public Serializer { |
| 479 public: |
| 480 PartialSerializer(Serializer* startup_snapshot_serializer, |
| 481 SnapshotByteSink* sink) |
| 482 : Serializer(sink), |
| 483 startup_serializer_(startup_snapshot_serializer) { |
| 484 } |
| 485 |
| 486 // Serialize the objects reachable from a single object pointer. |
| 487 virtual void Serialize(Object** o); |
| 488 virtual void SerializeObject(Object* o, |
| 489 ReferenceRepresentation representation); |
| 490 |
| 491 protected: |
| 492 virtual int RootIndex(HeapObject* o); |
| 493 virtual int PartialSnapshotCacheIndex(HeapObject* o); |
| 494 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) { |
| 495 return o->IsString() || o->IsSharedFunctionInfo(); |
| 496 } |
| 497 |
| 498 private: |
| 499 Serializer* startup_serializer_; |
| 500 DISALLOW_COPY_AND_ASSIGN(PartialSerializer); |
| 501 }; |
| 502 |
| 503 |
| 504 class StartupSerializer : public Serializer { |
| 505 public: |
| 506 explicit StartupSerializer(SnapshotByteSink* sink) : Serializer(sink) { |
| 507 // Clear the cache of objects used by the partial snapshot. After the |
| 508 // strong roots have been serialized we can create a partial snapshot |
| 509 // which will repopulate the cache with objects neede by that partial |
| 510 // snapshot. |
| 511 partial_snapshot_cache_length_ = 0; |
| 512 } |
| 513 // Serialize the current state of the heap. The order is: |
| 514 // 1) Strong references. |
| 515 // 2) Partial snapshot cache. |
| 516 // 3) Weak references (eg the symbol table). |
| 517 virtual void SerializeStrongReferences(); |
| 518 virtual void SerializeObject(Object* o, |
| 519 ReferenceRepresentation representation); |
| 520 void SerializeWeakReferences(); |
| 521 void Serialize() { |
| 522 SerializeStrongReferences(); |
| 523 SerializeWeakReferences(); |
| 524 } |
| 525 |
| 526 private: |
| 527 virtual int RootIndex(HeapObject* o) { return kInvalidRootIndex; } |
| 528 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) { |
| 529 return false; |
| 530 } |
| 531 }; |
| 532 |
412 } } // namespace v8::internal | 533 } } // namespace v8::internal |
413 | 534 |
414 #endif // V8_SERIALIZE_H_ | 535 #endif // V8_SERIALIZE_H_ |
OLD | NEW |