1 // Copyright 2012 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 // ExternalReferenceTable is a helper class that defines the relationship
64 // between external references and their encodings. It is used to build
65 // hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder.
66 class ExternalReferenceTable {
67 public:
68 static ExternalReferenceTable* instance(Isolate* isolate);
69
~ExternalReferenceTable()70 ~ExternalReferenceTable() { }
71
size()72 int size() const { return refs_.length(); }
73
address(int i)74 Address address(int i) { return refs_[i].address; }
75
code(int i)76 uint32_t code(int i) { return refs_[i].code; }
77
name(int i)78 const char* name(int i) { return refs_[i].name; }
79
max_id(int code)80 int max_id(int code) { return max_id_[code]; }
81
82 private:
ExternalReferenceTable(Isolate * isolate)83 explicit ExternalReferenceTable(Isolate* isolate) : refs_(64) {
84 PopulateTable(isolate);
85 }
86
87 struct ExternalReferenceEntry {
88 Address address;
89 uint32_t code;
90 const char* name;
91 };
92
93 void PopulateTable(Isolate* isolate);
94
95 // For a few types of references, we can get their address from their id.
96 void AddFromId(TypeCode type,
97 uint16_t id,
98 const char* name,
99 Isolate* isolate);
100
101 // For other types of references, the caller will figure out the address.
102 void Add(Address address, TypeCode type, uint16_t id, const char* name);
103
104 List<ExternalReferenceEntry> refs_;
105 int max_id_[kTypeCodeCount];
106 };
107
108
109 class ExternalReferenceEncoder {
110 public:
111 ExternalReferenceEncoder();
112
113 uint32_t Encode(Address key) const;
114
115 const char* NameOfAddress(Address key) const;
116
117 private:
118 HashMap encodings_;
Hash(Address key)119 static uint32_t Hash(Address key) {
120 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >> 2);
121 }
122
123 int IndexOf(Address key) const;
124
Match(void * key1,void * key2)125 static bool Match(void* key1, void* key2) { return key1 == key2; }
126
127 void Put(Address key, int index);
128
129 Isolate* isolate_;
130 };
131
132
133 class ExternalReferenceDecoder {
134 public:
135 ExternalReferenceDecoder();
136 ~ExternalReferenceDecoder();
137
Decode(uint32_t key)138 Address Decode(uint32_t key) const {
139 if (key == 0) return NULL;
140 return *Lookup(key);
141 }
142
143 private:
144 Address** encodings_;
145
Lookup(uint32_t key)146 Address* Lookup(uint32_t key) const {
147 int type = key >> kReferenceTypeShift;
148 ASSERT(kFirstTypeCode <= type && type < kTypeCodeCount);
149 int id = key & kReferenceIdMask;
150 return &encodings_[type][id];
151 }
152
Put(uint32_t key,Address value)153 void Put(uint32_t key, Address value) {
154 *Lookup(key) = value;
155 }
156
157 Isolate* isolate_;
158 };
159
160
161 class SnapshotByteSource {
162 public:
SnapshotByteSource(const byte * array,int length)163 SnapshotByteSource(const byte* array, int length)
164 : data_(array), length_(length), position_(0) { }
165
HasMore()166 bool HasMore() { return position_ < length_; }
167
Get()168 int Get() {
169 ASSERT(position_ < length_);
170 return data_[position_++];
171 }
172
173 inline void CopyRaw(byte* to, int number_of_bytes);
174
175 inline int GetInt();
176
AtEOF()177 bool AtEOF() {
178 return position_ == length_;
179 }
180
position()181 int position() { return position_; }
182
183 private:
184 const byte* data_;
185 int length_;
186 int position_;
187 };
188
189
190 #define COMMON_RAW_LENGTHS(f) \
191 f(1, 1) \
192 f(2, 2) \
193 f(3, 3) \
194 f(4, 4) \
195 f(5, 5) \
196 f(6, 6) \
197 f(7, 7) \
198 f(8, 8) \
199 f(9, 12) \
200 f(10, 16) \
201 f(11, 20) \
202 f(12, 24) \
203 f(13, 28) \
204 f(14, 32) \
205 f(15, 36)
206
207 // The Serializer/Deserializer class is a common superclass for Serializer and
208 // Deserializer which is used to store common constants and methods used by
209 // both.
210 class SerializerDeserializer: public ObjectVisitor {
211 public:
212 static void Iterate(ObjectVisitor* visitor);
213 static void SetSnapshotCacheSize(int size);
214
215 protected:
216 // Where the pointed-to object can be found:
217 enum Where {
218 kNewObject = 0, // Object is next in snapshot.
219 // 1-8 One per space.
220 kRootArray = 0x9, // Object is found in root array.
221 kPartialSnapshotCache = 0xa, // Object is in the cache.
222 kExternalReference = 0xb, // Pointer to an external reference.
223 kSkip = 0xc, // Skip a pointer sized cell.
224 // 0xd-0xf Free.
225 kBackref = 0x10, // Object is described relative to end.
226 // 0x11-0x18 One per space.
227 // 0x19-0x1f Free.
228 kFromStart = 0x20, // Object is described relative to start.
229 // 0x21-0x28 One per space.
230 // 0x29-0x2f Free.
231 // 0x30-0x3f Used by misc. tags below.
232 kPointedToMask = 0x3f
233 };
234
235 // How to code the pointer to the object.
236 enum HowToCode {
237 kPlain = 0, // Straight pointer.
238 // What this means depends on the architecture:
239 kFromCode = 0x40, // A pointer inlined in code.
240 kHowToCodeMask = 0x40
241 };
242
243 // Where to point within the object.
244 enum WhereToPoint {
245 kStartOfObject = 0,
246 kFirstInstruction = 0x80,
247 kWhereToPointMask = 0x80
248 };
249
250 // Misc.
251 // Raw data to be copied from the snapshot.
252 static const int kRawData = 0x30;
253 // Some common raw lengths: 0x31-0x3f
254 // A tag emitted at strategic points in the snapshot to delineate sections.
255 // If the deserializer does not find these at the expected moments then it
256 // is an indication that the snapshot and the VM do not fit together.
257 // Examine the build process for architecture, version or configuration
258 // mismatches.
259 static const int kSynchronize = 0x70;
260 // Used for the source code of the natives, which is in the executable, but
261 // is referred to from external strings in the snapshot.
262 static const int kNativesStringResource = 0x71;
263 static const int kNewPage = 0x72;
264 static const int kRepeat = 0x73;
265 static const int kConstantRepeat = 0x74;
266 // 0x74-0x7f Repeat last word (subtract 0x73 to get the count).
267 static const int kMaxRepeats = 0x7f - 0x73;
CodeForRepeats(int repeats)268 static int CodeForRepeats(int repeats) {
269 ASSERT(repeats >= 1 && repeats <= kMaxRepeats);
270 return 0x73 + repeats;
271 }
RepeatsForCode(int byte_code)272 static int RepeatsForCode(int byte_code) {
273 ASSERT(byte_code >= kConstantRepeat && byte_code <= 0x7f);
274 return byte_code - 0x73;
275 }
276 static const int kRootArrayLowConstants = 0xb0;
277 // 0xb0-0xbf Things from the first 16 elements of the root array.
278 static const int kRootArrayHighConstants = 0xf0;
279 // 0xf0-0xff Things from the next 16 elements of the root array.
280 static const int kRootArrayNumberOfConstantEncodings = 0x20;
281 static const int kRootArrayNumberOfLowConstantEncodings = 0x10;
RootArrayConstantFromByteCode(int byte_code)282 static int RootArrayConstantFromByteCode(int byte_code) {
283 int constant = (byte_code & 0xf) | ((byte_code & 0x40) >> 2);
284 ASSERT(constant >= 0 && constant < kRootArrayNumberOfConstantEncodings);
285 return constant;
286 }
287
288
289 static const int kLargeData = LAST_SPACE;
290 static const int kLargeCode = kLargeData + 1;
291 static const int kLargeFixedArray = kLargeCode + 1;
292 static const int kNumberOfSpaces = kLargeFixedArray + 1;
293 static const int kAnyOldSpace = -1;
294
295 // A bitmask for getting the space out of an instruction.
296 static const int kSpaceMask = 15;
297
SpaceIsLarge(int space)298 static inline bool SpaceIsLarge(int space) { return space >= kLargeData; }
SpaceIsPaged(int space)299 static inline bool SpaceIsPaged(int space) {
300 return space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE;
301 }
302 };
303
304
GetInt()305 int SnapshotByteSource::GetInt() {
306 // A little unwind to catch the really small ints.
307 int snapshot_byte = Get();
308 if ((snapshot_byte & 0x80) == 0) {
309 return snapshot_byte;
310 }
311 int accumulator = (snapshot_byte & 0x7f) << 7;
312 while (true) {
313 snapshot_byte = Get();
314 if ((snapshot_byte & 0x80) == 0) {
315 return accumulator | snapshot_byte;
316 }
317 accumulator = (accumulator | (snapshot_byte & 0x7f)) << 7;
318 }
319 UNREACHABLE();
320 return accumulator;
321 }
322
323
CopyRaw(byte * to,int number_of_bytes)324 void SnapshotByteSource::CopyRaw(byte* to, int number_of_bytes) {
325 memcpy(to, data_ + position_, number_of_bytes);
326 position_ += number_of_bytes;
327 }
328
329
330 // A Deserializer reads a snapshot and reconstructs the Object graph it defines.
331 class Deserializer: public SerializerDeserializer {
332 public:
333 // Create a deserializer from a snapshot byte source.
334 explicit Deserializer(SnapshotByteSource* source);
335
336 virtual ~Deserializer();
337
338 // Deserialize the snapshot into an empty heap.
339 void Deserialize();
340
341 // Deserialize a single object and the objects reachable from it.
342 void DeserializePartial(Object** root);
343
344 private:
345 virtual void VisitPointers(Object** start, Object** end);
346
VisitExternalReferences(Address * start,Address * end)347 virtual void VisitExternalReferences(Address* start, Address* end) {
348 UNREACHABLE();
349 }
350
VisitRuntimeEntry(RelocInfo * rinfo)351 virtual void VisitRuntimeEntry(RelocInfo* rinfo) {
352 UNREACHABLE();
353 }
354
355 // Fills in some heap data in an area from start to end (non-inclusive). The
356 // space id is used for the write barrier. The object_address is the address
357 // of the object we are writing into, or NULL if we are not writing into an
358 // object, i.e. if we are writing a series of tagged values that are not on
359 // the heap.
360 void ReadChunk(
361 Object** start, Object** end, int space, Address object_address);
362 HeapObject* GetAddressFromStart(int space);
363 inline HeapObject* GetAddressFromEnd(int space);
364 Address Allocate(int space_number, Space* space, int size);
365 void ReadObject(int space_number, Space* space, Object** write_back);
366
367 // Cached current isolate.
368 Isolate* isolate_;
369
370 // Keep track of the pages in the paged spaces.
371 // (In large object space we are keeping track of individual objects
372 // rather than pages.) In new space we just need the address of the
373 // first object and the others will flow from that.
374 List<Address> pages_[SerializerDeserializer::kNumberOfSpaces];
375
376 SnapshotByteSource* source_;
377 // This is the address of the next object that will be allocated in each
378 // space. It is used to calculate the addresses of back-references.
379 Address high_water_[LAST_SPACE + 1];
380 // This is the address of the most recent object that was allocated. It
381 // is used to set the location of the new page when we encounter a
382 // START_NEW_PAGE_SERIALIZATION tag.
383 Address last_object_address_;
384
385 ExternalReferenceDecoder* external_reference_decoder_;
386
387 DISALLOW_COPY_AND_ASSIGN(Deserializer);
388 };
389
390
391 class SnapshotByteSink {
392 public:
~SnapshotByteSink()393 virtual ~SnapshotByteSink() { }
394 virtual void Put(int byte, const char* description) = 0;
PutSection(int byte,const char * description)395 virtual void PutSection(int byte, const char* description) {
396 Put(byte, description);
397 }
398 void PutInt(uintptr_t integer, const char* description);
399 virtual int Position() = 0;
400 };
401
402
403 // Mapping objects to their location after deserialization.
404 // This is used during building, but not at runtime by V8.
405 class SerializationAddressMapper {
406 public:
SerializationAddressMapper()407 SerializationAddressMapper()
408 : serialization_map_(new HashMap(&SerializationMatchFun)),
409 no_allocation_(new AssertNoAllocation()) { }
410
~SerializationAddressMapper()411 ~SerializationAddressMapper() {
412 delete serialization_map_;
413 delete no_allocation_;
414 }
415
IsMapped(HeapObject * obj)416 bool IsMapped(HeapObject* obj) {
417 return serialization_map_->Lookup(Key(obj), Hash(obj), false) != NULL;
418 }
419
MappedTo(HeapObject * obj)420 int MappedTo(HeapObject* obj) {
421 ASSERT(IsMapped(obj));
422 return static_cast<int>(reinterpret_cast<intptr_t>(
423 serialization_map_->Lookup(Key(obj), Hash(obj), false)->value));
424 }
425
AddMapping(HeapObject * obj,int to)426 void AddMapping(HeapObject* obj, int to) {
427 ASSERT(!IsMapped(obj));
428 HashMap::Entry* entry =
429 serialization_map_->Lookup(Key(obj), Hash(obj), true);
430 entry->value = Value(to);
431 }
432
433 private:
SerializationMatchFun(void * key1,void * key2)434 static bool SerializationMatchFun(void* key1, void* key2) {
435 return key1 == key2;
436 }
437
Hash(HeapObject * obj)438 static uint32_t Hash(HeapObject* obj) {
439 return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
440 }
441
Key(HeapObject * obj)442 static void* Key(HeapObject* obj) {
443 return reinterpret_cast<void*>(obj->address());
444 }
445
Value(int v)446 static void* Value(int v) {
447 return reinterpret_cast<void*>(v);
448 }
449
450 HashMap* serialization_map_;
451 AssertNoAllocation* no_allocation_;
452 DISALLOW_COPY_AND_ASSIGN(SerializationAddressMapper);
453 };
454
455
456 // There can be only one serializer per V8 process.
457 class Serializer : public SerializerDeserializer {
458 public:
459 explicit Serializer(SnapshotByteSink* sink);
460 ~Serializer();
461 void VisitPointers(Object** start, Object** end);
462 // You can call this after serialization to find out how much space was used
463 // in each space.
CurrentAllocationAddress(int space)464 int CurrentAllocationAddress(int space) {
465 if (SpaceIsLarge(space)) return large_object_total_;
466 return fullness_[space];
467 }
468
Enable()469 static void Enable() {
470 if (!serialization_enabled_) {
471 ASSERT(!too_late_to_enable_now_);
472 }
473 serialization_enabled_ = true;
474 }
475
Disable()476 static void Disable() { serialization_enabled_ = false; }
477 // Call this when you have made use of the fact that there is no serialization
478 // going on.
TooLateToEnableNow()479 static void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
enabled()480 static bool enabled() { return serialization_enabled_; }
address_mapper()481 SerializationAddressMapper* address_mapper() { return &address_mapper_; }
482 void PutRoot(
483 int index, HeapObject* object, HowToCode how, WhereToPoint where);
484
485 protected:
486 static const int kInvalidRootIndex = -1;
487
488 int RootIndex(HeapObject* heap_object, HowToCode from);
489 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) = 0;
root_index_wave_front()490 intptr_t root_index_wave_front() { return root_index_wave_front_; }
set_root_index_wave_front(intptr_t value)491 void set_root_index_wave_front(intptr_t value) {
492 ASSERT(value >= root_index_wave_front_);
493 root_index_wave_front_ = value;
494 }
495
496 class ObjectSerializer : public ObjectVisitor {
497 public:
ObjectSerializer(Serializer * serializer,Object * o,SnapshotByteSink * sink,HowToCode how_to_code,WhereToPoint where_to_point)498 ObjectSerializer(Serializer* serializer,
499 Object* o,
500 SnapshotByteSink* sink,
501 HowToCode how_to_code,
502 WhereToPoint where_to_point)
503 : serializer_(serializer),
504 object_(HeapObject::cast(o)),
505 sink_(sink),
506 reference_representation_(how_to_code + where_to_point),
507 bytes_processed_so_far_(0) { }
508 void Serialize();
509 void VisitPointers(Object** start, Object** end);
510 void VisitEmbeddedPointer(RelocInfo* target);
511 void VisitExternalReferences(Address* start, Address* end);
512 void VisitExternalReference(RelocInfo* rinfo);
513 void VisitCodeTarget(RelocInfo* target);
514 void VisitCodeEntry(Address entry_address);
515 void VisitGlobalPropertyCell(RelocInfo* rinfo);
516 void VisitRuntimeEntry(RelocInfo* reloc);
517 // Used for seralizing the external strings that hold the natives source.
518 void VisitExternalAsciiString(
519 v8::String::ExternalAsciiStringResource** resource);
520 // We can't serialize a heap with external two byte strings.
VisitExternalTwoByteString(v8::String::ExternalStringResource ** resource)521 void VisitExternalTwoByteString(
522 v8::String::ExternalStringResource** resource) {
523 UNREACHABLE();
524 }
525
526 private:
527 void OutputRawData(Address up_to);
528
529 Serializer* serializer_;
530 HeapObject* object_;
531 SnapshotByteSink* sink_;
532 int reference_representation_;
533 int bytes_processed_so_far_;
534 };
535
536 virtual void SerializeObject(Object* o,
537 HowToCode how_to_code,
538 WhereToPoint where_to_point) = 0;
539 void SerializeReferenceToPreviousObject(
540 int space,
541 int address,
542 HowToCode how_to_code,
543 WhereToPoint where_to_point);
544 void InitializeAllocators();
545 // This will return the space for an object. If the object is in large
546 // object space it may return kLargeCode or kLargeFixedArray in order
547 // to indicate to the deserializer what kind of large object allocation
548 // to make.
549 static int SpaceOfObject(HeapObject* object);
550 // This just returns the space of the object. It will return LO_SPACE
551 // for all large objects since you can't check the type of the object
552 // once the map has been used for the serialization address.
553 static int SpaceOfAlreadySerializedObject(HeapObject* object);
554 int Allocate(int space, int size, bool* new_page_started);
EncodeExternalReference(Address addr)555 int EncodeExternalReference(Address addr) {
556 return external_reference_encoder_->Encode(addr);
557 }
558
559 int SpaceAreaSize(int space);
560
561 Isolate* isolate_;
562 // Keep track of the fullness of each space in order to generate
563 // relative addresses for back references. Large objects are
564 // just numbered sequentially since relative addresses make no
565 // sense in large object space.
566 int fullness_[LAST_SPACE + 1];
567 SnapshotByteSink* sink_;
568 int current_root_index_;
569 ExternalReferenceEncoder* external_reference_encoder_;
570 static bool serialization_enabled_;
571 // Did we already make use of the fact that serialization was not enabled?
572 static bool too_late_to_enable_now_;
573 int large_object_total_;
574 SerializationAddressMapper address_mapper_;
575 intptr_t root_index_wave_front_;
576
577 friend class ObjectSerializer;
578 friend class Deserializer;
579
580 private:
581 DISALLOW_COPY_AND_ASSIGN(Serializer);
582 };
583
584
585 class PartialSerializer : public Serializer {
586 public:
PartialSerializer(Serializer * startup_snapshot_serializer,SnapshotByteSink * sink)587 PartialSerializer(Serializer* startup_snapshot_serializer,
588 SnapshotByteSink* sink)
589 : Serializer(sink),
590 startup_serializer_(startup_snapshot_serializer) {
591 set_root_index_wave_front(Heap::kStrongRootListLength);
592 }
593
594 // Serialize the objects reachable from a single object pointer.
595 virtual void Serialize(Object** o);
596 virtual void SerializeObject(Object* o,
597 HowToCode how_to_code,
598 WhereToPoint where_to_point);
599
600 protected:
601 virtual int PartialSnapshotCacheIndex(HeapObject* o);
ShouldBeInThePartialSnapshotCache(HeapObject * o)602 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
603 // Scripts should be referred only through shared function infos. We can't
604 // allow them to be part of the partial snapshot because they contain a
605 // unique ID, and deserializing several partial snapshots containing script
606 // would cause dupes.
607 ASSERT(!o->IsScript());
608 return o->IsString() || o->IsSharedFunctionInfo() ||
609 o->IsHeapNumber() || o->IsCode() ||
610 o->IsScopeInfo() ||
611 o->map() == HEAP->fixed_cow_array_map();
612 }
613
614 private:
615 Serializer* startup_serializer_;
616 DISALLOW_COPY_AND_ASSIGN(PartialSerializer);
617 };
618
619
620 class StartupSerializer : public Serializer {
621 public:
StartupSerializer(SnapshotByteSink * sink)622 explicit StartupSerializer(SnapshotByteSink* sink) : Serializer(sink) {
623 // Clear the cache of objects used by the partial snapshot. After the
624 // strong roots have been serialized we can create a partial snapshot
625 // which will repopulate the cache with objects needed by that partial
626 // snapshot.
627 Isolate::Current()->set_serialize_partial_snapshot_cache_length(0);
628 }
629 // Serialize the current state of the heap. The order is:
630 // 1) Strong references.
631 // 2) Partial snapshot cache.
632 // 3) Weak references (e.g. the symbol table).
633 virtual void SerializeStrongReferences();
634 virtual void SerializeObject(Object* o,
635 HowToCode how_to_code,
636 WhereToPoint where_to_point);
637 void SerializeWeakReferences();
Serialize()638 void Serialize() {
639 SerializeStrongReferences();
640 SerializeWeakReferences();
641 }
642
643 private:
ShouldBeInThePartialSnapshotCache(HeapObject * o)644 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
645 return false;
646 }
647 };
648
649
650 } } // namespace v8::internal
651
652 #endif // V8_SERIALIZE_H_
653