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