Home | History | Annotate | Download | only in src
      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_
    708