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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 | 130 |
131 int position() { return position_; } | 131 int position() { return position_; } |
132 | 132 |
133 private: | 133 private: |
134 const byte* data_; | 134 const byte* data_; |
135 int length_; | 135 int length_; |
136 int position_; | 136 int position_; |
137 }; | 137 }; |
138 | 138 |
139 | 139 |
140 // It is very common to have a reference to the object at word 10 in space 2, | 140 // It is very common to have a reference to objects at certain offsets in the |
141 // the object at word 5 in space 2 and the object at word 28 in space 4. This | 141 // heap. These offsets have been determined experimentally. We code |
142 // only works for objects in the first page of a space. | 142 // references to such objects in a single byte that encodes the way the pointer |
143 #define COMMON_REFERENCE_PATTERNS(f) \ | 143 // is written (only plain pointers allowed), the space number and the offset. |
144 f(kNumberOfSpaces, 2, 10) \ | 144 // This only works for objects in the first page of a space. Don't use this for |
145 f(kNumberOfSpaces + 1, 2, 5) \ | 145 // things in newspace since it bypasses the write barrier. |
146 f(kNumberOfSpaces + 2, 4, 28) \ | 146 |
147 f(kNumberOfSpaces + 3, 2, 21) \ | 147 static const int k64 = (sizeof(uintptr_t) - 4) / 4; |
148 f(kNumberOfSpaces + 4, 2, 98) \ | 148 |
149 f(kNumberOfSpaces + 5, 2, 67) \ | 149 #define COMMON_REFERENCE_PATTERNS(f) \ |
150 f(kNumberOfSpaces + 6, 4, 132) | 150 f(kNumberOfSpaces, 2, 11 - k64) \ |
| 151 f(kNumberOfSpaces + 1, 2, 0) \ |
| 152 f(kNumberOfSpaces + 2, 2, 142 - 16 * k64) \ |
| 153 f(kNumberOfSpaces + 3, 2, 74 - 15 * k64) \ |
| 154 f(kNumberOfSpaces + 4, 2, 5) \ |
| 155 f(kNumberOfSpaces + 5, 1, 135) \ |
| 156 f(kNumberOfSpaces + 6, 2, 228 - 39 * k64) |
151 | 157 |
152 #define COMMON_RAW_LENGTHS(f) \ | 158 #define COMMON_RAW_LENGTHS(f) \ |
153 f(1, 1) \ | 159 f(1, 1) \ |
154 f(2, 2) \ | 160 f(2, 2) \ |
155 f(3, 3) \ | 161 f(3, 3) \ |
156 f(4, 4) \ | 162 f(4, 4) \ |
157 f(5, 5) \ | 163 f(5, 5) \ |
158 f(6, 6) \ | 164 f(6, 6) \ |
159 f(7, 7) \ | 165 f(7, 7) \ |
160 f(8, 8) \ | 166 f(8, 8) \ |
161 f(9, 12) \ | 167 f(9, 12) \ |
162 f(10, 16) \ | 168 f(10, 16) \ |
163 f(11, 20) \ | 169 f(11, 20) \ |
164 f(12, 24) \ | 170 f(12, 24) \ |
165 f(13, 28) \ | 171 f(13, 28) \ |
166 f(14, 32) \ | 172 f(14, 32) \ |
167 f(15, 36) | 173 f(15, 36) |
168 | 174 |
169 // The Serializer/Deserializer class is a common superclass for Serializer and | 175 // The Serializer/Deserializer class is a common superclass for Serializer and |
170 // Deserializer which is used to store common constants and methods used by | 176 // Deserializer which is used to store common constants and methods used by |
171 // both. | 177 // both. |
172 class SerializerDeserializer: public ObjectVisitor { | 178 class SerializerDeserializer: public ObjectVisitor { |
173 public: | 179 public: |
174 static void Iterate(ObjectVisitor* visitor); | 180 static void Iterate(ObjectVisitor* visitor); |
175 static void SetSnapshotCacheSize(int size); | 181 static void SetSnapshotCacheSize(int size); |
176 | 182 |
177 protected: | 183 protected: |
178 enum DataType { | 184 // Where the pointed-to object can be found: |
179 RAW_DATA_SERIALIZATION = 0, | 185 enum Where { |
180 // And 15 common raw lengths. | 186 kNewObject = 0, // Object is next in snapshot. |
181 OBJECT_SERIALIZATION = 16, | 187 // 1-8 One per space. |
182 // One variant per space. | 188 kRootArray = 0x9, // Object is found in root array. |
183 CODE_OBJECT_SERIALIZATION = 25, | 189 kPartialSnapshotCache = 0xa, // Object is in the cache. |
184 // One per space (only code spaces in use). | 190 kExternalReference = 0xb, // Pointer to an external reference. |
185 EXTERNAL_REFERENCE_SERIALIZATION = 34, | 191 // 0xc-0xf Free. |
186 EXTERNAL_BRANCH_TARGET_SERIALIZATION = 35, | 192 kBackref = 0x10, // Object is described relative to end. |
187 SYNCHRONIZE = 36, | 193 // 0x11-0x18 One per space. |
188 START_NEW_PAGE_SERIALIZATION = 37, | 194 // 0x19-0x1f Common backref offsets. |
189 NATIVES_STRING_RESOURCE = 38, | 195 kFromStart = 0x20, // Object is described relative to start. |
190 ROOT_SERIALIZATION = 39, | 196 // 0x21-0x28 One per space. |
191 PARTIAL_SNAPSHOT_CACHE_ENTRY = 40, | 197 // 0x29-0x2f Free. |
192 // Free: 41-47. | 198 // 0x30-0x3f Used by misc tags below. |
193 BACKREF_SERIALIZATION = 48, | 199 kPointedToMask = 0x3f |
194 // One per space, must be kSpaceMask aligned. | |
195 // Free: 57-63. | |
196 REFERENCE_SERIALIZATION = 64, | |
197 // One per space and common references. Must be kSpaceMask aligned. | |
198 CODE_BACKREF_SERIALIZATION = 80, | |
199 // One per space, must be kSpaceMask aligned. | |
200 // Free: 89-95. | |
201 CODE_REFERENCE_SERIALIZATION = 96 | |
202 // One per space, must be kSpaceMask aligned. | |
203 // Free: 105-255. | |
204 }; | 200 }; |
| 201 |
| 202 // How to code the pointer to the object. |
| 203 enum HowToCode { |
| 204 kPlain = 0, // Straight pointer. |
| 205 // What this means depends on the architecture: |
| 206 kFromCode = 0x40, // A pointer inlined in code. |
| 207 kHowToCodeMask = 0x40 |
| 208 }; |
| 209 |
| 210 // Where to point within the object. |
| 211 enum WhereToPoint { |
| 212 kStartOfObject = 0, |
| 213 kFirstInstruction = 0x80, |
| 214 kWhereToPointMask = 0x80 |
| 215 }; |
| 216 |
| 217 // Misc. |
| 218 // Raw data to be copied from the snapshot. |
| 219 static const int kRawData = 0x30; |
| 220 // Some common raw lengths: 0x31-0x3f |
| 221 // A tag emitted at strategic points in the snapshot to delineate sections. |
| 222 // If the deserializer does not find these at the expected moments then it |
| 223 // is an indication that the snapshot and the VM do not fit together. |
| 224 // Examine the build process for architecture, version or configuration |
| 225 // mismatches. |
| 226 static const int kSynchronize = 0x70; |
| 227 // Used for the source code of the natives, which is in the executable, but |
| 228 // is referred to from external strings in the snapshot. |
| 229 static const int kNativesStringResource = 0x71; |
| 230 static const int kNewPage = 0x72; |
| 231 // 0x73-0x7f Free. |
| 232 // 0xb0-0xbf Free. |
| 233 // 0xf0-0xff Free. |
| 234 |
| 235 |
205 static const int kLargeData = LAST_SPACE; | 236 static const int kLargeData = LAST_SPACE; |
206 static const int kLargeCode = kLargeData + 1; | 237 static const int kLargeCode = kLargeData + 1; |
207 static const int kLargeFixedArray = kLargeCode + 1; | 238 static const int kLargeFixedArray = kLargeCode + 1; |
208 static const int kNumberOfSpaces = kLargeFixedArray + 1; | 239 static const int kNumberOfSpaces = kLargeFixedArray + 1; |
| 240 static const int kAnyOldSpace = -1; |
209 | 241 |
210 // A bitmask for getting the space out of an instruction. | 242 // A bitmask for getting the space out of an instruction. |
211 static const int kSpaceMask = 15; | 243 static const int kSpaceMask = 15; |
212 | 244 |
213 static inline bool SpaceIsLarge(int space) { return space >= kLargeData; } | 245 static inline bool SpaceIsLarge(int space) { return space >= kLargeData; } |
214 static inline bool SpaceIsPaged(int space) { | 246 static inline bool SpaceIsPaged(int space) { |
215 return space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE; | 247 return space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE; |
216 } | 248 } |
217 | 249 |
218 static int partial_snapshot_cache_length_; | 250 static int partial_snapshot_cache_length_; |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 // Call this when you have made use of the fact that there is no serialization | 421 // Call this when you have made use of the fact that there is no serialization |
390 // going on. | 422 // going on. |
391 static void TooLateToEnableNow() { too_late_to_enable_now_ = true; } | 423 static void TooLateToEnableNow() { too_late_to_enable_now_ = true; } |
392 static bool enabled() { return serialization_enabled_; } | 424 static bool enabled() { return serialization_enabled_; } |
393 SerializationAddressMapper* address_mapper() { return &address_mapper_; } | 425 SerializationAddressMapper* address_mapper() { return &address_mapper_; } |
394 #ifdef DEBUG | 426 #ifdef DEBUG |
395 virtual void Synchronize(const char* tag); | 427 virtual void Synchronize(const char* tag); |
396 #endif | 428 #endif |
397 | 429 |
398 protected: | 430 protected: |
399 enum ReferenceRepresentation { | |
400 TAGGED_REPRESENTATION, // A tagged object reference. | |
401 CODE_TARGET_REPRESENTATION // A reference to first instruction in target. | |
402 }; | |
403 static const int kInvalidRootIndex = -1; | 431 static const int kInvalidRootIndex = -1; |
404 virtual int RootIndex(HeapObject* heap_object) = 0; | 432 virtual int RootIndex(HeapObject* heap_object) = 0; |
405 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) = 0; | 433 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) = 0; |
406 | 434 |
407 class ObjectSerializer : public ObjectVisitor { | 435 class ObjectSerializer : public ObjectVisitor { |
408 public: | 436 public: |
409 ObjectSerializer(Serializer* serializer, | 437 ObjectSerializer(Serializer* serializer, |
410 Object* o, | 438 Object* o, |
411 SnapshotByteSink* sink, | 439 SnapshotByteSink* sink, |
412 ReferenceRepresentation representation) | 440 HowToCode how_to_code, |
| 441 WhereToPoint where_to_point) |
413 : serializer_(serializer), | 442 : serializer_(serializer), |
414 object_(HeapObject::cast(o)), | 443 object_(HeapObject::cast(o)), |
415 sink_(sink), | 444 sink_(sink), |
416 reference_representation_(representation), | 445 reference_representation_(how_to_code + where_to_point), |
417 bytes_processed_so_far_(0) { } | 446 bytes_processed_so_far_(0) { } |
418 void Serialize(); | 447 void Serialize(); |
419 void VisitPointers(Object** start, Object** end); | 448 void VisitPointers(Object** start, Object** end); |
420 void VisitExternalReferences(Address* start, Address* end); | 449 void VisitExternalReferences(Address* start, Address* end); |
421 void VisitCodeTarget(RelocInfo* target); | 450 void VisitCodeTarget(RelocInfo* target); |
422 void VisitRuntimeEntry(RelocInfo* reloc); | 451 void VisitRuntimeEntry(RelocInfo* reloc); |
423 // Used for seralizing the external strings that hold the natives source. | 452 // Used for seralizing the external strings that hold the natives source. |
424 void VisitExternalAsciiString( | 453 void VisitExternalAsciiString( |
425 v8::String::ExternalAsciiStringResource** resource); | 454 v8::String::ExternalAsciiStringResource** resource); |
426 // We can't serialize a heap with external two byte strings. | 455 // We can't serialize a heap with external two byte strings. |
427 void VisitExternalTwoByteString( | 456 void VisitExternalTwoByteString( |
428 v8::String::ExternalStringResource** resource) { | 457 v8::String::ExternalStringResource** resource) { |
429 UNREACHABLE(); | 458 UNREACHABLE(); |
430 } | 459 } |
431 | 460 |
432 private: | 461 private: |
433 void OutputRawData(Address up_to); | 462 void OutputRawData(Address up_to); |
434 | 463 |
435 Serializer* serializer_; | 464 Serializer* serializer_; |
436 HeapObject* object_; | 465 HeapObject* object_; |
437 SnapshotByteSink* sink_; | 466 SnapshotByteSink* sink_; |
438 ReferenceRepresentation reference_representation_; | 467 int reference_representation_; |
439 int bytes_processed_so_far_; | 468 int bytes_processed_so_far_; |
440 }; | 469 }; |
441 | 470 |
442 virtual void SerializeObject(Object* o, | 471 virtual void SerializeObject(Object* o, |
443 ReferenceRepresentation representation) = 0; | 472 HowToCode how_to_code, |
| 473 WhereToPoint where_to_point) = 0; |
444 void SerializeReferenceToPreviousObject( | 474 void SerializeReferenceToPreviousObject( |
445 int space, | 475 int space, |
446 int address, | 476 int address, |
447 ReferenceRepresentation reference_representation); | 477 HowToCode how_to_code, |
| 478 WhereToPoint where_to_point); |
448 void InitializeAllocators(); | 479 void InitializeAllocators(); |
449 // This will return the space for an object. If the object is in large | 480 // This will return the space for an object. If the object is in large |
450 // object space it may return kLargeCode or kLargeFixedArray in order | 481 // object space it may return kLargeCode or kLargeFixedArray in order |
451 // to indicate to the deserializer what kind of large object allocation | 482 // to indicate to the deserializer what kind of large object allocation |
452 // to make. | 483 // to make. |
453 static int SpaceOfObject(HeapObject* object); | 484 static int SpaceOfObject(HeapObject* object); |
454 // This just returns the space of the object. It will return LO_SPACE | 485 // This just returns the space of the object. It will return LO_SPACE |
455 // for all large objects since you can't check the type of the object | 486 // for all large objects since you can't check the type of the object |
456 // once the map has been used for the serialization address. | 487 // once the map has been used for the serialization address. |
457 static int SpaceOfAlreadySerializedObject(HeapObject* object); | 488 static int SpaceOfAlreadySerializedObject(HeapObject* object); |
(...skipping 27 matching lines...) Expand all Loading... |
485 public: | 516 public: |
486 PartialSerializer(Serializer* startup_snapshot_serializer, | 517 PartialSerializer(Serializer* startup_snapshot_serializer, |
487 SnapshotByteSink* sink) | 518 SnapshotByteSink* sink) |
488 : Serializer(sink), | 519 : Serializer(sink), |
489 startup_serializer_(startup_snapshot_serializer) { | 520 startup_serializer_(startup_snapshot_serializer) { |
490 } | 521 } |
491 | 522 |
492 // Serialize the objects reachable from a single object pointer. | 523 // Serialize the objects reachable from a single object pointer. |
493 virtual void Serialize(Object** o); | 524 virtual void Serialize(Object** o); |
494 virtual void SerializeObject(Object* o, | 525 virtual void SerializeObject(Object* o, |
495 ReferenceRepresentation representation); | 526 HowToCode how_to_code, |
| 527 WhereToPoint where_to_point); |
496 | 528 |
497 protected: | 529 protected: |
498 virtual int RootIndex(HeapObject* o); | 530 virtual int RootIndex(HeapObject* o); |
499 virtual int PartialSnapshotCacheIndex(HeapObject* o); | 531 virtual int PartialSnapshotCacheIndex(HeapObject* o); |
500 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) { | 532 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) { |
501 // Scripts should be referred only through shared function infos. We can't | 533 // Scripts should be referred only through shared function infos. We can't |
502 // allow them to be part of the partial snapshot because they contain a | 534 // allow them to be part of the partial snapshot because they contain a |
503 // unique ID, and deserializing several partial snapshots containing script | 535 // unique ID, and deserializing several partial snapshots containing script |
504 // would cause dupes. | 536 // would cause dupes. |
505 ASSERT(!o->IsScript()); | 537 ASSERT(!o->IsScript()); |
(...skipping 15 matching lines...) Expand all Loading... |
521 // which will repopulate the cache with objects neede by that partial | 553 // which will repopulate the cache with objects neede by that partial |
522 // snapshot. | 554 // snapshot. |
523 partial_snapshot_cache_length_ = 0; | 555 partial_snapshot_cache_length_ = 0; |
524 } | 556 } |
525 // Serialize the current state of the heap. The order is: | 557 // Serialize the current state of the heap. The order is: |
526 // 1) Strong references. | 558 // 1) Strong references. |
527 // 2) Partial snapshot cache. | 559 // 2) Partial snapshot cache. |
528 // 3) Weak references (eg the symbol table). | 560 // 3) Weak references (eg the symbol table). |
529 virtual void SerializeStrongReferences(); | 561 virtual void SerializeStrongReferences(); |
530 virtual void SerializeObject(Object* o, | 562 virtual void SerializeObject(Object* o, |
531 ReferenceRepresentation representation); | 563 HowToCode how_to_code, |
| 564 WhereToPoint where_to_point); |
532 void SerializeWeakReferences(); | 565 void SerializeWeakReferences(); |
533 void Serialize() { | 566 void Serialize() { |
534 SerializeStrongReferences(); | 567 SerializeStrongReferences(); |
535 SerializeWeakReferences(); | 568 SerializeWeakReferences(); |
536 } | 569 } |
537 | 570 |
538 private: | 571 private: |
539 virtual int RootIndex(HeapObject* o) { return kInvalidRootIndex; } | 572 virtual int RootIndex(HeapObject* o) { return kInvalidRootIndex; } |
540 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) { | 573 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) { |
541 return false; | 574 return false; |
542 } | 575 } |
543 }; | 576 }; |
544 | 577 |
545 | 578 |
546 } } // namespace v8::internal | 579 } } // namespace v8::internal |
547 | 580 |
548 #endif // V8_SERIALIZE_H_ | 581 #endif // V8_SERIALIZE_H_ |
OLD | NEW |