13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_SERIALIZE_H_ 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_SERIALIZE_H_ 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "hashmap.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A TypeCode is used to distinguish different kinds of external reference. 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// It is a single bit to make testing for types easy. 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum TypeCode { 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNCLASSIFIED, // One-of-a-kind references. 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BUILTIN, 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RUNTIME_FUNCTION, 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IC_UTILITY, 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DEBUG_ADDRESS, 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block STATS_COUNTER, 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TOP_ADDRESS, 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block C_BUILTIN, 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EXTENSION, 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ACCESSOR, 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RUNTIME_ENTRY, 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block STUB_CACHE_TABLE 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kTypeCodeCount = STUB_CACHE_TABLE + 1; 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kFirstTypeCode = UNCLASSIFIED; 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kReferenceIdBits = 16; 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kReferenceIdMask = (1 << kReferenceIdBits) - 1; 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kReferenceTypeShift = kReferenceIdBits; 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kDebugRegisterBits = 4; 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int kDebugIdShift = kDebugRegisterBits; 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// ExternalReferenceTable is a helper class that defines the relationship 6469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// between external references and their encodings. It is used to build 6569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder. 6669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalReferenceTable { 6769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch public: 6869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch static ExternalReferenceTable* instance(Isolate* isolate); 6969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 7069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ~ExternalReferenceTable() { } 7169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 7269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int size() const { return refs_.length(); } 7369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 7469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Address address(int i) { return refs_[i].address; } 7569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 7669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch uint32_t code(int i) { return refs_[i].code; } 7769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 7869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch const char* name(int i) { return refs_[i].name; } 7969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 8069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int max_id(int code) { return max_id_[code]; } 8169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 8269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch private: 8369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch explicit ExternalReferenceTable(Isolate* isolate) : refs_(64) { 8469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch PopulateTable(isolate); 8569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 8669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 8769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch struct ExternalReferenceEntry { 8869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Address address; 8969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch uint32_t code; 9069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch const char* name; 9169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch }; 9269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 9369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void PopulateTable(Isolate* isolate); 9469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 9569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // For a few types of references, we can get their address from their id. 9669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void AddFromId(TypeCode type, 9769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch uint16_t id, 9869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch const char* name, 9969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Isolate* isolate); 10069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 10169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // For other types of references, the caller will figure out the address. 10269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch void Add(Address address, TypeCode type, uint16_t id, const char* name); 10369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 10469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch List<ExternalReferenceEntry> refs_; 10569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int max_id_[kTypeCodeCount]; 10669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}; 10769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 10869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ExternalReferenceEncoder { 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReferenceEncoder(); 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t Encode(Address key) const; 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* NameOfAddress(Address key) const; 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HashMap encodings_; 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static uint32_t Hash(Address key) { 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >> 2); 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int IndexOf(Address key) const; 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static bool Match(void* key1, void* key2) { return key1 == key2; } 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Put(Address key, int index); 12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate_; 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ExternalReferenceDecoder { 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReferenceDecoder(); 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~ExternalReferenceDecoder(); 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address Decode(uint32_t key) const { 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (key == 0) return NULL; 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return *Lookup(key); 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address** encodings_; 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address* Lookup(uint32_t key) const { 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int type = key >> kReferenceTypeShift; 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(kFirstTypeCode <= type && type < kTypeCodeCount); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int id = key & kReferenceIdMask; 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return &encodings_[type][id]; 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Put(uint32_t key, Address value) { 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *Lookup(key) = value; 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 15744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate_; 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockclass SnapshotByteSource { 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SnapshotByteSource(const byte* array, int length) 164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block : data_(array), length_(length), position_(0) { } 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool HasMore() { return position_ < length_; } 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int Get() { 169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(position_ < length_); 170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return data_[position_++]; 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1733100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline void CopyRaw(byte* to, int number_of_bytes); 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1753100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu inline int GetInt(); 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool AtEOF() { 178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return position_ == length_; 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 181d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int position() { return position_; } 182e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const byte* data_; 185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int length_; 186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int position_; 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#define COMMON_RAW_LENGTHS(f) \ 191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(1, 1) \ 192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(2, 2) \ 193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(3, 3) \ 194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(4, 4) \ 195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(5, 5) \ 196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(6, 6) \ 197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(7, 7) \ 198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(8, 8) \ 199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(9, 12) \ 200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(10, 16) \ 201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(11, 20) \ 202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(12, 24) \ 203d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(13, 28) \ 204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(14, 32) \ 205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block f(15, 36) 206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 207d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// The Serializer/Deserializer class is a common superclass for Serializer and 208d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Deserializer which is used to store common constants and methods used by 209d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// both. 210d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass SerializerDeserializer: public ObjectVisitor { 211d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public: 212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static void Iterate(ObjectVisitor* visitor); 213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static void SetSnapshotCacheSize(int size); 214d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block protected: 216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Where the pointed-to object can be found: 217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke enum Where { 218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke kNewObject = 0, // Object is next in snapshot. 219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 1-8 One per space. 220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke kRootArray = 0x9, // Object is found in root array. 221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke kPartialSnapshotCache = 0xa, // Object is in the cache. 222f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke kExternalReference = 0xb, // Pointer to an external reference. 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kSkip = 0xc, // Skip a pointer sized cell. 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 0xd-0xf Free. 225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke kBackref = 0x10, // Object is described relative to end. 226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0x11-0x18 One per space. 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 0x19-0x1f Free. 228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke kFromStart = 0x20, // Object is described relative to start. 229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0x21-0x28 One per space. 230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // 0x29-0x2f Free. 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 0x30-0x3f Used by misc. tags below. 232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke kPointedToMask = 0x3f 233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block }; 234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // How to code the pointer to the object. 236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke enum HowToCode { 237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke kPlain = 0, // Straight pointer. 238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // What this means depends on the architecture: 239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke kFromCode = 0x40, // A pointer inlined in code. 240f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke kHowToCodeMask = 0x40 241f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke }; 242f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Where to point within the object. 244f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke enum WhereToPoint { 245f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke kStartOfObject = 0, 246f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke kFirstInstruction = 0x80, 247f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke kWhereToPointMask = 0x80 248f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke }; 249f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Misc. 251f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Raw data to be copied from the snapshot. 252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kRawData = 0x30; 253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Some common raw lengths: 0x31-0x3f 254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // A tag emitted at strategic points in the snapshot to delineate sections. 255f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the deserializer does not find these at the expected moments then it 256f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // is an indication that the snapshot and the VM do not fit together. 257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Examine the build process for architecture, version or configuration 258f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // mismatches. 259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kSynchronize = 0x70; 260f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Used for the source code of the natives, which is in the executable, but 261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // is referred to from external strings in the snapshot. 262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kNativesStringResource = 0x71; 263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kNewPage = 0x72; 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kRepeat = 0x73; 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kConstantRepeat = 0x74; 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 0x74-0x7f Repeat last word (subtract 0x73 to get the count). 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kMaxRepeats = 0x7f - 0x73; 2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static int CodeForRepeats(int repeats) { 2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(repeats >= 1 && repeats <= kMaxRepeats); 2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return 0x73 + repeats; 2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static int RepeatsForCode(int byte_code) { 2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(byte_code >= kConstantRepeat && byte_code <= 0x7f); 2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return byte_code - 0x73; 2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kRootArrayLowConstants = 0xb0; 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 0xb0-0xbf Things from the first 16 elements of the root array. 2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kRootArrayHighConstants = 0xf0; 2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 0xf0-0xff Things from the next 16 elements of the root array. 2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kRootArrayNumberOfConstantEncodings = 0x20; 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kRootArrayNumberOfLowConstantEncodings = 0x10; 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static int RootArrayConstantFromByteCode(int byte_code) { 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int constant = (byte_code & 0xf) | ((byte_code & 0x40) >> 2); 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(constant >= 0 && constant < kRootArrayNumberOfConstantEncodings); 2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return constant; 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kLargeData = LAST_SPACE; 290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kLargeCode = kLargeData + 1; 291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kLargeFixedArray = kLargeCode + 1; 292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kNumberOfSpaces = kLargeFixedArray + 1; 293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kAnyOldSpace = -1; 294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // A bitmask for getting the space out of an instruction. 296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kSpaceMask = 15; 297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static inline bool SpaceIsLarge(int space) { return space >= kLargeData; } 299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static inline bool SpaceIsPaged(int space) { 300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE; 301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuint SnapshotByteSource::GetInt() { 3063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // A little unwind to catch the really small ints. 3073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int snapshot_byte = Get(); 3083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((snapshot_byte & 0x80) == 0) { 3093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return snapshot_byte; 3103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 3113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int accumulator = (snapshot_byte & 0x7f) << 7; 3123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu while (true) { 3133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu snapshot_byte = Get(); 3143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu if ((snapshot_byte & 0x80) == 0) { 3153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return accumulator | snapshot_byte; 3163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 3173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu accumulator = (accumulator | (snapshot_byte & 0x7f)) << 7; 3183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu } 3193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu UNREACHABLE(); 3203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu return accumulator; 3213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 3223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid SnapshotByteSource::CopyRaw(byte* to, int number_of_bytes) { 3253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu memcpy(to, data_ + position_, number_of_bytes); 3263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu position_ += number_of_bytes; 3273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 3283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// A Deserializer reads a snapshot and reconstructs the Object graph it defines. 331d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass Deserializer: public SerializerDeserializer { 332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Create a deserializer from a snapshot byte source. 334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block explicit Deserializer(SnapshotByteSource* source); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual ~Deserializer(); 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Deserialize the snapshot into an empty heap. 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Deserialize(); 340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Deserialize a single object and the objects reachable from it. 342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke void DeserializePartial(Object** root); 343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual void VisitPointers(Object** start, Object** end); 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 347d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual void VisitExternalReferences(Address* start, Address* end) { 348d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 349d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 351d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual void VisitRuntimeEntry(RelocInfo* rinfo) { 352d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 353d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Fills in some heap data in an area from start to end (non-inclusive). The 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // space id is used for the write barrier. The object_address is the address 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of the object we are writing into, or NULL if we are not writing into an 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // object, i.e. if we are writing a series of tagged values that are not on 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the heap. 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void ReadChunk( 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Object** start, Object** end, int space, Address object_address); 362d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block HeapObject* GetAddressFromStart(int space); 363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block inline HeapObject* GetAddressFromEnd(int space); 364d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Address Allocate(int space_number, Space* space, int size); 365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void ReadObject(int space_number, Space* space, Object** write_back); 366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 36744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Cached current isolate. 36844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate_; 36944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 370d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Keep track of the pages in the paged spaces. 371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // (In large object space we are keeping track of individual objects 372d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // rather than pages.) In new space we just need the address of the 373d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // first object and the others will flow from that. 374d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke List<Address> pages_[SerializerDeserializer::kNumberOfSpaces]; 375d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SnapshotByteSource* source_; 377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This is the address of the next object that will be allocated in each 378d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // space. It is used to calculate the addresses of back-references. 379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Address high_water_[LAST_SPACE + 1]; 380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This is the address of the most recent object that was allocated. It 381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // is used to set the location of the new page when we encounter a 382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // START_NEW_PAGE_SERIALIZATION tag. 383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Address last_object_address_; 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 38544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReferenceDecoder* external_reference_decoder_; 38644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block DISALLOW_COPY_AND_ASSIGN(Deserializer); 388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockclass SnapshotByteSink { 392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual ~SnapshotByteSink() { } 394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual void Put(int byte, const char* description) = 0; 395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual void PutSection(int byte, const char* description) { 396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Put(byte, description); 397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void PutInt(uintptr_t integer, const char* description); 399e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke virtual int Position() = 0; 400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 403d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Mapping objects to their location after deserialization. 404d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// This is used during building, but not at runtime by V8. 405d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass SerializationAddressMapper { 406d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public: 407d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke SerializationAddressMapper() 408d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke : serialization_map_(new HashMap(&SerializationMatchFun)), 409d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke no_allocation_(new AssertNoAllocation()) { } 410d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 411d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ~SerializationAddressMapper() { 412d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke delete serialization_map_; 413d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke delete no_allocation_; 414d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 415d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 416d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke bool IsMapped(HeapObject* obj) { 417d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return serialization_map_->Lookup(Key(obj), Hash(obj), false) != NULL; 418d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 419d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 420d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int MappedTo(HeapObject* obj) { 421d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(IsMapped(obj)); 422d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return static_cast<int>(reinterpret_cast<intptr_t>( 423d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke serialization_map_->Lookup(Key(obj), Hash(obj), false)->value)); 424d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 425d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 426d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void AddMapping(HeapObject* obj, int to) { 427d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(!IsMapped(obj)); 428d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke HashMap::Entry* entry = 429d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke serialization_map_->Lookup(Key(obj), Hash(obj), true); 430d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke entry->value = Value(to); 431d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 432d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 433d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private: 434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static bool SerializationMatchFun(void* key1, void* key2) { 435d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return key1 == key2; 436d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 437d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static uint32_t Hash(HeapObject* obj) { 439d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address())); 440d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 441d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static void* Key(HeapObject* obj) { 443d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return reinterpret_cast<void*>(obj->address()); 444d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 445d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static void* Value(int v) { 447d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return reinterpret_cast<void*>(v); 448d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 449d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 450d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke HashMap* serialization_map_; 451d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke AssertNoAllocation* no_allocation_; 452d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke DISALLOW_COPY_AND_ASSIGN(SerializationAddressMapper); 453d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}; 454d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 455d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 45644f0eee88ff00398ff7f715fab053374d808c90dSteve Block// There can be only one serializer per V8 process. 457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass Serializer : public SerializerDeserializer { 458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block explicit Serializer(SnapshotByteSink* sink); 4603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ~Serializer(); 461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void VisitPointers(Object** start, Object** end); 462e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // You can call this after serialization to find out how much space was used 463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // in each space. 464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int CurrentAllocationAddress(int space) { 465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (SpaceIsLarge(space)) return large_object_total_; 466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return fullness_[space]; 467e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static void Enable() { 470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!serialization_enabled_) { 471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(!too_late_to_enable_now_); 472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block serialization_enabled_ = true; 474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static void Disable() { serialization_enabled_ = false; } 477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call this when you have made use of the fact that there is no serialization 478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // going on. 479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static void TooLateToEnableNow() { too_late_to_enable_now_ = true; } 480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static bool enabled() { return serialization_enabled_; } 481d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke SerializationAddressMapper* address_mapper() { return &address_mapper_; } 4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void PutRoot( 4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int index, HeapObject* object, HowToCode how, WhereToPoint where); 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 485d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke protected: 486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kInvalidRootIndex = -1; 4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int RootIndex(HeapObject* heap_object, HowToCode from); 489d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) = 0; 4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t root_index_wave_front() { return root_index_wave_front_; } 4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void set_root_index_wave_front(intptr_t value) { 4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(value >= root_index_wave_front_); 4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch root_index_wave_front_ = value; 4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 495d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block class ObjectSerializer : public ObjectVisitor { 497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ObjectSerializer(Serializer* serializer, 499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Object* o, 500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SnapshotByteSink* sink, 501f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke HowToCode how_to_code, 502f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke WhereToPoint where_to_point) 503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block : serializer_(serializer), 504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block object_(HeapObject::cast(o)), 505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block sink_(sink), 506f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke reference_representation_(how_to_code + where_to_point), 507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bytes_processed_so_far_(0) { } 508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void Serialize(); 509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void VisitPointers(Object** start, Object** end); 5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void VisitEmbeddedPointer(RelocInfo* target); 511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void VisitExternalReferences(Address* start, Address* end); 5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void VisitExternalReference(RelocInfo* rinfo); 513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void VisitCodeTarget(RelocInfo* target); 514791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block void VisitCodeEntry(Address entry_address); 515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void VisitGlobalPropertyCell(RelocInfo* rinfo); 516d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void VisitRuntimeEntry(RelocInfo* reloc); 517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Used for seralizing the external strings that hold the natives source. 518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void VisitExternalAsciiString( 519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block v8::String::ExternalAsciiStringResource** resource); 520d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We can't serialize a heap with external two byte strings. 521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void VisitExternalTwoByteString( 522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block v8::String::ExternalStringResource** resource) { 523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block private: 527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void OutputRawData(Address up_to); 528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Serializer* serializer_; 530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block HeapObject* object_; 531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SnapshotByteSink* sink_; 532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int reference_representation_; 533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int bytes_processed_so_far_; 534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block }; 535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 536d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual void SerializeObject(Object* o, 537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke HowToCode how_to_code, 538f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke WhereToPoint where_to_point) = 0; 539d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void SerializeReferenceToPreviousObject( 540d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int space, 541d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int address, 542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke HowToCode how_to_code, 543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke WhereToPoint where_to_point); 544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void InitializeAllocators(); 545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This will return the space for an object. If the object is in large 546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // object space it may return kLargeCode or kLargeFixedArray in order 547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // to indicate to the deserializer what kind of large object allocation 548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // to make. 549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static int SpaceOfObject(HeapObject* object); 550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This just returns the space of the object. It will return LO_SPACE 551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // for all large objects since you can't check the type of the object 552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // once the map has been used for the serialization address. 553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static int SpaceOfAlreadySerializedObject(HeapObject* object); 554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int Allocate(int space, int size, bool* new_page_started); 555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int EncodeExternalReference(Address addr) { 556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return external_reference_encoder_->Encode(addr); 557d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int SpaceAreaSize(int space); 5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Isolate* isolate_; 562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Keep track of the fullness of each space in order to generate 563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // relative addresses for back references. Large objects are 564d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // just numbered sequentially since relative addresses make no 565d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // sense in large object space. 566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int fullness_[LAST_SPACE + 1]; 567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SnapshotByteSink* sink_; 568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int current_root_index_; 569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReferenceEncoder* external_reference_encoder_; 570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static bool serialization_enabled_; 571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Did we already make use of the fact that serialization was not enabled? 572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static bool too_late_to_enable_now_; 573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke int large_object_total_; 574d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke SerializationAddressMapper address_mapper_; 5753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t root_index_wave_front_; 576d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block friend class ObjectSerializer; 578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block friend class Deserializer; 579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block DISALLOW_COPY_AND_ASSIGN(Serializer); 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 584d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 585d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass PartialSerializer : public Serializer { 586d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public: 587d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke PartialSerializer(Serializer* startup_snapshot_serializer, 588d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke SnapshotByteSink* sink) 589d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke : Serializer(sink), 590d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke startup_serializer_(startup_snapshot_serializer) { 5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_root_index_wave_front(Heap::kStrongRootListLength); 592d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 593d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 594d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Serialize the objects reachable from a single object pointer. 595d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual void Serialize(Object** o); 596d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual void SerializeObject(Object* o, 597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke HowToCode how_to_code, 598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke WhereToPoint where_to_point); 599d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 600d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke protected: 601d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual int PartialSnapshotCacheIndex(HeapObject* o); 602d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) { 6033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // Scripts should be referred only through shared function infos. We can't 6043100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // allow them to be part of the partial snapshot because they contain a 6053100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // unique ID, and deserializing several partial snapshots containing script 6063100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu // would cause dupes. 6073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu ASSERT(!o->IsScript()); 6086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return o->IsString() || o->IsSharedFunctionInfo() || 609756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick o->IsHeapNumber() || o->IsCode() || 6103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch o->IsScopeInfo() || 61144f0eee88ff00398ff7f715fab053374d808c90dSteve Block o->map() == HEAP->fixed_cow_array_map(); 612d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 613d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 614d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private: 615d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Serializer* startup_serializer_; 616d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke DISALLOW_COPY_AND_ASSIGN(PartialSerializer); 617d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}; 618d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 619d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 620d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass StartupSerializer : public Serializer { 621d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public: 622d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke explicit StartupSerializer(SnapshotByteSink* sink) : Serializer(sink) { 623d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Clear the cache of objects used by the partial snapshot. After the 624d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // strong roots have been serialized we can create a partial snapshot 6253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // which will repopulate the cache with objects needed by that partial 626d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // snapshot. 62744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate::Current()->set_serialize_partial_snapshot_cache_length(0); 628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 629d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Serialize the current state of the heap. The order is: 630d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // 1) Strong references. 631d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // 2) Partial snapshot cache. 6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 3) Weak references (e.g. the symbol table). 633d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual void SerializeStrongReferences(); 634d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual void SerializeObject(Object* o, 635f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke HowToCode how_to_code, 636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke WhereToPoint where_to_point); 637d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void SerializeWeakReferences(); 638d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void Serialize() { 639d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke SerializeStrongReferences(); 640d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke SerializeWeakReferences(); 641d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 642d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 643d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private: 644d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) { 645d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return false; 646d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 647d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}; 648d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 6493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_SERIALIZE_H_ 653