Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / v8 / src / serialize.h
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
3 // found in the LICENSE file.
4
5 #ifndef V8_SERIALIZE_H_
6 #define V8_SERIALIZE_H_
7
8 #include "src/compiler.h"
9 #include "src/hashmap.h"
10 #include "src/heap-profiler.h"
11 #include "src/isolate.h"
12 #include "src/snapshot-source-sink.h"
13
14 namespace v8 {
15 namespace internal {
16
17 // A TypeCode is used to distinguish different kinds of external reference.
18 // It is a single bit to make testing for types easy.
19 enum TypeCode {
20   UNCLASSIFIED,  // One-of-a-kind references.
21   C_BUILTIN,
22   BUILTIN,
23   RUNTIME_FUNCTION,
24   IC_UTILITY,
25   STATS_COUNTER,
26   TOP_ADDRESS,
27   ACCESSOR,
28   STUB_CACHE_TABLE,
29   RUNTIME_ENTRY,
30   LAZY_DEOPTIMIZATION
31 };
32
33 const int kTypeCodeCount = LAZY_DEOPTIMIZATION + 1;
34 const int kFirstTypeCode = UNCLASSIFIED;
35
36 const int kReferenceIdBits = 16;
37 const int kReferenceIdMask = (1 << kReferenceIdBits) - 1;
38 const int kReferenceTypeShift = kReferenceIdBits;
39
40 const int kDeoptTableSerializeEntryCount = 64;
41
42 // ExternalReferenceTable is a helper class that defines the relationship
43 // between external references and their encodings. It is used to build
44 // hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder.
45 class ExternalReferenceTable {
46  public:
47   static ExternalReferenceTable* instance(Isolate* isolate);
48
49   ~ExternalReferenceTable() { }
50
51   int size() const { return refs_.length(); }
52
53   Address address(int i) { return refs_[i].address; }
54
55   uint32_t code(int i) { return refs_[i].code; }
56
57   const char* name(int i) { return refs_[i].name; }
58
59   int max_id(int code) { return max_id_[code]; }
60
61  private:
62   explicit ExternalReferenceTable(Isolate* isolate) : refs_(64) {
63     PopulateTable(isolate);
64   }
65
66   struct ExternalReferenceEntry {
67     Address address;
68     uint32_t code;
69     const char* name;
70   };
71
72   void PopulateTable(Isolate* isolate);
73
74   // For a few types of references, we can get their address from their id.
75   void AddFromId(TypeCode type,
76                  uint16_t id,
77                  const char* name,
78                  Isolate* isolate);
79
80   // For other types of references, the caller will figure out the address.
81   void Add(Address address, TypeCode type, uint16_t id, const char* name);
82
83   void Add(Address address, const char* name) {
84     Add(address, UNCLASSIFIED, ++max_id_[UNCLASSIFIED], name);
85   }
86
87   List<ExternalReferenceEntry> refs_;
88   uint16_t max_id_[kTypeCodeCount];
89 };
90
91
92 class ExternalReferenceEncoder {
93  public:
94   explicit ExternalReferenceEncoder(Isolate* isolate);
95
96   uint32_t Encode(Address key) const;
97
98   const char* NameOfAddress(Address key) const;
99
100  private:
101   HashMap encodings_;
102   static uint32_t Hash(Address key) {
103     return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >> 2);
104   }
105
106   int IndexOf(Address key) const;
107
108   void Put(Address key, int index);
109
110   Isolate* isolate_;
111 };
112
113
114 class ExternalReferenceDecoder {
115  public:
116   explicit ExternalReferenceDecoder(Isolate* isolate);
117   ~ExternalReferenceDecoder();
118
119   Address Decode(uint32_t key) const {
120     if (key == 0) return NULL;
121     return *Lookup(key);
122   }
123
124  private:
125   Address** encodings_;
126
127   Address* Lookup(uint32_t key) const {
128     int type = key >> kReferenceTypeShift;
129     DCHECK(kFirstTypeCode <= type && type < kTypeCodeCount);
130     int id = key & kReferenceIdMask;
131     return &encodings_[type][id];
132   }
133
134   void Put(uint32_t key, Address value) {
135     *Lookup(key) = value;
136   }
137
138   Isolate* isolate_;
139 };
140
141
142 // The Serializer/Deserializer class is a common superclass for Serializer and
143 // Deserializer which is used to store common constants and methods used by
144 // both.
145 class SerializerDeserializer: public ObjectVisitor {
146  public:
147   static void Iterate(Isolate* isolate, ObjectVisitor* visitor);
148
149   static int nop() { return kNop; }
150
151  protected:
152   // Where the pointed-to object can be found:
153   enum Where {
154     kNewObject = 0,  // Object is next in snapshot.
155     // 1-6                             One per space.
156     kRootArray = 0x9,             // Object is found in root array.
157     kPartialSnapshotCache = 0xa,  // Object is in the cache.
158     kExternalReference = 0xb,     // Pointer to an external reference.
159     kSkip = 0xc,                  // Skip n bytes.
160     kBuiltin = 0xd,               // Builtin code object.
161     kAttachedReference = 0xe,     // Object is described in an attached list.
162     kNop = 0xf,                   // Does nothing, used to pad.
163     kBackref = 0x10,              // Object is described relative to end.
164     // 0x11-0x16                       One per space.
165     kBackrefWithSkip = 0x18,  // Object is described relative to end.
166     // 0x19-0x1e                       One per space.
167     // 0x20-0x3f                       Used by misc. tags below.
168     kPointedToMask = 0x3f
169   };
170
171   // How to code the pointer to the object.
172   enum HowToCode {
173     kPlain = 0,                          // Straight pointer.
174     // What this means depends on the architecture:
175     kFromCode = 0x40,                    // A pointer inlined in code.
176     kHowToCodeMask = 0x40
177   };
178
179   // For kRootArrayConstants
180   enum WithSkip {
181     kNoSkipDistance = 0,
182     kHasSkipDistance = 0x40,
183     kWithSkipMask = 0x40
184   };
185
186   // Where to point within the object.
187   enum WhereToPoint {
188     kStartOfObject = 0,
189     kInnerPointer = 0x80,  // First insn in code object or payload of cell.
190     kWhereToPointMask = 0x80
191   };
192
193   // Misc.
194   // Raw data to be copied from the snapshot.  This byte code does not advance
195   // the current pointer, which is used for code objects, where we write the
196   // entire code in one memcpy, then fix up stuff with kSkip and other byte
197   // codes that overwrite data.
198   static const int kRawData = 0x20;
199   // Some common raw lengths: 0x21-0x3f.  These autoadvance the current pointer.
200   // A tag emitted at strategic points in the snapshot to delineate sections.
201   // If the deserializer does not find these at the expected moments then it
202   // is an indication that the snapshot and the VM do not fit together.
203   // Examine the build process for architecture, version or configuration
204   // mismatches.
205   static const int kSynchronize = 0x70;
206   // Used for the source code of the natives, which is in the executable, but
207   // is referred to from external strings in the snapshot.
208   static const int kNativesStringResource = 0x71;
209   static const int kRepeat = 0x72;
210   static const int kConstantRepeat = 0x73;
211   // 0x73-0x7f            Repeat last word (subtract 0x72 to get the count).
212   static const int kMaxRepeats = 0x7f - 0x72;
213   static int CodeForRepeats(int repeats) {
214     DCHECK(repeats >= 1 && repeats <= kMaxRepeats);
215     return 0x72 + repeats;
216   }
217   static int RepeatsForCode(int byte_code) {
218     DCHECK(byte_code >= kConstantRepeat && byte_code <= 0x7f);
219     return byte_code - 0x72;
220   }
221   static const int kRootArrayConstants = 0xa0;
222   // 0xa0-0xbf            Things from the first 32 elements of the root array.
223   static const int kRootArrayNumberOfConstantEncodings = 0x20;
224   static int RootArrayConstantFromByteCode(int byte_code) {
225     return byte_code & 0x1f;
226   }
227
228   static const int kNumberOfSpaces = LO_SPACE;
229   static const int kAnyOldSpace = -1;
230
231   // A bitmask for getting the space out of an instruction.
232   static const int kSpaceMask = 7;
233 };
234
235
236 // A Deserializer reads a snapshot and reconstructs the Object graph it defines.
237 class Deserializer: public SerializerDeserializer {
238  public:
239   // Create a deserializer from a snapshot byte source.
240   explicit Deserializer(SnapshotByteSource* source);
241
242   virtual ~Deserializer();
243
244   // Deserialize the snapshot into an empty heap.
245   void Deserialize(Isolate* isolate);
246
247   // Deserialize a single object and the objects reachable from it.
248   void DeserializePartial(Isolate* isolate, Object** root);
249
250   void set_reservation(int space_number, int reservation) {
251     DCHECK(space_number >= 0);
252     DCHECK(space_number <= LAST_SPACE);
253     reservations_[space_number] = reservation;
254   }
255
256   void FlushICacheForNewCodeObjects();
257
258   // Serialized user code reference certain objects that are provided in a list
259   // By calling this method, we assume that we are deserializing user code.
260   void SetAttachedObjects(Vector<Handle<Object> >* attached_objects) {
261     attached_objects_ = attached_objects;
262   }
263
264   bool deserializing_user_code() { return attached_objects_ != NULL; }
265
266  private:
267   virtual void VisitPointers(Object** start, Object** end);
268
269   virtual void VisitRuntimeEntry(RelocInfo* rinfo) {
270     UNREACHABLE();
271   }
272
273   // Allocation sites are present in the snapshot, and must be linked into
274   // a list at deserialization time.
275   void RelinkAllocationSite(AllocationSite* site);
276
277   // Fills in some heap data in an area from start to end (non-inclusive).  The
278   // space id is used for the write barrier.  The object_address is the address
279   // of the object we are writing into, or NULL if we are not writing into an
280   // object, i.e. if we are writing a series of tagged values that are not on
281   // the heap.
282   void ReadChunk(
283       Object** start, Object** end, int space, Address object_address);
284   void ReadObject(int space_number, Object** write_back);
285
286   // Special handling for serialized code like hooking up internalized strings.
287   HeapObject* ProcessNewObjectFromSerializedCode(HeapObject* obj);
288   Object* ProcessBackRefInSerializedCode(Object* obj);
289
290   // This routine both allocates a new object, and also keeps
291   // track of where objects have been allocated so that we can
292   // fix back references when deserializing.
293   Address Allocate(int space_index, int size) {
294     Address address = high_water_[space_index];
295     high_water_[space_index] = address + size;
296     return address;
297   }
298
299   // This returns the address of an object that has been described in the
300   // snapshot as being offset bytes back in a particular space.
301   HeapObject* GetAddressFromEnd(int space) {
302     int offset = source_->GetInt();
303     offset <<= kObjectAlignmentBits;
304     return HeapObject::FromAddress(high_water_[space] - offset);
305   }
306
307   // Cached current isolate.
308   Isolate* isolate_;
309
310   // Objects from the attached object descriptions in the serialized user code.
311   Vector<Handle<Object> >* attached_objects_;
312
313   SnapshotByteSource* source_;
314   // This is the address of the next object that will be allocated in each
315   // space.  It is used to calculate the addresses of back-references.
316   Address high_water_[LAST_SPACE + 1];
317
318   int reservations_[LAST_SPACE + 1];
319   static const intptr_t kUninitializedReservation = -1;
320
321   ExternalReferenceDecoder* external_reference_decoder_;
322
323   DISALLOW_COPY_AND_ASSIGN(Deserializer);
324 };
325
326
327 // Mapping objects to their location after deserialization.
328 // This is used during building, but not at runtime by V8.
329 class SerializationAddressMapper {
330  public:
331   SerializationAddressMapper()
332       : no_allocation_(),
333         serialization_map_(new HashMap(HashMap::PointersMatch)) { }
334
335   ~SerializationAddressMapper() {
336     delete serialization_map_;
337   }
338
339   bool IsMapped(HeapObject* obj) {
340     return serialization_map_->Lookup(Key(obj), Hash(obj), false) != NULL;
341   }
342
343   int MappedTo(HeapObject* obj) {
344     DCHECK(IsMapped(obj));
345     return static_cast<int>(reinterpret_cast<intptr_t>(
346         serialization_map_->Lookup(Key(obj), Hash(obj), false)->value));
347   }
348
349   void AddMapping(HeapObject* obj, int to) {
350     DCHECK(!IsMapped(obj));
351     HashMap::Entry* entry =
352         serialization_map_->Lookup(Key(obj), Hash(obj), true);
353     entry->value = Value(to);
354   }
355
356  private:
357   static uint32_t Hash(HeapObject* obj) {
358     return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
359   }
360
361   static void* Key(HeapObject* obj) {
362     return reinterpret_cast<void*>(obj->address());
363   }
364
365   static void* Value(int v) {
366     return reinterpret_cast<void*>(v);
367   }
368
369   DisallowHeapAllocation no_allocation_;
370   HashMap* serialization_map_;
371   DISALLOW_COPY_AND_ASSIGN(SerializationAddressMapper);
372 };
373
374
375 class CodeAddressMap;
376
377 // There can be only one serializer per V8 process.
378 class Serializer : public SerializerDeserializer {
379  public:
380   Serializer(Isolate* isolate, SnapshotByteSink* sink);
381   ~Serializer();
382   void VisitPointers(Object** start, Object** end);
383   // You can call this after serialization to find out how much space was used
384   // in each space.
385   int CurrentAllocationAddress(int space) const {
386     DCHECK(space < kNumberOfSpaces);
387     return fullness_[space];
388   }
389
390   Isolate* isolate() const { return isolate_; }
391
392   SerializationAddressMapper* address_mapper() { return &address_mapper_; }
393   void PutRoot(int index,
394                HeapObject* object,
395                HowToCode how,
396                WhereToPoint where,
397                int skip);
398
399  protected:
400   static const int kInvalidRootIndex = -1;
401
402   int RootIndex(HeapObject* heap_object, HowToCode from);
403   intptr_t root_index_wave_front() { return root_index_wave_front_; }
404   void set_root_index_wave_front(intptr_t value) {
405     DCHECK(value >= root_index_wave_front_);
406     root_index_wave_front_ = value;
407   }
408
409   class ObjectSerializer : public ObjectVisitor {
410    public:
411     ObjectSerializer(Serializer* serializer,
412                      Object* o,
413                      SnapshotByteSink* sink,
414                      HowToCode how_to_code,
415                      WhereToPoint where_to_point)
416       : serializer_(serializer),
417         object_(HeapObject::cast(o)),
418         sink_(sink),
419         reference_representation_(how_to_code + where_to_point),
420         bytes_processed_so_far_(0),
421         code_object_(o->IsCode()),
422         code_has_been_output_(false) { }
423     void Serialize();
424     void VisitPointers(Object** start, Object** end);
425     void VisitEmbeddedPointer(RelocInfo* target);
426     void VisitExternalReference(Address* p);
427     void VisitExternalReference(RelocInfo* rinfo);
428     void VisitCodeTarget(RelocInfo* target);
429     void VisitCodeEntry(Address entry_address);
430     void VisitCell(RelocInfo* rinfo);
431     void VisitRuntimeEntry(RelocInfo* reloc);
432     // Used for seralizing the external strings that hold the natives source.
433     void VisitExternalOneByteString(
434         v8::String::ExternalOneByteStringResource** resource);
435     // We can't serialize a heap with external two byte strings.
436     void VisitExternalTwoByteString(
437         v8::String::ExternalStringResource** resource) {
438       UNREACHABLE();
439     }
440
441    private:
442     enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn };
443     // This function outputs or skips the raw data between the last pointer and
444     // up to the current position.  It optionally can just return the number of
445     // bytes to skip instead of performing a skip instruction, in case the skip
446     // can be merged into the next instruction.
447     int OutputRawData(Address up_to, ReturnSkip return_skip = kIgnoringReturn);
448
449     Serializer* serializer_;
450     HeapObject* object_;
451     SnapshotByteSink* sink_;
452     int reference_representation_;
453     int bytes_processed_so_far_;
454     bool code_object_;
455     bool code_has_been_output_;
456   };
457
458   virtual void SerializeObject(Object* o,
459                                HowToCode how_to_code,
460                                WhereToPoint where_to_point,
461                                int skip) = 0;
462   void SerializeReferenceToPreviousObject(HeapObject* heap_object,
463                                           HowToCode how_to_code,
464                                           WhereToPoint where_to_point,
465                                           int skip);
466   void InitializeAllocators();
467   // This will return the space for an object.
468   static int SpaceOfObject(HeapObject* object);
469   int Allocate(int space, int size);
470   int EncodeExternalReference(Address addr) {
471     return external_reference_encoder_->Encode(addr);
472   }
473
474   int SpaceAreaSize(int space);
475
476   // Some roots should not be serialized, because their actual value depends on
477   // absolute addresses and they are reset after deserialization, anyway.
478   bool ShouldBeSkipped(Object** current);
479
480   Isolate* isolate_;
481   // Keep track of the fullness of each space in order to generate
482   // relative addresses for back references.
483   int fullness_[LAST_SPACE + 1];
484   SnapshotByteSink* sink_;
485   ExternalReferenceEncoder* external_reference_encoder_;
486
487   SerializationAddressMapper address_mapper_;
488   intptr_t root_index_wave_front_;
489   void Pad();
490
491   friend class ObjectSerializer;
492   friend class Deserializer;
493
494   // We may not need the code address map for logging for every instance
495   // of the serializer.  Initialize it on demand.
496   void InitializeCodeAddressMap();
497
498  private:
499   CodeAddressMap* code_address_map_;
500   DISALLOW_COPY_AND_ASSIGN(Serializer);
501 };
502
503
504 class PartialSerializer : public Serializer {
505  public:
506   PartialSerializer(Isolate* isolate,
507                     Serializer* startup_snapshot_serializer,
508                     SnapshotByteSink* sink)
509     : Serializer(isolate, sink),
510       startup_serializer_(startup_snapshot_serializer) {
511     set_root_index_wave_front(Heap::kStrongRootListLength);
512     InitializeCodeAddressMap();
513   }
514
515   // Serialize the objects reachable from a single object pointer.
516   void Serialize(Object** o);
517   virtual void SerializeObject(Object* o,
518                                HowToCode how_to_code,
519                                WhereToPoint where_to_point,
520                                int skip);
521
522  private:
523   int PartialSnapshotCacheIndex(HeapObject* o);
524   bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
525     // Scripts should be referred only through shared function infos.  We can't
526     // allow them to be part of the partial snapshot because they contain a
527     // unique ID, and deserializing several partial snapshots containing script
528     // would cause dupes.
529     DCHECK(!o->IsScript());
530     return o->IsName() || o->IsSharedFunctionInfo() ||
531            o->IsHeapNumber() || o->IsCode() ||
532            o->IsScopeInfo() ||
533            o->map() ==
534                startup_serializer_->isolate()->heap()->fixed_cow_array_map();
535   }
536
537
538   Serializer* startup_serializer_;
539   DISALLOW_COPY_AND_ASSIGN(PartialSerializer);
540 };
541
542
543 class StartupSerializer : public Serializer {
544  public:
545   StartupSerializer(Isolate* isolate, SnapshotByteSink* sink)
546     : Serializer(isolate, sink) {
547     // Clear the cache of objects used by the partial snapshot.  After the
548     // strong roots have been serialized we can create a partial snapshot
549     // which will repopulate the cache with objects needed by that partial
550     // snapshot.
551     isolate->set_serialize_partial_snapshot_cache_length(0);
552     InitializeCodeAddressMap();
553   }
554   // Serialize the current state of the heap.  The order is:
555   // 1) Strong references.
556   // 2) Partial snapshot cache.
557   // 3) Weak references (e.g. the string table).
558   virtual void SerializeStrongReferences();
559   virtual void SerializeObject(Object* o,
560                                HowToCode how_to_code,
561                                WhereToPoint where_to_point,
562                                int skip);
563   void SerializeWeakReferences();
564   void Serialize() {
565     SerializeStrongReferences();
566     SerializeWeakReferences();
567     Pad();
568   }
569
570  private:
571   DISALLOW_COPY_AND_ASSIGN(StartupSerializer);
572 };
573
574
575 class CodeSerializer : public Serializer {
576  public:
577   CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source)
578       : Serializer(isolate, sink), source_(source) {
579     set_root_index_wave_front(Heap::kStrongRootListLength);
580     InitializeCodeAddressMap();
581   }
582
583   static ScriptData* Serialize(Isolate* isolate,
584                                Handle<SharedFunctionInfo> info,
585                                Handle<String> source);
586
587   virtual void SerializeObject(Object* o, HowToCode how_to_code,
588                                WhereToPoint where_to_point, int skip);
589
590   static Handle<SharedFunctionInfo> Deserialize(Isolate* isolate,
591                                                 ScriptData* data,
592                                                 Handle<String> source);
593
594   static const int kSourceObjectIndex = 0;
595   static const int kCodeStubsBaseIndex = 1;
596
597   String* source() {
598     DCHECK(!AllowHeapAllocation::IsAllowed());
599     return source_;
600   }
601
602   List<uint32_t>* stub_keys() { return &stub_keys_; }
603
604  private:
605   void SerializeBuiltin(Code* builtin, HowToCode how_to_code,
606                         WhereToPoint where_to_point, int skip);
607   void SerializeCodeStub(Code* code, HowToCode how_to_code,
608                          WhereToPoint where_to_point, int skip);
609   void SerializeSourceObject(HowToCode how_to_code, WhereToPoint where_to_point,
610                              int skip);
611   void SerializeHeapObject(HeapObject* heap_object, HowToCode how_to_code,
612                            WhereToPoint where_to_point, int skip);
613   int AddCodeStubKey(uint32_t stub_key);
614
615   DisallowHeapAllocation no_gc_;
616   String* source_;
617   List<uint32_t> stub_keys_;
618   DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
619 };
620
621
622 // Wrapper around ScriptData to provide code-serializer-specific functionality.
623 class SerializedCodeData {
624  public:
625   // Used by when consuming.
626   explicit SerializedCodeData(ScriptData* data, String* source)
627       : script_data_(data), owns_script_data_(false) {
628     DisallowHeapAllocation no_gc;
629     CHECK(IsSane(source));
630   }
631
632   // Used when producing.
633   SerializedCodeData(List<byte>* payload, CodeSerializer* cs);
634
635   ~SerializedCodeData() {
636     if (owns_script_data_) delete script_data_;
637   }
638
639   // Return ScriptData object and relinquish ownership over it to the caller.
640   ScriptData* GetScriptData() {
641     ScriptData* result = script_data_;
642     script_data_ = NULL;
643     DCHECK(owns_script_data_);
644     owns_script_data_ = false;
645     return result;
646   }
647
648   Vector<const uint32_t> CodeStubKeys() const {
649     return Vector<const uint32_t>(
650         reinterpret_cast<const uint32_t*>(script_data_->data() + kHeaderSize),
651         GetHeaderValue(kNumCodeStubKeysOffset));
652   }
653
654   const byte* Payload() const {
655     int code_stubs_size = GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size;
656     return script_data_->data() + kHeaderSize + code_stubs_size;
657   }
658
659   int PayloadLength() const {
660     int payload_length = GetHeaderValue(kPayloadLengthOffset);
661     DCHECK_EQ(script_data_->data() + script_data_->length(),
662               Payload() + payload_length);
663     return payload_length;
664   }
665
666   int GetReservation(int space) const {
667     return GetHeaderValue(kReservationsOffset + space);
668   }
669
670  private:
671   void SetHeaderValue(int offset, int value) {
672     reinterpret_cast<int*>(const_cast<byte*>(script_data_->data()))[offset] =
673         value;
674   }
675
676   int GetHeaderValue(int offset) const {
677     return reinterpret_cast<const int*>(script_data_->data())[offset];
678   }
679
680   bool IsSane(String* source);
681
682   int CheckSum(String* source);
683
684   // The data header consists of int-sized entries:
685   // [0] version hash
686   // [1] number of code stub keys
687   // [2] payload length
688   // [3..9] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
689   static const int kCheckSumOffset = 0;
690   static const int kNumCodeStubKeysOffset = 1;
691   static const int kPayloadLengthOffset = 2;
692   static const int kReservationsOffset = 3;
693
694   static const int kNumSpaces = PROPERTY_CELL_SPACE - NEW_SPACE + 1;
695   static const int kHeaderEntries = kReservationsOffset + kNumSpaces;
696   static const int kHeaderSize = kHeaderEntries * kIntSize;
697
698   // Following the header, we store, in sequential order
699   // - code stub keys
700   // - serialization payload
701
702   ScriptData* script_data_;
703   bool owns_script_data_;
704 };
705 } }  // namespace v8::internal
706
707 #endif  // V8_SERIALIZE_H_