105ed9ddc6ff3a1ab3983c50d378cddfa257869b6jkummerow@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#ifndef V8_SERIALIZE_H_
643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#define V8_SERIALIZE_H_
743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org#include "src/compiler.h"
9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/hashmap.h"
10975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org#include "src/heap-profiler.h"
11975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org#include "src/isolate.h"
12975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org#include "src/snapshot-source-sink.h"
1343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
1571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal {
1643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// A TypeCode is used to distinguish different kinds of external reference.
1843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// It is a single bit to make testing for types easy.
1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenenum TypeCode {
209d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  UNCLASSIFIED,  // One-of-a-kind references.
219d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  C_BUILTIN,
2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  BUILTIN,
2343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  RUNTIME_FUNCTION,
2443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  IC_UTILITY,
2543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  STATS_COUNTER,
2643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  TOP_ADDRESS,
2743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ACCESSOR,
28a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  STUB_CACHE_TABLE,
299d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  RUNTIME_ENTRY,
30a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  LAZY_DEOPTIMIZATION
3143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
3243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
33a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgconst int kTypeCodeCount = LAZY_DEOPTIMIZATION + 1;
3443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenconst int kFirstTypeCode = UNCLASSIFIED;
3543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenconst int kReferenceIdBits = 16;
3743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenconst int kReferenceIdMask = (1 << kReferenceIdBits) - 1;
3843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenconst int kReferenceTypeShift = kReferenceIdBits;
3943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
401845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgconst int kDeoptTableSerializeEntryCount = 64;
4143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
42b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// ExternalReferenceTable is a helper class that defines the relationship
43b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// between external references and their encodings. It is used to build
44b645116853c677aca8a316381b87441ba6004f67danno@chromium.org// hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder.
45b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgclass ExternalReferenceTable {
46b645116853c677aca8a316381b87441ba6004f67danno@chromium.org public:
47b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  static ExternalReferenceTable* instance(Isolate* isolate);
48b645116853c677aca8a316381b87441ba6004f67danno@chromium.org
49b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  ~ExternalReferenceTable() { }
50b645116853c677aca8a316381b87441ba6004f67danno@chromium.org
51b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  int size() const { return refs_.length(); }
52b645116853c677aca8a316381b87441ba6004f67danno@chromium.org
53b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  Address address(int i) { return refs_[i].address; }
54b645116853c677aca8a316381b87441ba6004f67danno@chromium.org
55b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  uint32_t code(int i) { return refs_[i].code; }
56b645116853c677aca8a316381b87441ba6004f67danno@chromium.org
57b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  const char* name(int i) { return refs_[i].name; }
58b645116853c677aca8a316381b87441ba6004f67danno@chromium.org
59b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  int max_id(int code) { return max_id_[code]; }
60b645116853c677aca8a316381b87441ba6004f67danno@chromium.org
61b645116853c677aca8a316381b87441ba6004f67danno@chromium.org private:
62b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  explicit ExternalReferenceTable(Isolate* isolate) : refs_(64) {
63fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org    PopulateTable(isolate);
64b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  }
65b645116853c677aca8a316381b87441ba6004f67danno@chromium.org
66b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  struct ExternalReferenceEntry {
67b645116853c677aca8a316381b87441ba6004f67danno@chromium.org    Address address;
68b645116853c677aca8a316381b87441ba6004f67danno@chromium.org    uint32_t code;
69b645116853c677aca8a316381b87441ba6004f67danno@chromium.org    const char* name;
70b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  };
71b645116853c677aca8a316381b87441ba6004f67danno@chromium.org
72b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  void PopulateTable(Isolate* isolate);
73b645116853c677aca8a316381b87441ba6004f67danno@chromium.org
74b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // For a few types of references, we can get their address from their id.
75b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  void AddFromId(TypeCode type,
76b645116853c677aca8a316381b87441ba6004f67danno@chromium.org                 uint16_t id,
77b645116853c677aca8a316381b87441ba6004f67danno@chromium.org                 const char* name,
78b645116853c677aca8a316381b87441ba6004f67danno@chromium.org                 Isolate* isolate);
79b645116853c677aca8a316381b87441ba6004f67danno@chromium.org
80b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // For other types of references, the caller will figure out the address.
81b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  void Add(Address address, TypeCode type, uint16_t id, const char* name);
82b645116853c677aca8a316381b87441ba6004f67danno@chromium.org
839d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  void Add(Address address, const char* name) {
849d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org    Add(address, UNCLASSIFIED, ++max_id_[UNCLASSIFIED], name);
859d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  }
869d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org
87b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  List<ExternalReferenceEntry> refs_;
889d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  uint16_t max_id_[kTypeCodeCount];
89b645116853c677aca8a316381b87441ba6004f67danno@chromium.org};
90b645116853c677aca8a316381b87441ba6004f67danno@chromium.org
91b645116853c677aca8a316381b87441ba6004f67danno@chromium.org
9243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenclass ExternalReferenceEncoder {
9343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen public:
943d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org  explicit ExternalReferenceEncoder(Isolate* isolate);
9543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
9643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  uint32_t Encode(Address key) const;
9743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
9843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  const char* NameOfAddress(Address key) const;
9943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
10043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen private:
10143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  HashMap encodings_;
10243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static uint32_t Hash(Address key) {
1039085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >> 2);
10443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
10543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
10643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int IndexOf(Address key) const;
10743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
10843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  void Put(Address key, int index);
109ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
110ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Isolate* isolate_;
11143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
11243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
11343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
11443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenclass ExternalReferenceDecoder {
11543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen public:
1163d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org  explicit ExternalReferenceDecoder(Isolate* isolate);
11743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ~ExternalReferenceDecoder();
11843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
11943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Address Decode(uint32_t key) const {
12043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (key == 0) return NULL;
12143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return *Lookup(key);
12243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
12343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
12443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen private:
12543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Address** encodings_;
12643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
12743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Address* Lookup(uint32_t key) const {
12843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    int type = key >> kReferenceTypeShift;
129e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(kFirstTypeCode <= type && type < kTypeCodeCount);
13043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    int id = key & kReferenceIdMask;
13143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return &encodings_[type][id];
13243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
13343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
13443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  void Put(uint32_t key, Address value) {
13543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    *Lookup(key) = value;
13643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
137ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
138ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Isolate* isolate_;
13943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
14043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
14143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
142b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// The Serializer/Deserializer class is a common superclass for Serializer and
143b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// Deserializer which is used to store common constants and methods used by
144b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// both.
145b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgclass SerializerDeserializer: public ObjectVisitor {
146b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org public:
1473d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org  static void Iterate(Isolate* isolate, ObjectVisitor* visitor);
148b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
14956c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  static int nop() { return kNop; }
15056c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org
1513811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org protected:
1529dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Where the pointed-to object can be found:
1539dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  enum Where {
1549bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    kNewObject = 0,  // Object is next in snapshot.
15556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    // 1-6                             One per space.
1569bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    kRootArray = 0x9,             // Object is found in root array.
1579bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    kPartialSnapshotCache = 0xa,  // Object is in the cache.
1589bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    kExternalReference = 0xb,     // Pointer to an external reference.
1599bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    kSkip = 0xc,                  // Skip n bytes.
1609bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    kBuiltin = 0xd,               // Builtin code object.
161d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org    kAttachedReference = 0xe,     // Object is described in an attached list.
162d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org    kNop = 0xf,                   // Does nothing, used to pad.
163d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org    kBackref = 0x10,              // Object is described relative to end.
16456c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    // 0x11-0x16                       One per space.
1659bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    kBackrefWithSkip = 0x18,  // Object is described relative to end.
16656c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    // 0x19-0x1e                       One per space.
16756c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    // 0x20-0x3f                       Used by misc. tags below.
1689dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    kPointedToMask = 0x3f
1693811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  };
1709dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
1719dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // How to code the pointer to the object.
1729dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  enum HowToCode {
1739dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    kPlain = 0,                          // Straight pointer.
1749dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    // What this means depends on the architecture:
1759dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    kFromCode = 0x40,                    // A pointer inlined in code.
1769dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    kHowToCodeMask = 0x40
1779dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  };
1789dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
17956c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // For kRootArrayConstants
18056c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  enum WithSkip {
18156c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    kNoSkipDistance = 0,
18256c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    kHasSkipDistance = 0x40,
18356c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    kWithSkipMask = 0x40
18456c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  };
18556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org
1869dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Where to point within the object.
1879dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  enum WhereToPoint {
1889dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    kStartOfObject = 0,
189000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org    kInnerPointer = 0x80,  // First insn in code object or payload of cell.
1909dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    kWhereToPointMask = 0x80
1919dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  };
1929dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
1939dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Misc.
19456c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // Raw data to be copied from the snapshot.  This byte code does not advance
19556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // the current pointer, which is used for code objects, where we write the
19656c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // entire code in one memcpy, then fix up stuff with kSkip and other byte
19756c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // codes that overwrite data.
19856c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  static const int kRawData = 0x20;
19956c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // Some common raw lengths: 0x21-0x3f.  These autoadvance the current pointer.
2009dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // A tag emitted at strategic points in the snapshot to delineate sections.
2019dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // If the deserializer does not find these at the expected moments then it
2029dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // is an indication that the snapshot and the VM do not fit together.
2039dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Examine the build process for architecture, version or configuration
2049dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // mismatches.
20540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  static const int kSynchronize = 0x70;
2069dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Used for the source code of the natives, which is in the executable, but
2079dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // is referred to from external strings in the snapshot.
20840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  static const int kNativesStringResource = 0x71;
20956c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  static const int kRepeat = 0x72;
21056c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  static const int kConstantRepeat = 0x73;
21156c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // 0x73-0x7f            Repeat last word (subtract 0x72 to get the count).
21256c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  static const int kMaxRepeats = 0x7f - 0x72;
213394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  static int CodeForRepeats(int repeats) {
214e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(repeats >= 1 && repeats <= kMaxRepeats);
21556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    return 0x72 + repeats;
216394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
217394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  static int RepeatsForCode(int byte_code) {
218e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(byte_code >= kConstantRepeat && byte_code <= 0x7f);
21956c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    return byte_code - 0x72;
220394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
22156c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  static const int kRootArrayConstants = 0xa0;
22256c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // 0xa0-0xbf            Things from the first 32 elements of the root array.
223394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  static const int kRootArrayNumberOfConstantEncodings = 0x20;
224394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  static int RootArrayConstantFromByteCode(int byte_code) {
22556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    return byte_code & 0x1f;
226394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
2279dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
22856c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  static const int kNumberOfSpaces = LO_SPACE;
22940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  static const int kAnyOldSpace = -1;
2303811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
231c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  // A bitmask for getting the space out of an instruction.
23256c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  static const int kSpaceMask = 7;
2333811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org};
2343811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
2353811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
2363811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org// A Deserializer reads a snapshot and reconstructs the Object graph it defines.
237b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgclass Deserializer: public SerializerDeserializer {
2383811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org public:
2393811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Create a deserializer from a snapshot byte source.
240c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  explicit Deserializer(SnapshotByteSource* source);
2413811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
242b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  virtual ~Deserializer();
2433811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
2443811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Deserialize the snapshot into an empty heap.
2453d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org  void Deserialize(Isolate* isolate);
246b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
247b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Deserialize a single object and the objects reachable from it.
2483d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org  void DeserializePartial(Isolate* isolate, Object** root);
249b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
25056c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  void set_reservation(int space_number, int reservation) {
251e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(space_number >= 0);
252e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(space_number <= LAST_SPACE);
25356c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    reservations_[space_number] = reservation;
25456c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  }
25556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org
2565366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org  void FlushICacheForNewCodeObjects();
2575366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org
258d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  // Serialized user code reference certain objects that are provided in a list
259d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  // By calling this method, we assume that we are deserializing user code.
260a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  void SetAttachedObjects(Vector<Handle<Object> >* attached_objects) {
261d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org    attached_objects_ = attached_objects;
262d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  }
263d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org
264d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  bool deserializing_user_code() { return attached_objects_ != NULL; }
265d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org
2663811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org private:
2673811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  virtual void VisitPointers(Object** start, Object** end);
2683811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
2693811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  virtual void VisitRuntimeEntry(RelocInfo* rinfo) {
2703811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    UNREACHABLE();
2713811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
2723811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
273ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // Allocation sites are present in the snapshot, and must be linked into
274ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  // a list at deserialization time.
275ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  void RelinkAllocationSite(AllocationSite* site);
276ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org
277394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Fills in some heap data in an area from start to end (non-inclusive).  The
278394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // space id is used for the write barrier.  The object_address is the address
279394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // of the object we are writing into, or NULL if we are not writing into an
2802efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // object, i.e. if we are writing a series of tagged values that are not on
2812efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // the heap.
282394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  void ReadChunk(
283394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      Object** start, Object** end, int space, Address object_address);
28456c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  void ReadObject(int space_number, Object** write_back);
28556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org
2867c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  // Special handling for serialized code like hooking up internalized strings.
2877c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  HeapObject* ProcessNewObjectFromSerializedCode(HeapObject* obj);
2887c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  Object* ProcessBackRefInSerializedCode(Object* obj);
289d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org
29056c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // This routine both allocates a new object, and also keeps
29156c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // track of where objects have been allocated so that we can
29256c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // fix back references when deserializing.
29356c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  Address Allocate(int space_index, int size) {
29456c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    Address address = high_water_[space_index];
29556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    high_water_[space_index] = address + size;
29656c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    return address;
29756c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  }
29856c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org
29956c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // This returns the address of an object that has been described in the
30056c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // snapshot as being offset bytes back in a particular space.
30156c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  HeapObject* GetAddressFromEnd(int space) {
30256c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    int offset = source_->GetInt();
30356c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    offset <<= kObjectAlignmentBits;
30456c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    return HeapObject::FromAddress(high_water_[space] - offset);
30556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  }
30656c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org
307ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  // Cached current isolate.
308ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Isolate* isolate_;
309ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
310d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  // Objects from the attached object descriptions in the serialized user code.
311a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Vector<Handle<Object> >* attached_objects_;
312d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org
3133811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  SnapshotByteSource* source_;
314c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  // This is the address of the next object that will be allocated in each
315c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  // space.  It is used to calculate the addresses of back-references.
316c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  Address high_water_[LAST_SPACE + 1];
31756c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org
31856c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  int reservations_[LAST_SPACE + 1];
31956c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  static const intptr_t kUninitializedReservation = -1;
3203811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
321ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ExternalReferenceDecoder* external_reference_decoder_;
322ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
323c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  DISALLOW_COPY_AND_ASSIGN(Deserializer);
3243811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org};
3253811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
3263811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
327b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// Mapping objects to their location after deserialization.
328b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// This is used during building, but not at runtime by V8.
329b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgclass SerializationAddressMapper {
330b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org public:
331b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  SerializationAddressMapper()
33279e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org      : no_allocation_(),
333731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org        serialization_map_(new HashMap(HashMap::PointersMatch)) { }
334b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
335b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ~SerializationAddressMapper() {
336b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    delete serialization_map_;
337b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
338b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
339b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  bool IsMapped(HeapObject* obj) {
340b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    return serialization_map_->Lookup(Key(obj), Hash(obj), false) != NULL;
341b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
342b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
343b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  int MappedTo(HeapObject* obj) {
344e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(IsMapped(obj));
345b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    return static_cast<int>(reinterpret_cast<intptr_t>(
346b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        serialization_map_->Lookup(Key(obj), Hash(obj), false)->value));
347b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
348b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
349b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void AddMapping(HeapObject* obj, int to) {
350e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!IsMapped(obj));
351b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    HashMap::Entry* entry =
352b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        serialization_map_->Lookup(Key(obj), Hash(obj), true);
353b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    entry->value = Value(to);
354b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
355b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
356b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org private:
35740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  static uint32_t Hash(HeapObject* obj) {
358b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
359b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
360b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
36140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  static void* Key(HeapObject* obj) {
362b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    return reinterpret_cast<void*>(obj->address());
363b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
364b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
36540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  static void* Value(int v) {
366b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    return reinterpret_cast<void*>(v);
367b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
368b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
36979e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org  DisallowHeapAllocation no_allocation_;
370b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  HashMap* serialization_map_;
371b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  DISALLOW_COPY_AND_ASSIGN(SerializationAddressMapper);
372b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org};
373b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
374b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
375d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.orgclass CodeAddressMap;
376d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org
377ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org// There can be only one serializer per V8 process.
37840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.orgclass Serializer : public SerializerDeserializer {
3793811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org public:
3803d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org  Serializer(Isolate* isolate, SnapshotByteSink* sink);
3815d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org  ~Serializer();
3823811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void VisitPointers(Object** start, Object** end);
3830c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  // You can call this after serialization to find out how much space was used
3840c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  // in each space.
385f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  int CurrentAllocationAddress(int space) const {
386e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(space < kNumberOfSpaces);
3870c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    return fullness_[space];
3880c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  }
389c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org
3903d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org  Isolate* isolate() const { return isolate_; }
391fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org
392b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  SerializationAddressMapper* address_mapper() { return &address_mapper_; }
39356c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  void PutRoot(int index,
39456c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org               HeapObject* object,
39556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org               HowToCode how,
39656c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org               WhereToPoint where,
39756c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org               int skip);
3983811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
399b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org protected:
40040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  static const int kInvalidRootIndex = -1;
401394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
40288aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  int RootIndex(HeapObject* heap_object, HowToCode from);
403394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  intptr_t root_index_wave_front() { return root_index_wave_front_; }
404394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  void set_root_index_wave_front(intptr_t value) {
405e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(value >= root_index_wave_front_);
406394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    root_index_wave_front_ = value;
407394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
408b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4093811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  class ObjectSerializer : public ObjectVisitor {
4103811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org   public:
411c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    ObjectSerializer(Serializer* serializer,
4123811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org                     Object* o,
4133811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org                     SnapshotByteSink* sink,
4149dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                     HowToCode how_to_code,
4159dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                     WhereToPoint where_to_point)
4163811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org      : serializer_(serializer),
4173811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        object_(HeapObject::cast(o)),
4183811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org        sink_(sink),
4199dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com        reference_representation_(how_to_code + where_to_point),
42056c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org        bytes_processed_so_far_(0),
42156c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org        code_object_(o->IsCode()),
42256c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org        code_has_been_output_(false) { }
4233811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    void Serialize();
4243811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    void VisitPointers(Object** start, Object** end);
42504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org    void VisitEmbeddedPointer(RelocInfo* target);
426c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org    void VisitExternalReference(Address* p);
42704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org    void VisitExternalReference(RelocInfo* rinfo);
4283811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    void VisitCodeTarget(RelocInfo* target);
429145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com    void VisitCodeEntry(Address entry_address);
43041728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    void VisitCell(RelocInfo* rinfo);
431c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    void VisitRuntimeEntry(RelocInfo* reloc);
432c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    // Used for seralizing the external strings that hold the natives source.
4332c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    void VisitExternalOneByteString(
4342c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org        v8::String::ExternalOneByteStringResource** resource);
435c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    // We can't serialize a heap with external two byte strings.
436c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    void VisitExternalTwoByteString(
437c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org        v8::String::ExternalStringResource** resource) {
438c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org      UNREACHABLE();
439c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    }
4403811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
4413811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org   private:
44256c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn };
44356c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    // This function outputs or skips the raw data between the last pointer and
44456c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    // up to the current position.  It optionally can just return the number of
44556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    // bytes to skip instead of performing a skip instruction, in case the skip
44656c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    // can be merged into the next instruction.
44756c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    int OutputRawData(Address up_to, ReturnSkip return_skip = kIgnoringReturn);
4483811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
449c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org    Serializer* serializer_;
4503811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    HeapObject* object_;
4513811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    SnapshotByteSink* sink_;
4529dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    int reference_representation_;
4533811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    int bytes_processed_so_far_;
45456c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    bool code_object_;
45556c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    bool code_has_been_output_;
4563811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  };
4573811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
458b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  virtual void SerializeObject(Object* o,
4599dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                               HowToCode how_to_code,
46056c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org                               WhereToPoint where_to_point,
46156c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org                               int skip) = 0;
462a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  void SerializeReferenceToPreviousObject(HeapObject* heap_object,
463a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org                                          HowToCode how_to_code,
464a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org                                          WhereToPoint where_to_point,
465a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org                                          int skip);
4663811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  void InitializeAllocators();
46756c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // This will return the space for an object.
46840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  static int SpaceOfObject(HeapObject* object);
46956c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  int Allocate(int space, int size);
4703811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  int EncodeExternalReference(Address addr) {
4713811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org    return external_reference_encoder_->Encode(addr);
4723811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  }
4733811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
474ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org  int SpaceAreaSize(int space);
475ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org
476db783297aea0c1b0faf438598202d2abe10da70ebmeurer@chromium.org  // Some roots should not be serialized, because their actual value depends on
477db783297aea0c1b0faf438598202d2abe10da70ebmeurer@chromium.org  // absolute addresses and they are reset after deserialization, anyway.
478db783297aea0c1b0faf438598202d2abe10da70ebmeurer@chromium.org  bool ShouldBeSkipped(Object** current);
479db783297aea0c1b0faf438598202d2abe10da70ebmeurer@chromium.org
480ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org  Isolate* isolate_;
4813811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  // Keep track of the fullness of each space in order to generate
48256c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  // relative addresses for back references.
4833811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  int fullness_[LAST_SPACE + 1];
4843811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  SnapshotByteSink* sink_;
4853811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ExternalReferenceEncoder* external_reference_encoder_;
4864ef23eea527ce7f45bdc5edd52bd4d1a989e2359machenbach@chromium.org
487b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  SerializationAddressMapper address_mapper_;
488394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  intptr_t root_index_wave_front_;
48956c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org  void Pad();
4903811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
4913811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  friend class ObjectSerializer;
492c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  friend class Deserializer;
4933811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
494fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org  // We may not need the code address map for logging for every instance
495fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org  // of the serializer.  Initialize it on demand.
496fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org  void InitializeCodeAddressMap();
497fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org
49805ed9ddc6ff3a1ab3983c50d378cddfa257869b6jkummerow@chromium.org private:
499fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org  CodeAddressMap* code_address_map_;
500c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  DISALLOW_COPY_AND_ASSIGN(Serializer);
5013811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org};
5023811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org
503b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
504b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgclass PartialSerializer : public Serializer {
505b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org public:
5063d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org  PartialSerializer(Isolate* isolate,
5073d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org                    Serializer* startup_snapshot_serializer,
508b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org                    SnapshotByteSink* sink)
5093d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org    : Serializer(isolate, sink),
510b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      startup_serializer_(startup_snapshot_serializer) {
511394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    set_root_index_wave_front(Heap::kStrongRootListLength);
512fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org    InitializeCodeAddressMap();
513b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
514b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
515b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Serialize the objects reachable from a single object pointer.
5163ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  void Serialize(Object** o);
517b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  virtual void SerializeObject(Object* o,
5189dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                               HowToCode how_to_code,
51956c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org                               WhereToPoint where_to_point,
52056c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org                               int skip);
521b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5223ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org private:
5233ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  int PartialSnapshotCacheIndex(HeapObject* o);
5243ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
5255d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org    // Scripts should be referred only through shared function infos.  We can't
5265d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org    // allow them to be part of the partial snapshot because they contain a
5275d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org    // unique ID, and deserializing several partial snapshots containing script
5285d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org    // would cause dupes.
529e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!o->IsScript());
5301510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    return o->IsName() || o->IsSharedFunctionInfo() ||
5310b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org           o->IsHeapNumber() || o->IsCode() ||
532c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org           o->IsScopeInfo() ||
533c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org           o->map() ==
534c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org               startup_serializer_->isolate()->heap()->fixed_cow_array_map();
535b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
536b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5373ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
538b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Serializer* startup_serializer_;
539b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  DISALLOW_COPY_AND_ASSIGN(PartialSerializer);
540b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org};
541b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
542b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
543b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgclass StartupSerializer : public Serializer {
544b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org public:
5453d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org  StartupSerializer(Isolate* isolate, SnapshotByteSink* sink)
5463d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org    : Serializer(isolate, sink) {
547b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    // Clear the cache of objects used by the partial snapshot.  After the
548b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    // strong roots have been serialized we can create a partial snapshot
549394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // which will repopulate the cache with objects needed by that partial
550b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    // snapshot.
5513d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org    isolate->set_serialize_partial_snapshot_cache_length(0);
552fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org    InitializeCodeAddressMap();
553b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
554b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Serialize the current state of the heap.  The order is:
555b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // 1) Strong references.
556b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // 2) Partial snapshot cache.
5574a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // 3) Weak references (e.g. the string table).
558b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  virtual void SerializeStrongReferences();
559b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  virtual void SerializeObject(Object* o,
5609dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                               HowToCode how_to_code,
56156c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org                               WhereToPoint where_to_point,
56256c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org                               int skip);
563b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void SerializeWeakReferences();
564b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  void Serialize() {
565b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    SerializeStrongReferences();
566b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    SerializeWeakReferences();
56756c14afabc547f0a8ab2e24d789c00030f8df892ulan@chromium.org    Pad();
568b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
569d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org
570d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org private:
571d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  DISALLOW_COPY_AND_ASSIGN(StartupSerializer);
572b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org};
573b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5745d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org
575f78524cb19cf078611235da0d6e361207f7eacdcmachenbach@chromium.orgclass CodeSerializer : public Serializer {
576f78524cb19cf078611235da0d6e361207f7eacdcmachenbach@chromium.org public:
577d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source)
578d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org      : Serializer(isolate, sink), source_(source) {
579f78524cb19cf078611235da0d6e361207f7eacdcmachenbach@chromium.org    set_root_index_wave_front(Heap::kStrongRootListLength);
580f78524cb19cf078611235da0d6e361207f7eacdcmachenbach@chromium.org    InitializeCodeAddressMap();
581f78524cb19cf078611235da0d6e361207f7eacdcmachenbach@chromium.org  }
582f78524cb19cf078611235da0d6e361207f7eacdcmachenbach@chromium.org
583d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  static ScriptData* Serialize(Isolate* isolate,
584d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org                               Handle<SharedFunctionInfo> info,
585d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org                               Handle<String> source);
586d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org
587f78524cb19cf078611235da0d6e361207f7eacdcmachenbach@chromium.org  virtual void SerializeObject(Object* o, HowToCode how_to_code,
588f78524cb19cf078611235da0d6e361207f7eacdcmachenbach@chromium.org                               WhereToPoint where_to_point, int skip);
589f78524cb19cf078611235da0d6e361207f7eacdcmachenbach@chromium.org
590d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  static Handle<SharedFunctionInfo> Deserialize(Isolate* isolate,
591d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org                                                ScriptData* data,
592d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org                                                Handle<String> source);
593d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org
594d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  static const int kSourceObjectIndex = 0;
595a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  static const int kCodeStubsBaseIndex = 1;
596f78524cb19cf078611235da0d6e361207f7eacdcmachenbach@chromium.org
5974c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org  String* source() {
598e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!AllowHeapAllocation::IsAllowed());
5994c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org    return source_;
6004c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org  }
6014c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org
602a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  List<uint32_t>* stub_keys() { return &stub_keys_; }
603a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
6049bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org private:
6059bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  void SerializeBuiltin(Code* builtin, HowToCode how_to_code,
6069bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                        WhereToPoint where_to_point, int skip);
607a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  void SerializeCodeStub(Code* code, HowToCode how_to_code,
608a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org                         WhereToPoint where_to_point, int skip);
609d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  void SerializeSourceObject(HowToCode how_to_code, WhereToPoint where_to_point,
610d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org                             int skip);
611a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  void SerializeHeapObject(HeapObject* heap_object, HowToCode how_to_code,
612a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org                           WhereToPoint where_to_point, int skip);
613a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  int AddCodeStubKey(uint32_t stub_key);
614d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org
615d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  DisallowHeapAllocation no_gc_;
616d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  String* source_;
617a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  List<uint32_t> stub_keys_;
618d6472083da14af6fde0101cc78f95ababd7cc077machenbach@chromium.org  DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
619f78524cb19cf078611235da0d6e361207f7eacdcmachenbach@chromium.org};
62070d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
62170d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
62270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org// Wrapper around ScriptData to provide code-serializer-specific functionality.
62370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.orgclass SerializedCodeData {
62470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org public:
62570d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  // Used by when consuming.
6264c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org  explicit SerializedCodeData(ScriptData* data, String* source)
62770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      : script_data_(data), owns_script_data_(false) {
6284c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org    DisallowHeapAllocation no_gc;
6294c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org    CHECK(IsSane(source));
63070d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  }
63170d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
63270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  // Used when producing.
63370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  SerializedCodeData(List<byte>* payload, CodeSerializer* cs);
63470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
63570d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  ~SerializedCodeData() {
63670d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    if (owns_script_data_) delete script_data_;
63770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  }
63870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
63970d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  // Return ScriptData object and relinquish ownership over it to the caller.
64070d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  ScriptData* GetScriptData() {
64170d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    ScriptData* result = script_data_;
64270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    script_data_ = NULL;
643e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(owns_script_data_);
64470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    owns_script_data_ = false;
64570d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    return result;
64670d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  }
64770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
648a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Vector<const uint32_t> CodeStubKeys() const {
649a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    return Vector<const uint32_t>(
650a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        reinterpret_cast<const uint32_t*>(script_data_->data() + kHeaderSize),
651a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        GetHeaderValue(kNumCodeStubKeysOffset));
652a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  }
653a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
65470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  const byte* Payload() const {
655a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    int code_stubs_size = GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size;
656a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    return script_data_->data() + kHeaderSize + code_stubs_size;
65770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  }
65870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
65970d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  int PayloadLength() const {
660a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    int payload_length = GetHeaderValue(kPayloadLengthOffset);
661a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    DCHECK_EQ(script_data_->data() + script_data_->length(),
662a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org              Payload() + payload_length);
663a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    return payload_length;
66470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  }
66570d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
66670d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  int GetReservation(int space) const {
66770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    return GetHeaderValue(kReservationsOffset + space);
66870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  }
66970d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
67070d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org private:
67170d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  void SetHeaderValue(int offset, int value) {
67270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    reinterpret_cast<int*>(const_cast<byte*>(script_data_->data()))[offset] =
67370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org        value;
67470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  }
67570d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
67670d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  int GetHeaderValue(int offset) const {
67770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    return reinterpret_cast<const int*>(script_data_->data())[offset];
67870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  }
67970d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
6804c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org  bool IsSane(String* source);
6814c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org
6824c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org  int CheckSum(String* source);
68370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
68470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  // The data header consists of int-sized entries:
68570d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  // [0] version hash
686a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // [1] number of code stub keys
687a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // [2] payload length
688a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // [3..9] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
6894c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org  static const int kCheckSumOffset = 0;
690a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  static const int kNumCodeStubKeysOffset = 1;
691a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  static const int kPayloadLengthOffset = 2;
692a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  static const int kReservationsOffset = 3;
693a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
694a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  static const int kNumSpaces = PROPERTY_CELL_SPACE - NEW_SPACE + 1;
695a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  static const int kHeaderEntries = kReservationsOffset + kNumSpaces;
696a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  static const int kHeaderSize = kHeaderEntries * kIntSize;
697a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
698a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // Following the header, we store, in sequential order
699a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // - code stub keys
700a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // - serialization payload
70170d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
70270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  ScriptData* script_data_;
70370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  bool owns_script_data_;
70470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org};
70543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} }  // namespace v8::internal
70643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
70743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#endif  // V8_SERIALIZE_H_
708