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 
~ExternalReferenceTable()49   ~ExternalReferenceTable() { }
50 
size()51   int size() const { return refs_.length(); }
52 
address(int i)53   Address address(int i) { return refs_[i].address; }
54 
code(int i)55   uint32_t code(int i) { return refs_[i].code; }
56 
name(int i)57   const char* name(int i) { return refs_[i].name; }
58 
max_id(int code)59   int max_id(int code) { return max_id_[code]; }
60 
61  private:
ExternalReferenceTable(Isolate * isolate)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 
Add(Address address,const char * name)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_;
Hash(Address key)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 
Decode(uint32_t key)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 
Lookup(uint32_t key)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 
Put(uint32_t key,Address value)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 
nop()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;
CodeForRepeats(int repeats)213   static int CodeForRepeats(int repeats) {
214     DCHECK(repeats >= 1 && repeats <= kMaxRepeats);
215     return 0x72 + repeats;
216   }
RepeatsForCode(int byte_code)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;
RootArrayConstantFromByteCode(int byte_code)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 
set_reservation(int space_number,int reservation)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.
SetAttachedObjects(Vector<Handle<Object>> * attached_objects)260   void SetAttachedObjects(Vector<Handle<Object> >* attached_objects) {
261     attached_objects_ = attached_objects;
262   }
263 
deserializing_user_code()264   bool deserializing_user_code() { return attached_objects_ != NULL; }
265 
266  private:
267   virtual void VisitPointers(Object** start, Object** end);
268 
VisitRuntimeEntry(RelocInfo * rinfo)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.
Allocate(int space_index,int size)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.
GetAddressFromEnd(int 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:
SerializationAddressMapper()331   SerializationAddressMapper()
332       : no_allocation_(),
333         serialization_map_(new HashMap(HashMap::PointersMatch)) { }
334 
~SerializationAddressMapper()335   ~SerializationAddressMapper() {
336     delete serialization_map_;
337   }
338 
IsMapped(HeapObject * obj)339   bool IsMapped(HeapObject* obj) {
340     return serialization_map_->Lookup(Key(obj), Hash(obj), false) != NULL;
341   }
342 
MappedTo(HeapObject * obj)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 
AddMapping(HeapObject * obj,int to)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:
Hash(HeapObject * obj)357   static uint32_t Hash(HeapObject* obj) {
358     return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
359   }
360 
Key(HeapObject * obj)361   static void* Key(HeapObject* obj) {
362     return reinterpret_cast<void*>(obj->address());
363   }
364 
Value(int v)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.
CurrentAllocationAddress(int space)385   int CurrentAllocationAddress(int space) const {
386     DCHECK(space < kNumberOfSpaces);
387     return fullness_[space];
388   }
389 
isolate()390   Isolate* isolate() const { return isolate_; }
391 
address_mapper()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);
root_index_wave_front()403   intptr_t root_index_wave_front() { return root_index_wave_front_; }
set_root_index_wave_front(intptr_t value)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:
ObjectSerializer(Serializer * serializer,Object * o,SnapshotByteSink * sink,HowToCode how_to_code,WhereToPoint where_to_point)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.
VisitExternalTwoByteString(v8::String::ExternalStringResource ** resource)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);
EncodeExternalReference(Address addr)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:
PartialSerializer(Isolate * isolate,Serializer * startup_snapshot_serializer,SnapshotByteSink * sink)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);
ShouldBeInThePartialSnapshotCache(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:
StartupSerializer(Isolate * isolate,SnapshotByteSink * sink)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();
Serialize()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:
CodeSerializer(Isolate * isolate,SnapshotByteSink * sink,String * source)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 
source()597   String* source() {
598     DCHECK(!AllowHeapAllocation::IsAllowed());
599     return source_;
600   }
601 
stub_keys()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.
SerializedCodeData(ScriptData * data,String * source)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 
~SerializedCodeData()635   ~SerializedCodeData() {
636     if (owns_script_data_) delete script_data_;
637   }
638 
639   // Return ScriptData object and relinquish ownership over it to the caller.
GetScriptData()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 
CodeStubKeys()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 
Payload()654   const byte* Payload() const {
655     int code_stubs_size = GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size;
656     return script_data_->data() + kHeaderSize + code_stubs_size;
657   }
658 
PayloadLength()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 
GetReservation(int space)666   int GetReservation(int space) const {
667     return GetHeaderValue(kReservationsOffset + space);
668   }
669 
670  private:
SetHeaderValue(int offset,int value)671   void SetHeaderValue(int offset, int value) {
672     reinterpret_cast<int*>(const_cast<byte*>(script_data_->data()))[offset] =
673         value;
674   }
675 
GetHeaderValue(int offset)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_
708