OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_SERIALIZE_H_ | 5 #ifndef V8_SERIALIZE_H_ |
6 #define V8_SERIALIZE_H_ | 6 #define V8_SERIALIZE_H_ |
7 | 7 |
8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
9 #include "src/hashmap.h" | 9 #include "src/hashmap.h" |
10 #include "src/heap-profiler.h" | 10 #include "src/heap-profiler.h" |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 Add(string, BackReference::SourceReference()); | 278 Add(string, BackReference::SourceReference()); |
279 } | 279 } |
280 | 280 |
281 private: | 281 private: |
282 DisallowHeapAllocation no_allocation_; | 282 DisallowHeapAllocation no_allocation_; |
283 HashMap* map_; | 283 HashMap* map_; |
284 DISALLOW_COPY_AND_ASSIGN(BackReferenceMap); | 284 DISALLOW_COPY_AND_ASSIGN(BackReferenceMap); |
285 }; | 285 }; |
286 | 286 |
287 | 287 |
| 288 class HotObjectsList { |
| 289 public: |
| 290 HotObjectsList() : index_(0) { |
| 291 for (int i = 0; i < kSize; i++) circular_queue_[i] = NULL; |
| 292 } |
| 293 |
| 294 void Add(HeapObject* object) { |
| 295 circular_queue_[index_] = object; |
| 296 index_ = (index_ + 1) & kSizeMask; |
| 297 } |
| 298 |
| 299 HeapObject* Get(int index) { |
| 300 DCHECK_NE(NULL, circular_queue_[index]); |
| 301 return circular_queue_[index]; |
| 302 } |
| 303 |
| 304 static const int kNotFound = -1; |
| 305 |
| 306 int Find(HeapObject* object) { |
| 307 for (int i = 0; i < kSize; i++) { |
| 308 if (circular_queue_[i] == object) return i; |
| 309 } |
| 310 return kNotFound; |
| 311 } |
| 312 |
| 313 static const int kSize = 8; |
| 314 |
| 315 private: |
| 316 STATIC_ASSERT(IS_POWER_OF_TWO(kSize)); |
| 317 static const int kSizeMask = kSize - 1; |
| 318 HeapObject* circular_queue_[kSize]; |
| 319 int index_; |
| 320 |
| 321 DISALLOW_COPY_AND_ASSIGN(HotObjectsList); |
| 322 }; |
| 323 |
| 324 |
288 // The Serializer/Deserializer class is a common superclass for Serializer and | 325 // The Serializer/Deserializer class is a common superclass for Serializer and |
289 // Deserializer which is used to store common constants and methods used by | 326 // Deserializer which is used to store common constants and methods used by |
290 // both. | 327 // both. |
291 class SerializerDeserializer: public ObjectVisitor { | 328 class SerializerDeserializer: public ObjectVisitor { |
292 public: | 329 public: |
293 static void Iterate(Isolate* isolate, ObjectVisitor* visitor); | 330 static void Iterate(Isolate* isolate, ObjectVisitor* visitor); |
294 | 331 |
295 static int nop() { return kNop; } | 332 static int nop() { return kNop; } |
296 | 333 |
297 // No reservation for large object space necessary. | 334 // No reservation for large object space necessary. |
298 static const int kNumberOfPreallocatedSpaces = LO_SPACE; | 335 static const int kNumberOfPreallocatedSpaces = LO_SPACE; |
299 static const int kNumberOfSpaces = LAST_SPACE + 1; | 336 static const int kNumberOfSpaces = LAST_SPACE + 1; |
300 | 337 |
301 protected: | 338 protected: |
302 // Where the pointed-to object can be found: | 339 // Where the pointed-to object can be found: |
303 enum Where { | 340 enum Where { |
304 kNewObject = 0, // Object is next in snapshot. | 341 kNewObject = 0, // Object is next in snapshot. |
305 // 1-7 One per space. | 342 // 1-7 One per space. |
| 343 // 0x8 Unused. |
306 kRootArray = 0x9, // Object is found in root array. | 344 kRootArray = 0x9, // Object is found in root array. |
307 kPartialSnapshotCache = 0xa, // Object is in the cache. | 345 kPartialSnapshotCache = 0xa, // Object is in the cache. |
308 kExternalReference = 0xb, // Pointer to an external reference. | 346 kExternalReference = 0xb, // Pointer to an external reference. |
309 kSkip = 0xc, // Skip n bytes. | 347 kSkip = 0xc, // Skip n bytes. |
310 kBuiltin = 0xd, // Builtin code object. | 348 kBuiltin = 0xd, // Builtin code object. |
311 kAttachedReference = 0xe, // Object is described in an attached list. | 349 kAttachedReference = 0xe, // Object is described in an attached list. |
312 // 0xf Used by misc. See below. | 350 // 0xf Used by misc. See below. |
313 kBackref = 0x10, // Object is described relative to end. | 351 kBackref = 0x10, // Object is described relative to end. |
314 // 0x11-0x17 One per space. | 352 // 0x11-0x17 One per space. |
315 kBackrefWithSkip = 0x18, // Object is described relative to end. | 353 kBackrefWithSkip = 0x18, // Object is described relative to end. |
(...skipping 23 matching lines...) Expand all Loading... |
339 kInnerPointer = 0x80, // First insn in code object or payload of cell. | 377 kInnerPointer = 0x80, // First insn in code object or payload of cell. |
340 kWhereToPointMask = 0x80 | 378 kWhereToPointMask = 0x80 |
341 }; | 379 }; |
342 | 380 |
343 // Misc. | 381 // Misc. |
344 // Raw data to be copied from the snapshot. This byte code does not advance | 382 // Raw data to be copied from the snapshot. This byte code does not advance |
345 // the current pointer, which is used for code objects, where we write the | 383 // the current pointer, which is used for code objects, where we write the |
346 // entire code in one memcpy, then fix up stuff with kSkip and other byte | 384 // entire code in one memcpy, then fix up stuff with kSkip and other byte |
347 // codes that overwrite data. | 385 // codes that overwrite data. |
348 static const int kRawData = 0x20; | 386 static const int kRawData = 0x20; |
349 // Some common raw lengths: 0x21-0x3f. These autoadvance the current pointer. | 387 // Some common raw lengths: 0x21-0x3f. |
| 388 // These autoadvance the current pointer. |
| 389 static const int kOnePointerRawData = 0x21; |
| 390 |
| 391 static const int kVariableRepeat = 0x60; |
| 392 // 0x61-0x6f Repeat last word |
| 393 static const int kFixedRepeat = 0x61; |
| 394 static const int kFixedRepeatBase = kFixedRepeat - 1; |
| 395 static const int kLastFixedRepeat = 0x6f; |
| 396 static const int kMaxFixedRepeats = kLastFixedRepeat - kFixedRepeatBase; |
| 397 static int CodeForRepeats(int repeats) { |
| 398 DCHECK(repeats >= 1 && repeats <= kMaxFixedRepeats); |
| 399 return kFixedRepeatBase + repeats; |
| 400 } |
| 401 static int RepeatsForCode(int byte_code) { |
| 402 DCHECK(byte_code > kFixedRepeatBase && byte_code <= kLastFixedRepeat); |
| 403 return byte_code - kFixedRepeatBase; |
| 404 } |
| 405 |
| 406 // Hot objects are a small set of recently seen or back-referenced objects. |
| 407 // They are represented by a single opcode to save space. |
| 408 // We use 0x70..0x77 for 8 hot objects, and 0x78..0x7f to add skip. |
| 409 static const int kHotObject = 0x70; |
| 410 static const int kMaxHotObjectIndex = 0x77 - kHotObject; |
| 411 static const int kHotObjectWithSkip = 0x78; |
| 412 STATIC_ASSERT(HotObjectsList::kSize == kMaxHotObjectIndex + 1); |
| 413 STATIC_ASSERT(0x7f - kHotObjectWithSkip == kMaxHotObjectIndex); |
| 414 static const int kHotObjectIndexMask = 0x7; |
| 415 |
| 416 static const int kRootArrayConstants = 0xa0; |
| 417 // 0xa0-0xbf Things from the first 32 elements of the root array. |
| 418 static const int kRootArrayNumberOfConstantEncodings = 0x20; |
| 419 static int RootArrayConstantFromByteCode(int byte_code) { |
| 420 return byte_code & 0x1f; |
| 421 } |
| 422 |
| 423 // Do nothing, used for padding. |
| 424 static const int kNop = 0xf; |
| 425 |
| 426 // Move to next reserved chunk. |
| 427 static const int kNextChunk = 0x4f; |
| 428 |
350 // A tag emitted at strategic points in the snapshot to delineate sections. | 429 // A tag emitted at strategic points in the snapshot to delineate sections. |
351 // If the deserializer does not find these at the expected moments then it | 430 // If the deserializer does not find these at the expected moments then it |
352 // is an indication that the snapshot and the VM do not fit together. | 431 // is an indication that the snapshot and the VM do not fit together. |
353 // Examine the build process for architecture, version or configuration | 432 // Examine the build process for architecture, version or configuration |
354 // mismatches. | 433 // mismatches. |
355 static const int kSynchronize = 0x70; | 434 static const int kSynchronize = 0x8f; |
| 435 |
356 // Used for the source code of the natives, which is in the executable, but | 436 // Used for the source code of the natives, which is in the executable, but |
357 // is referred to from external strings in the snapshot. | 437 // is referred to from external strings in the snapshot. |
358 static const int kNativesStringResource = 0x71; | 438 static const int kNativesStringResource = 0xcf; |
359 static const int kRepeat = 0x72; | |
360 static const int kConstantRepeat = 0x73; | |
361 // 0x73-0x7f Repeat last word (subtract 0x72 to get the count). | |
362 static const int kMaxRepeats = 0x7f - 0x72; | |
363 static int CodeForRepeats(int repeats) { | |
364 DCHECK(repeats >= 1 && repeats <= kMaxRepeats); | |
365 return 0x72 + repeats; | |
366 } | |
367 static int RepeatsForCode(int byte_code) { | |
368 DCHECK(byte_code >= kConstantRepeat && byte_code <= 0x7f); | |
369 return byte_code - 0x72; | |
370 } | |
371 static const int kRootArrayConstants = 0xa0; | |
372 // 0xa0-0xbf Things from the first 32 elements of the root array. | |
373 static const int kRootArrayNumberOfConstantEncodings = 0x20; | |
374 static int RootArrayConstantFromByteCode(int byte_code) { | |
375 return byte_code & 0x1f; | |
376 } | |
377 | |
378 static const int kNop = 0xf; // Do nothing, used for padding. | |
379 | |
380 static const int kNextChunk = 0x4f; // Move to next reserved chunk. | |
381 | 439 |
382 static const int kAnyOldSpace = -1; | 440 static const int kAnyOldSpace = -1; |
383 | 441 |
384 // A bitmask for getting the space out of an instruction. | 442 // A bitmask for getting the space out of an instruction. |
385 static const int kSpaceMask = 7; | 443 static const int kSpaceMask = 7; |
386 STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1); | 444 STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1); |
387 | 445 |
388 // Sentinel after a new object to indicate that double alignment is needed. | 446 // Sentinel after a new object to indicate that double alignment is needed. |
389 static const int kDoubleAlignmentSentinel = 0; | 447 static const int kDoubleAlignmentSentinel = 0; |
| 448 |
| 449 // Used as index for the attached reference representing the source object. |
| 450 static const int kSourceObjectReference = 0; |
| 451 |
| 452 HotObjectsList hot_objects_; |
390 }; | 453 }; |
391 | 454 |
392 | 455 |
393 // A Deserializer reads a snapshot and reconstructs the Object graph it defines. | 456 // A Deserializer reads a snapshot and reconstructs the Object graph it defines. |
394 class Deserializer: public SerializerDeserializer { | 457 class Deserializer: public SerializerDeserializer { |
395 public: | 458 public: |
396 // Create a deserializer from a snapshot byte source. | 459 // Create a deserializer from a snapshot byte source. |
397 explicit Deserializer(SnapshotByteSource* source); | 460 explicit Deserializer(SnapshotByteSource* source); |
398 | 461 |
399 virtual ~Deserializer(); | 462 virtual ~Deserializer(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 // of the object we are writing into, or NULL if we are not writing into an | 505 // of the object we are writing into, or NULL if we are not writing into an |
443 // object, i.e. if we are writing a series of tagged values that are not on | 506 // object, i.e. if we are writing a series of tagged values that are not on |
444 // the heap. | 507 // the heap. |
445 void ReadData(Object** start, Object** end, int space, | 508 void ReadData(Object** start, Object** end, int space, |
446 Address object_address); | 509 Address object_address); |
447 void ReadObject(int space_number, Object** write_back); | 510 void ReadObject(int space_number, Object** write_back); |
448 Address Allocate(int space_index, int size); | 511 Address Allocate(int space_index, int size); |
449 | 512 |
450 // Special handling for serialized code like hooking up internalized strings. | 513 // Special handling for serialized code like hooking up internalized strings. |
451 HeapObject* ProcessNewObjectFromSerializedCode(HeapObject* obj); | 514 HeapObject* ProcessNewObjectFromSerializedCode(HeapObject* obj); |
452 Object* ProcessBackRefInSerializedCode(Object* obj); | |
453 | 515 |
454 // This returns the address of an object that has been described in the | 516 // This returns the address of an object that has been described in the |
455 // snapshot by chunk index and offset. | 517 // snapshot by chunk index and offset. |
456 HeapObject* GetBackReferencedObject(int space) { | 518 HeapObject* GetBackReferencedObject(int space); |
457 if (space == LO_SPACE) { | |
458 uint32_t index = source_->GetInt(); | |
459 return deserialized_large_objects_[index]; | |
460 } else { | |
461 BackReference back_reference(source_->GetInt()); | |
462 DCHECK(space < kNumberOfPreallocatedSpaces); | |
463 uint32_t chunk_index = back_reference.chunk_index(); | |
464 DCHECK_LE(chunk_index, current_chunk_[space]); | |
465 uint32_t chunk_offset = back_reference.chunk_offset(); | |
466 return HeapObject::FromAddress(reservations_[space][chunk_index].start + | |
467 chunk_offset); | |
468 } | |
469 } | |
470 | 519 |
471 // Cached current isolate. | 520 // Cached current isolate. |
472 Isolate* isolate_; | 521 Isolate* isolate_; |
473 | 522 |
474 // Objects from the attached object descriptions in the serialized user code. | 523 // Objects from the attached object descriptions in the serialized user code. |
475 Vector<Handle<Object> >* attached_objects_; | 524 Vector<Handle<Object> >* attached_objects_; |
476 | 525 |
477 SnapshotByteSource* source_; | 526 SnapshotByteSource* source_; |
478 // The address of the next object that will be allocated in each space. | 527 // The address of the next object that will be allocated in each space. |
479 // Each space has a number of chunks reserved by the GC, with each chunk | 528 // Each space has a number of chunks reserved by the GC, with each chunk |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 bool code_object_; | 618 bool code_object_; |
570 bool code_has_been_output_; | 619 bool code_has_been_output_; |
571 }; | 620 }; |
572 | 621 |
573 virtual void SerializeObject(HeapObject* o, HowToCode how_to_code, | 622 virtual void SerializeObject(HeapObject* o, HowToCode how_to_code, |
574 WhereToPoint where_to_point, int skip) = 0; | 623 WhereToPoint where_to_point, int skip) = 0; |
575 | 624 |
576 void PutRoot(int index, HeapObject* object, HowToCode how, WhereToPoint where, | 625 void PutRoot(int index, HeapObject* object, HowToCode how, WhereToPoint where, |
577 int skip); | 626 int skip); |
578 | 627 |
579 void SerializeBackReference(BackReference back_reference, | 628 // Returns true if the object was successfully serialized. |
580 HowToCode how_to_code, | 629 bool SerializeKnownObject(HeapObject* obj, HowToCode how_to_code, |
581 WhereToPoint where_to_point, int skip); | 630 WhereToPoint where_to_point, int skip); |
| 631 |
| 632 inline void FlushSkip(int skip) { |
| 633 if (skip != 0) { |
| 634 sink_->Put(kSkip, "SkipFromSerializeObject"); |
| 635 sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); |
| 636 } |
| 637 } |
| 638 |
582 void InitializeAllocators(); | 639 void InitializeAllocators(); |
583 // This will return the space for an object. | 640 // This will return the space for an object. |
584 static AllocationSpace SpaceOfObject(HeapObject* object); | 641 static AllocationSpace SpaceOfObject(HeapObject* object); |
585 BackReference AllocateLargeObject(int size); | 642 BackReference AllocateLargeObject(int size); |
586 BackReference Allocate(AllocationSpace space, int size); | 643 BackReference Allocate(AllocationSpace space, int size); |
587 int EncodeExternalReference(Address addr) { | 644 int EncodeExternalReference(Address addr) { |
588 return external_reference_encoder_->Encode(addr); | 645 return external_reference_encoder_->Encode(addr); |
589 } | 646 } |
590 | 647 |
591 // GetInt reads 4 bytes at once, requiring padding at the end. | 648 // GetInt reads 4 bytes at once, requiring padding at the end. |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 class CodeSerializer : public Serializer { | 766 class CodeSerializer : public Serializer { |
710 public: | 767 public: |
711 static ScriptData* Serialize(Isolate* isolate, | 768 static ScriptData* Serialize(Isolate* isolate, |
712 Handle<SharedFunctionInfo> info, | 769 Handle<SharedFunctionInfo> info, |
713 Handle<String> source); | 770 Handle<String> source); |
714 | 771 |
715 MUST_USE_RESULT static MaybeHandle<SharedFunctionInfo> Deserialize( | 772 MUST_USE_RESULT static MaybeHandle<SharedFunctionInfo> Deserialize( |
716 Isolate* isolate, ScriptData* cached_data, Handle<String> source); | 773 Isolate* isolate, ScriptData* cached_data, Handle<String> source); |
717 | 774 |
718 static const int kSourceObjectIndex = 0; | 775 static const int kSourceObjectIndex = 0; |
| 776 STATIC_ASSERT(kSourceObjectReference == kSourceObjectIndex); |
| 777 |
719 static const int kCodeStubsBaseIndex = 1; | 778 static const int kCodeStubsBaseIndex = 1; |
720 | 779 |
721 String* source() const { | 780 String* source() const { |
722 DCHECK(!AllowHeapAllocation::IsAllowed()); | 781 DCHECK(!AllowHeapAllocation::IsAllowed()); |
723 return source_; | 782 return source_; |
724 } | 783 } |
725 | 784 |
726 List<uint32_t>* stub_keys() { return &stub_keys_; } | 785 List<uint32_t>* stub_keys() { return &stub_keys_; } |
727 int num_internalized_strings() const { return num_internalized_strings_; } | 786 int num_internalized_strings() const { return num_internalized_strings_; } |
728 | 787 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
868 // Following the header, we store, in sequential order | 927 // Following the header, we store, in sequential order |
869 // - code stub keys | 928 // - code stub keys |
870 // - serialization payload | 929 // - serialization payload |
871 | 930 |
872 ScriptData* script_data_; | 931 ScriptData* script_data_; |
873 bool owns_script_data_; | 932 bool owns_script_data_; |
874 }; | 933 }; |
875 } } // namespace v8::internal | 934 } } // namespace v8::internal |
876 | 935 |
877 #endif // V8_SERIALIZE_H_ | 936 #endif // V8_SERIALIZE_H_ |
OLD | NEW |