Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(495)

Side by Side Diff: src/serialize.cc

Issue 394007: * Remove old snapshot implementation (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 26 matching lines...) Expand all
37 #include "runtime.h" 37 #include "runtime.h"
38 #include "serialize.h" 38 #include "serialize.h"
39 #include "stub-cache.h" 39 #include "stub-cache.h"
40 #include "v8threads.h" 40 #include "v8threads.h"
41 #include "top.h" 41 #include "top.h"
42 #include "bootstrapper.h" 42 #include "bootstrapper.h"
43 43
44 namespace v8 { 44 namespace v8 {
45 namespace internal { 45 namespace internal {
46 46
47 // 32-bit encoding: a RelativeAddress must be able to fit in a
48 // pointer: it is encoded as an Address with (from LS to MS bits):
49 // - 2 bits identifying this as a HeapObject.
50 // - 4 bits to encode the AllocationSpace (including special values for
51 // code and fixed arrays in LO space)
52 // - 27 bits identifying a word in the space, in one of three formats:
53 // - paged spaces: 16 bits of page number, 11 bits of word offset in page
54 // - NEW space: 27 bits of word offset
55 // - LO space: 27 bits of page number
56
57 const int kSpaceShift = kHeapObjectTagSize;
58 const int kSpaceBits = 4;
59 const int kSpaceMask = (1 << kSpaceBits) - 1;
60
61 const int kOffsetShift = kSpaceShift + kSpaceBits;
62 const int kOffsetBits = 11;
63 const int kOffsetMask = (1 << kOffsetBits) - 1;
64
65 const int kPageShift = kOffsetShift + kOffsetBits;
66 const int kPageBits = 32 - (kOffsetBits + kSpaceBits + kHeapObjectTagSize);
67 const int kPageMask = (1 << kPageBits) - 1;
68
69 const int kPageAndOffsetShift = kOffsetShift;
70 const int kPageAndOffsetBits = kPageBits + kOffsetBits;
71 const int kPageAndOffsetMask = (1 << kPageAndOffsetBits) - 1;
72
73 // These values are special allocation space tags used for
74 // serialization.
75 // Mark the pages executable on platforms that support it.
76 const int kLargeCode = LAST_SPACE + 1;
77 // Allocate extra remembered-set bits.
78 const int kLargeFixedArray = LAST_SPACE + 2;
79
80
81 static inline AllocationSpace GetSpace(Address addr) {
82 const intptr_t encoded = reinterpret_cast<intptr_t>(addr);
83 int space_number = (static_cast<int>(encoded >> kSpaceShift) & kSpaceMask);
84 if (space_number > LAST_SPACE) space_number = LO_SPACE;
85 return static_cast<AllocationSpace>(space_number);
86 }
87
88
89 static inline bool IsLargeExecutableObject(Address addr) {
90 const intptr_t encoded = reinterpret_cast<intptr_t>(addr);
91 const int space_number =
92 (static_cast<int>(encoded >> kSpaceShift) & kSpaceMask);
93 return (space_number == kLargeCode);
94 }
95
96
97 static inline bool IsLargeFixedArray(Address addr) {
98 const intptr_t encoded = reinterpret_cast<intptr_t>(addr);
99 const int space_number =
100 (static_cast<int>(encoded >> kSpaceShift) & kSpaceMask);
101 return (space_number == kLargeFixedArray);
102 }
103
104
105 static inline int PageIndex(Address addr) {
106 const intptr_t encoded = reinterpret_cast<intptr_t>(addr);
107 return static_cast<int>(encoded >> kPageShift) & kPageMask;
108 }
109
110
111 static inline int PageOffset(Address addr) {
112 const intptr_t encoded = reinterpret_cast<intptr_t>(addr);
113 const int offset = static_cast<int>(encoded >> kOffsetShift) & kOffsetMask;
114 return offset << kObjectAlignmentBits;
115 }
116
117
118 static inline int NewSpaceOffset(Address addr) {
119 const intptr_t encoded = reinterpret_cast<intptr_t>(addr);
120 const int page_offset =
121 static_cast<int>(encoded >> kPageAndOffsetShift) & kPageAndOffsetMask;
122 return page_offset << kObjectAlignmentBits;
123 }
124
125
126 static inline int LargeObjectIndex(Address addr) {
127 const intptr_t encoded = reinterpret_cast<intptr_t>(addr);
128 return static_cast<int>(encoded >> kPageAndOffsetShift) & kPageAndOffsetMask;
129 }
130
131
132 // A RelativeAddress encodes a heap address that is independent of
133 // the actual memory addresses in real heap. The general case (for the
134 // OLD, CODE and MAP spaces) is as a (space id, page number, page offset)
135 // triple. The NEW space has page number == 0, because there are no
136 // pages. The LARGE_OBJECT space has page offset = 0, since there is
137 // exactly one object per page. RelativeAddresses are encodable as
138 // Addresses, so that they can replace the map() pointers of
139 // HeapObjects. The encoded Addresses are also encoded as HeapObjects
140 // and allow for marking (is_marked() see mark(), clear_mark()...) as
141 // used by the Mark-Compact collector.
142
143 class RelativeAddress {
144 public:
145 RelativeAddress(AllocationSpace space,
146 int page_index,
147 int page_offset)
148 : space_(space), page_index_(page_index), page_offset_(page_offset) {
149 // Assert that the space encoding (plus the two pseudo-spaces for
150 // special large objects) fits in the available bits.
151 ASSERT(((LAST_SPACE + 2) & ~kSpaceMask) == 0);
152 ASSERT(space <= LAST_SPACE && space >= 0);
153 }
154
155 // Return the encoding of 'this' as an Address. Decode with constructor.
156 Address Encode() const;
157
158 AllocationSpace space() const {
159 if (space_ > LAST_SPACE) return LO_SPACE;
160 return static_cast<AllocationSpace>(space_);
161 }
162 int page_index() const { return page_index_; }
163 int page_offset() const { return page_offset_; }
164
165 bool in_paged_space() const {
166 return space_ == CODE_SPACE ||
167 space_ == OLD_POINTER_SPACE ||
168 space_ == OLD_DATA_SPACE ||
169 space_ == MAP_SPACE ||
170 space_ == CELL_SPACE;
171 }
172
173 void next_address(int offset) { page_offset_ += offset; }
174 void next_page(int init_offset = 0) {
175 page_index_++;
176 page_offset_ = init_offset;
177 }
178
179 #ifdef DEBUG
180 void Verify();
181 #endif
182
183 void set_to_large_code_object() {
184 ASSERT(space_ == LO_SPACE);
185 space_ = kLargeCode;
186 }
187 void set_to_large_fixed_array() {
188 ASSERT(space_ == LO_SPACE);
189 space_ = kLargeFixedArray;
190 }
191
192
193 private:
194 int space_;
195 int page_index_;
196 int page_offset_;
197 };
198
199
200 Address RelativeAddress::Encode() const {
201 ASSERT(page_index_ >= 0);
202 int word_offset = 0;
203 int result = 0;
204 switch (space_) {
205 case MAP_SPACE:
206 case CELL_SPACE:
207 case OLD_POINTER_SPACE:
208 case OLD_DATA_SPACE:
209 case CODE_SPACE:
210 ASSERT_EQ(0, page_index_ & ~kPageMask);
211 word_offset = page_offset_ >> kObjectAlignmentBits;
212 ASSERT_EQ(0, word_offset & ~kOffsetMask);
213 result = (page_index_ << kPageShift) | (word_offset << kOffsetShift);
214 break;
215 case NEW_SPACE:
216 ASSERT_EQ(0, page_index_);
217 word_offset = page_offset_ >> kObjectAlignmentBits;
218 ASSERT_EQ(0, word_offset & ~kPageAndOffsetMask);
219 result = word_offset << kPageAndOffsetShift;
220 break;
221 case LO_SPACE:
222 case kLargeCode:
223 case kLargeFixedArray:
224 ASSERT_EQ(0, page_offset_);
225 ASSERT_EQ(0, page_index_ & ~kPageAndOffsetMask);
226 result = page_index_ << kPageAndOffsetShift;
227 break;
228 }
229 // OR in AllocationSpace and kHeapObjectTag
230 ASSERT_EQ(0, space_ & ~kSpaceMask);
231 result |= (space_ << kSpaceShift) | kHeapObjectTag;
232 return reinterpret_cast<Address>(result);
233 }
234
235
236 #ifdef DEBUG
237 void RelativeAddress::Verify() {
238 ASSERT(page_offset_ >= 0 && page_index_ >= 0);
239 switch (space_) {
240 case MAP_SPACE:
241 case CELL_SPACE:
242 case OLD_POINTER_SPACE:
243 case OLD_DATA_SPACE:
244 case CODE_SPACE:
245 ASSERT(Page::kObjectStartOffset <= page_offset_ &&
246 page_offset_ <= Page::kPageSize);
247 break;
248 case NEW_SPACE:
249 ASSERT(page_index_ == 0);
250 break;
251 case LO_SPACE:
252 case kLargeCode:
253 case kLargeFixedArray:
254 ASSERT(page_offset_ == 0);
255 break;
256 }
257 }
258 #endif
259
260 enum GCTreatment {
261 DataObject, // Object that cannot contain a reference to new space.
262 PointerObject, // Object that can contain a reference to new space.
263 CodeObject // Object that contains executable code.
264 };
265
266 // A SimulatedHeapSpace simulates the allocation of objects in a page in
267 // the heap. It uses linear allocation - that is, it doesn't simulate the
268 // use of a free list. This simulated
269 // allocation must exactly match that done by Heap.
270
271 class SimulatedHeapSpace {
272 public:
273 // The default constructor initializes to an invalid state.
274 SimulatedHeapSpace(): current_(LAST_SPACE, -1, -1) {}
275
276 // Sets 'this' to the first address in 'space' that would be
277 // returned by allocation in an empty heap.
278 void InitEmptyHeap(AllocationSpace space);
279
280 // Sets 'this' to the next address in 'space' that would be returned
281 // by allocation in the current heap. Intended only for testing
282 // serialization and deserialization in the current address space.
283 void InitCurrentHeap(AllocationSpace space);
284
285 // Returns the RelativeAddress where the next
286 // object of 'size' bytes will be allocated, and updates 'this' to
287 // point to the next free address beyond that object.
288 RelativeAddress Allocate(int size, GCTreatment special_gc_treatment);
289
290 private:
291 RelativeAddress current_;
292 };
293
294
295 void SimulatedHeapSpace::InitEmptyHeap(AllocationSpace space) {
296 switch (space) {
297 case MAP_SPACE:
298 case CELL_SPACE:
299 case OLD_POINTER_SPACE:
300 case OLD_DATA_SPACE:
301 case CODE_SPACE:
302 current_ = RelativeAddress(space, 0, Page::kObjectStartOffset);
303 break;
304 case NEW_SPACE:
305 case LO_SPACE:
306 current_ = RelativeAddress(space, 0, 0);
307 break;
308 }
309 }
310
311
312 void SimulatedHeapSpace::InitCurrentHeap(AllocationSpace space) {
313 switch (space) {
314 case MAP_SPACE:
315 case CELL_SPACE:
316 case OLD_POINTER_SPACE:
317 case OLD_DATA_SPACE:
318 case CODE_SPACE: {
319 PagedSpace* ps;
320 if (space == MAP_SPACE) {
321 ps = Heap::map_space();
322 } else if (space == CELL_SPACE) {
323 ps = Heap::cell_space();
324 } else if (space == OLD_POINTER_SPACE) {
325 ps = Heap::old_pointer_space();
326 } else if (space == OLD_DATA_SPACE) {
327 ps = Heap::old_data_space();
328 } else {
329 ASSERT(space == CODE_SPACE);
330 ps = Heap::code_space();
331 }
332 Address top = ps->top();
333 Page* top_page = Page::FromAllocationTop(top);
334 int page_index = 0;
335 PageIterator it(ps, PageIterator::PAGES_IN_USE);
336 while (it.has_next()) {
337 if (it.next() == top_page) break;
338 page_index++;
339 }
340 current_ = RelativeAddress(space,
341 page_index,
342 top_page->Offset(top));
343 break;
344 }
345 case NEW_SPACE:
346 current_ = RelativeAddress(space,
347 0,
348 static_cast<int>(Heap::NewSpaceTop()
349 - Heap::NewSpaceStart()));
350 break;
351 case LO_SPACE:
352 int page_index = 0;
353 for (LargeObjectIterator it(Heap::lo_space()); it.has_next(); it.next()) {
354 page_index++;
355 }
356 current_ = RelativeAddress(space, page_index, 0);
357 break;
358 }
359 }
360
361
362 RelativeAddress SimulatedHeapSpace::Allocate(int size,
363 GCTreatment special_gc_treatment) {
364 #ifdef DEBUG
365 current_.Verify();
366 #endif
367 int alloc_size = OBJECT_SIZE_ALIGN(size);
368 if (current_.in_paged_space() &&
369 current_.page_offset() + alloc_size > Page::kPageSize) {
370 ASSERT(alloc_size <= Page::kMaxHeapObjectSize);
371 current_.next_page(Page::kObjectStartOffset);
372 }
373 RelativeAddress result = current_;
374 if (current_.space() == LO_SPACE) {
375 current_.next_page();
376 if (special_gc_treatment == CodeObject) {
377 result.set_to_large_code_object();
378 } else if (special_gc_treatment == PointerObject) {
379 result.set_to_large_fixed_array();
380 }
381 } else {
382 current_.next_address(alloc_size);
383 }
384 #ifdef DEBUG
385 current_.Verify();
386 result.Verify();
387 #endif
388 return result;
389 }
390
391 // ----------------------------------------------------------------------------- 47 // -----------------------------------------------------------------------------
392 // Coding of external references. 48 // Coding of external references.
393 49
394 // The encoding of an external reference. The type is in the high word. 50 // The encoding of an external reference. The type is in the high word.
395 // The id is in the low word. 51 // The id is in the low word.
396 static uint32_t EncodeExternal(TypeCode type, uint16_t id) { 52 static uint32_t EncodeExternal(TypeCode type, uint16_t id) {
397 return static_cast<uint32_t>(type) << 16 | id; 53 return static_cast<uint32_t>(type) << 16 | id;
398 } 54 }
399 55
400 56
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 478
823 479
824 ExternalReferenceDecoder::~ExternalReferenceDecoder() { 480 ExternalReferenceDecoder::~ExternalReferenceDecoder() {
825 for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) { 481 for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
826 DeleteArray(encodings_[type]); 482 DeleteArray(encodings_[type]);
827 } 483 }
828 DeleteArray(encodings_); 484 DeleteArray(encodings_);
829 } 485 }
830 486
831 487
832 //------------------------------------------------------------------------------
833 // Implementation of Serializer
834
835
836 // Helper class to write the bytes of the serialized heap.
837
838 class SnapshotWriter {
839 public:
840 SnapshotWriter() {
841 len_ = 0;
842 max_ = 8 << 10; // 8K initial size
843 str_ = NewArray<byte>(max_);
844 }
845
846 ~SnapshotWriter() {
847 DeleteArray(str_);
848 }
849
850 void GetBytes(byte** str, int* len) {
851 *str = NewArray<byte>(len_);
852 memcpy(*str, str_, len_);
853 *len = len_;
854 }
855
856 void Reserve(int bytes, int pos);
857
858 void PutC(char c) {
859 InsertC(c, len_);
860 }
861
862 void PutInt(int i) {
863 InsertInt(i, len_);
864 }
865
866 void PutAddress(Address p) {
867 PutBytes(reinterpret_cast<byte*>(&p), sizeof(p));
868 }
869
870 void PutBytes(const byte* a, int size) {
871 InsertBytes(a, len_, size);
872 }
873
874 void PutString(const char* s) {
875 InsertString(s, len_);
876 }
877
878 int InsertC(char c, int pos) {
879 Reserve(1, pos);
880 str_[pos] = c;
881 len_++;
882 return pos + 1;
883 }
884
885 int InsertInt(int i, int pos) {
886 return InsertBytes(reinterpret_cast<byte*>(&i), pos, sizeof(i));
887 }
888
889 int InsertBytes(const byte* a, int pos, int size) {
890 Reserve(size, pos);
891 memcpy(&str_[pos], a, size);
892 len_ += size;
893 return pos + size;
894 }
895
896 int InsertString(const char* s, int pos);
897
898 int length() { return len_; }
899
900 Address position() { return reinterpret_cast<Address>(&str_[len_]); }
901
902 private:
903 byte* str_; // the snapshot
904 int len_; // the current length of str_
905 int max_; // the allocated size of str_
906 };
907
908
909 void SnapshotWriter::Reserve(int bytes, int pos) {
910 CHECK(0 <= pos && pos <= len_);
911 while (len_ + bytes >= max_) {
912 max_ *= 2;
913 byte* old = str_;
914 str_ = NewArray<byte>(max_);
915 memcpy(str_, old, len_);
916 DeleteArray(old);
917 }
918 if (pos < len_) {
919 byte* old = str_;
920 str_ = NewArray<byte>(max_);
921 memcpy(str_, old, pos);
922 memcpy(str_ + pos + bytes, old + pos, len_ - pos);
923 DeleteArray(old);
924 }
925 }
926
927 int SnapshotWriter::InsertString(const char* s, int pos) {
928 int size = StrLength(s);
929 pos = InsertC('[', pos);
930 pos = InsertInt(size, pos);
931 pos = InsertC(']', pos);
932 return InsertBytes(reinterpret_cast<const byte*>(s), pos, size);
933 }
934
935
936 class ReferenceUpdater: public ObjectVisitor {
937 public:
938 ReferenceUpdater(HeapObject* obj, Serializer* serializer)
939 : obj_address_(obj->address()),
940 serializer_(serializer),
941 reference_encoder_(serializer->reference_encoder_),
942 offsets_(8),
943 addresses_(8),
944 offsets_32_bit_(0),
945 data_32_bit_(0) {
946 }
947
948 virtual void VisitPointers(Object** start, Object** end) {
949 for (Object** p = start; p < end; ++p) {
950 if ((*p)->IsHeapObject()) {
951 offsets_.Add(
952 static_cast<int>(reinterpret_cast<Address>(p) - obj_address_));
953 Address a = serializer_->GetSavedAddress(HeapObject::cast(*p));
954 addresses_.Add(a);
955 }
956 }
957 }
958
959 virtual void VisitCodeTarget(RelocInfo* rinfo) {
960 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
961 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
962 Address encoded_target = serializer_->GetSavedAddress(target);
963 // All calls and jumps are to code objects that encode into 32 bits.
964 offsets_32_bit_.Add(
965 static_cast<int>(rinfo->target_address_address() - obj_address_));
966 uint32_t small_target =
967 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(encoded_target));
968 ASSERT(reinterpret_cast<uintptr_t>(encoded_target) == small_target);
969 data_32_bit_.Add(small_target);
970 }
971
972
973 virtual void VisitExternalReferences(Address* start, Address* end) {
974 for (Address* p = start; p < end; ++p) {
975 uint32_t code = reference_encoder_->Encode(*p);
976 CHECK(*p == NULL ? code == 0 : code != 0);
977 offsets_.Add(
978 static_cast<int>(reinterpret_cast<Address>(p) - obj_address_));
979 addresses_.Add(reinterpret_cast<Address>(code));
980 }
981 }
982
983 virtual void VisitRuntimeEntry(RelocInfo* rinfo) {
984 Address target = rinfo->target_address();
985 uint32_t encoding = reference_encoder_->Encode(target);
986 CHECK(target == NULL ? encoding == 0 : encoding != 0);
987 offsets_.Add(
988 static_cast<int>(rinfo->target_address_address() - obj_address_));
989 addresses_.Add(reinterpret_cast<Address>(encoding));
990 }
991
992 void Update(Address start_address) {
993 for (int i = 0; i < offsets_.length(); i++) {
994 memcpy(start_address + offsets_[i], &addresses_[i], sizeof(Address));
995 }
996 for (int i = 0; i < offsets_32_bit_.length(); i++) {
997 memcpy(start_address + offsets_32_bit_[i], &data_32_bit_[i],
998 sizeof(uint32_t));
999 }
1000 }
1001
1002 private:
1003 Address obj_address_;
1004 Serializer* serializer_;
1005 ExternalReferenceEncoder* reference_encoder_;
1006 List<int> offsets_;
1007 List<Address> addresses_;
1008 // Some updates are 32-bit even on a 64-bit platform.
1009 // We keep a separate list of them on 64-bit platforms.
1010 List<int> offsets_32_bit_;
1011 List<uint32_t> data_32_bit_;
1012 };
1013
1014
1015 // Helper functions for a map of encoded heap object addresses.
1016 static uint32_t HeapObjectHash(HeapObject* key) {
1017 uint32_t low32bits = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key));
1018 return low32bits >> 2;
1019 }
1020
1021
1022 static bool MatchHeapObject(void* key1, void* key2) {
1023 return key1 == key2;
1024 }
1025
1026
1027 Serializer::Serializer()
1028 : global_handles_(4),
1029 saved_addresses_(MatchHeapObject) {
1030 root_ = true;
1031 roots_ = 0;
1032 objects_ = 0;
1033 reference_encoder_ = NULL;
1034 writer_ = new SnapshotWriter();
1035 for (int i = 0; i <= LAST_SPACE; i++) {
1036 allocator_[i] = new SimulatedHeapSpace();
1037 }
1038 }
1039
1040
1041 Serializer::~Serializer() {
1042 for (int i = 0; i <= LAST_SPACE; i++) {
1043 delete allocator_[i];
1044 }
1045 if (reference_encoder_) delete reference_encoder_;
1046 delete writer_;
1047 }
1048
1049
1050 bool Serializer::serialization_enabled_ = false; 488 bool Serializer::serialization_enabled_ = false;
1051 bool Serializer::too_late_to_enable_now_ = false; 489 bool Serializer::too_late_to_enable_now_ = false;
1052 490
1053 491
1054 #ifdef DEBUG 492 Deserializer::Deserializer(SnapshotByteSource* source)
1055 static const int kMaxTagLength = 32;
1056
1057 void Serializer::Synchronize(const char* tag) {
1058 if (FLAG_debug_serialization) {
1059 int length = StrLength(tag);
1060 ASSERT(length <= kMaxTagLength);
1061 writer_->PutC('S');
1062 writer_->PutInt(length);
1063 writer_->PutBytes(reinterpret_cast<const byte*>(tag), length);
1064 }
1065 }
1066 #endif
1067
1068
1069 void Serializer::InitializeAllocators() {
1070 for (int i = 0; i <= LAST_SPACE; i++) {
1071 allocator_[i]->InitEmptyHeap(static_cast<AllocationSpace>(i));
1072 }
1073 }
1074
1075
1076 bool Serializer::IsVisited(HeapObject* obj) {
1077 HashMap::Entry* entry =
1078 saved_addresses_.Lookup(obj, HeapObjectHash(obj), false);
1079 return entry != NULL;
1080 }
1081
1082
1083 Address Serializer::GetSavedAddress(HeapObject* obj) {
1084 HashMap::Entry* entry =
1085 saved_addresses_.Lookup(obj, HeapObjectHash(obj), false);
1086 ASSERT(entry != NULL);
1087 return reinterpret_cast<Address>(entry->value);
1088 }
1089
1090
1091 void Serializer::SaveAddress(HeapObject* obj, Address addr) {
1092 HashMap::Entry* entry =
1093 saved_addresses_.Lookup(obj, HeapObjectHash(obj), true);
1094 entry->value = addr;
1095 }
1096
1097
1098 void Serializer::Serialize() {
1099 // No active threads.
1100 CHECK_EQ(NULL, ThreadState::FirstInUse());
1101 // No active or weak handles.
1102 CHECK(HandleScopeImplementer::instance()->blocks()->is_empty());
1103 CHECK_EQ(0, GlobalHandles::NumberOfWeakHandles());
1104 // We need a counter function during serialization to resolve the
1105 // references to counters in the code on the heap.
1106 CHECK(StatsTable::HasCounterFunction());
1107 CHECK(enabled());
1108 InitializeAllocators();
1109 reference_encoder_ = new ExternalReferenceEncoder();
1110 PutHeader();
1111 Heap::IterateRoots(this, VISIT_ONLY_STRONG);
1112 PutLog();
1113 PutContextStack();
1114 Disable();
1115 }
1116
1117
1118 void Serializer::Finalize(byte** str, int* len) {
1119 writer_->GetBytes(str, len);
1120 }
1121
1122
1123 // Serialize objects by writing them into the stream.
1124
1125 void Serializer::VisitPointers(Object** start, Object** end) {
1126 bool root = root_;
1127 root_ = false;
1128 for (Object** p = start; p < end; ++p) {
1129 bool serialized;
1130 Address a = Encode(*p, &serialized);
1131 if (root) {
1132 roots_++;
1133 // If the object was not just serialized,
1134 // write its encoded address instead.
1135 if (!serialized) PutEncodedAddress(a);
1136 }
1137 }
1138 root_ = root;
1139 }
1140
1141
1142 void Serializer::VisitCodeTarget(RelocInfo* rinfo) {
1143 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
1144 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
1145 bool serialized;
1146 Encode(target, &serialized);
1147 }
1148
1149
1150 class GlobalHandlesRetriever: public ObjectVisitor {
1151 public:
1152 explicit GlobalHandlesRetriever(List<Object**>* handles)
1153 : global_handles_(handles) {}
1154
1155 virtual void VisitPointers(Object** start, Object** end) {
1156 for (; start != end; ++start) {
1157 global_handles_->Add(start);
1158 }
1159 }
1160
1161 private:
1162 List<Object**>* global_handles_;
1163 };
1164
1165
1166 void Serializer::PutFlags() {
1167 writer_->PutC('F');
1168 List<const char*>* argv = FlagList::argv();
1169 writer_->PutInt(argv->length());
1170 writer_->PutC('[');
1171 for (int i = 0; i < argv->length(); i++) {
1172 if (i > 0) writer_->PutC('|');
1173 writer_->PutString((*argv)[i]);
1174 DeleteArray((*argv)[i]);
1175 }
1176 writer_->PutC(']');
1177 flags_end_ = writer_->length();
1178 delete argv;
1179 }
1180
1181
1182 void Serializer::PutHeader() {
1183 PutFlags();
1184 writer_->PutC('D');
1185 #ifdef DEBUG
1186 writer_->PutC(FLAG_debug_serialization ? '1' : '0');
1187 #else
1188 writer_->PutC('0');
1189 #endif
1190 #ifdef V8_NATIVE_REGEXP
1191 writer_->PutC('N');
1192 #else // Interpreted regexp
1193 writer_->PutC('I');
1194 #endif
1195 // Write sizes of paged memory spaces. Allocate extra space for the old
1196 // and code spaces, because objects in new space will be promoted to them.
1197 writer_->PutC('S');
1198 writer_->PutC('[');
1199 writer_->PutInt(Heap::old_pointer_space()->Size() +
1200 Heap::new_space()->Size());
1201 writer_->PutC('|');
1202 writer_->PutInt(Heap::old_data_space()->Size() + Heap::new_space()->Size());
1203 writer_->PutC('|');
1204 writer_->PutInt(Heap::code_space()->Size() + Heap::new_space()->Size());
1205 writer_->PutC('|');
1206 writer_->PutInt(Heap::map_space()->Size());
1207 writer_->PutC('|');
1208 writer_->PutInt(Heap::cell_space()->Size());
1209 writer_->PutC(']');
1210 // Write global handles.
1211 writer_->PutC('G');
1212 writer_->PutC('[');
1213 GlobalHandlesRetriever ghr(&global_handles_);
1214 GlobalHandles::IterateStrongRoots(&ghr);
1215 for (int i = 0; i < global_handles_.length(); i++) {
1216 writer_->PutC('N');
1217 }
1218 writer_->PutC(']');
1219 }
1220
1221
1222 void Serializer::PutLog() {
1223 #ifdef ENABLE_LOGGING_AND_PROFILING
1224 if (FLAG_log_code) {
1225 Logger::TearDown();
1226 int pos = writer_->InsertC('L', flags_end_);
1227 bool exists;
1228 Vector<const char> log = ReadFile(FLAG_logfile, &exists);
1229 writer_->InsertString(log.start(), pos);
1230 log.Dispose();
1231 }
1232 #endif
1233 }
1234
1235
1236 static int IndexOf(const List<Object**>& list, Object** element) {
1237 for (int i = 0; i < list.length(); i++) {
1238 if (list[i] == element) return i;
1239 }
1240 return -1;
1241 }
1242
1243
1244 void Serializer::PutGlobalHandleStack(const List<Handle<Object> >& stack) {
1245 writer_->PutC('[');
1246 writer_->PutInt(stack.length());
1247 for (int i = stack.length() - 1; i >= 0; i--) {
1248 writer_->PutC('|');
1249 int gh_index = IndexOf(global_handles_, stack[i].location());
1250 CHECK_GE(gh_index, 0);
1251 writer_->PutInt(gh_index);
1252 }
1253 writer_->PutC(']');
1254 }
1255
1256
1257 void Serializer::PutContextStack() {
1258 List<Context*> contexts(2);
1259 while (HandleScopeImplementer::instance()->HasSavedContexts()) {
1260 Context* context =
1261 HandleScopeImplementer::instance()->RestoreContext();
1262 contexts.Add(context);
1263 }
1264 for (int i = contexts.length() - 1; i >= 0; i--) {
1265 HandleScopeImplementer::instance()->SaveContext(contexts[i]);
1266 }
1267 writer_->PutC('C');
1268 writer_->PutC('[');
1269 writer_->PutInt(contexts.length());
1270 if (!contexts.is_empty()) {
1271 Object** start = reinterpret_cast<Object**>(&contexts.first());
1272 VisitPointers(start, start + contexts.length());
1273 }
1274 writer_->PutC(']');
1275 }
1276
1277 void Serializer::PutEncodedAddress(Address addr) {
1278 writer_->PutC('P');
1279 writer_->PutAddress(addr);
1280 }
1281
1282
1283 Address Serializer::Encode(Object* o, bool* serialized) {
1284 *serialized = false;
1285 if (o->IsSmi()) {
1286 return reinterpret_cast<Address>(o);
1287 } else {
1288 HeapObject* obj = HeapObject::cast(o);
1289 if (IsVisited(obj)) {
1290 return GetSavedAddress(obj);
1291 } else {
1292 // First visit: serialize the object.
1293 *serialized = true;
1294 return PutObject(obj);
1295 }
1296 }
1297 }
1298
1299
1300 Address Serializer::PutObject(HeapObject* obj) {
1301 Map* map = obj->map();
1302 InstanceType type = map->instance_type();
1303 int size = obj->SizeFromMap(map);
1304
1305 // Simulate the allocation of obj to predict where it will be
1306 // allocated during deserialization.
1307 Address addr = Allocate(obj).Encode();
1308
1309 SaveAddress(obj, addr);
1310
1311 if (type == CODE_TYPE) {
1312 LOG(CodeMoveEvent(obj->address(), addr));
1313 }
1314
1315 // Write out the object prologue: type, size, and simulated address of obj.
1316 writer_->PutC('[');
1317 CHECK_EQ(0, static_cast<int>(size & kObjectAlignmentMask));
1318 writer_->PutInt(type);
1319 writer_->PutInt(size >> kObjectAlignmentBits);
1320 PutEncodedAddress(addr); // encodes AllocationSpace
1321
1322 // Visit all the pointers in the object other than the map. This
1323 // will recursively serialize any as-yet-unvisited objects.
1324 obj->Iterate(this);
1325
1326 // Mark end of recursively embedded objects, start of object body.
1327 writer_->PutC('|');
1328 // Write out the raw contents of the object. No compression, but
1329 // fast to deserialize.
1330 writer_->PutBytes(obj->address(), size);
1331 // Update pointers and external references in the written object.
1332 ReferenceUpdater updater(obj, this);
1333 obj->Iterate(&updater);
1334 updater.Update(writer_->position() - size);
1335
1336 #ifdef DEBUG
1337 if (FLAG_debug_serialization) {
1338 // Write out the object epilogue to catch synchronization errors.
1339 PutEncodedAddress(addr);
1340 writer_->PutC(']');
1341 }
1342 #endif
1343
1344 objects_++;
1345 return addr;
1346 }
1347
1348
1349 RelativeAddress Serializer::Allocate(HeapObject* obj) {
1350 // Find out which AllocationSpace 'obj' is in.
1351 AllocationSpace s;
1352 bool found = false;
1353 for (int i = FIRST_SPACE; !found && i <= LAST_SPACE; i++) {
1354 s = static_cast<AllocationSpace>(i);
1355 found = Heap::InSpace(obj, s);
1356 }
1357 CHECK(found);
1358 int size = obj->Size();
1359 if (s == NEW_SPACE) {
1360 if (size > Heap::MaxObjectSizeInPagedSpace()) {
1361 s = LO_SPACE;
1362 } else {
1363 OldSpace* space = Heap::TargetSpace(obj);
1364 ASSERT(space == Heap::old_pointer_space() ||
1365 space == Heap::old_data_space());
1366 s = (space == Heap::old_pointer_space()) ?
1367 OLD_POINTER_SPACE :
1368 OLD_DATA_SPACE;
1369 }
1370 }
1371 GCTreatment gc_treatment = DataObject;
1372 if (obj->IsFixedArray()) gc_treatment = PointerObject;
1373 else if (obj->IsCode()) gc_treatment = CodeObject;
1374 return allocator_[s]->Allocate(size, gc_treatment);
1375 }
1376
1377
1378 //------------------------------------------------------------------------------
1379 // Implementation of Deserializer
1380
1381
1382 static const int kInitArraySize = 32;
1383
1384
1385 Deserializer::Deserializer(const byte* str, int len)
1386 : reader_(str, len),
1387 map_pages_(kInitArraySize),
1388 cell_pages_(kInitArraySize),
1389 old_pointer_pages_(kInitArraySize),
1390 old_data_pages_(kInitArraySize),
1391 code_pages_(kInitArraySize),
1392 large_objects_(kInitArraySize),
1393 global_handles_(4) {
1394 root_ = true;
1395 roots_ = 0;
1396 objects_ = 0;
1397 reference_decoder_ = NULL;
1398 #ifdef DEBUG
1399 expect_debug_information_ = false;
1400 #endif
1401 }
1402
1403
1404 Deserializer::~Deserializer() {
1405 if (reference_decoder_) delete reference_decoder_;
1406 }
1407
1408
1409 void Deserializer::ExpectEncodedAddress(Address expected) {
1410 Address a = GetEncodedAddress();
1411 USE(a);
1412 ASSERT(a == expected);
1413 }
1414
1415
1416 #ifdef DEBUG
1417 void Deserializer::Synchronize(const char* tag) {
1418 if (expect_debug_information_) {
1419 char buf[kMaxTagLength];
1420 reader_.ExpectC('S');
1421 int length = reader_.GetInt();
1422 ASSERT(length <= kMaxTagLength);
1423 reader_.GetBytes(reinterpret_cast<Address>(buf), length);
1424 ASSERT_EQ(StrLength(tag), length);
1425 ASSERT(strncmp(tag, buf, length) == 0);
1426 }
1427 }
1428 #endif
1429
1430
1431 class NoGlobalHandlesChecker : public ObjectVisitor {
1432 public:
1433 virtual void VisitPointers(Object** start, Object** end) {
1434 ASSERT(false);
1435 }
1436 };
1437
1438
1439 class GlobalHandleDestroyer : public ObjectVisitor {
1440 void VisitPointers(Object**start, Object**end) {
1441 while (start < end) {
1442 GlobalHandles::Destroy(start++);
1443 }
1444 }
1445 };
1446
1447
1448 void Deserializer::Deserialize() {
1449 // No global handles.
1450 NoGlobalHandlesChecker checker;
1451 GlobalHandles::IterateStrongRoots(&checker);
1452 // No active threads.
1453 ASSERT_EQ(NULL, ThreadState::FirstInUse());
1454 // No active handles.
1455 ASSERT(HandleScopeImplementer::instance()->blocks()->is_empty());
1456 reference_decoder_ = new ExternalReferenceDecoder();
1457 // By setting linear allocation only, we forbid the use of free list
1458 // allocation which is not predicted by SimulatedAddress.
1459 GetHeader();
1460 Heap::IterateRoots(this, VISIT_ONLY_STRONG);
1461 GetContextStack();
1462 // Any global handles that have been set up by deserialization are leaked
1463 // since noone is keeping track of them. So we discard them now.
1464 GlobalHandleDestroyer destroyer;
1465 GlobalHandles::IterateStrongRoots(&destroyer);
1466 }
1467
1468
1469 void Deserializer::VisitPointers(Object** start, Object** end) {
1470 bool root = root_;
1471 root_ = false;
1472 for (Object** p = start; p < end; ++p) {
1473 if (root) {
1474 roots_++;
1475 // Read the next object or pointer from the stream
1476 // pointer in the stream.
1477 int c = reader_.GetC();
1478 if (c == '[') {
1479 *p = GetObject(); // embedded object
1480 } else {
1481 ASSERT(c == 'P'); // pointer to previously serialized object
1482 *p = Resolve(reader_.GetAddress());
1483 }
1484 } else {
1485 // A pointer internal to a HeapObject that we've already
1486 // read: resolve it to a true address (or Smi)
1487 *p = Resolve(reinterpret_cast<Address>(*p));
1488 }
1489 }
1490 root_ = root;
1491 }
1492
1493
1494 void Deserializer::VisitCodeTarget(RelocInfo* rinfo) {
1495 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
1496 // On all platforms, the encoded code object address is only 32 bits.
1497 Address encoded_address = reinterpret_cast<Address>(Memory::uint32_at(
1498 reinterpret_cast<Address>(rinfo->target_object_address())));
1499 Code* target_object = reinterpret_cast<Code*>(Resolve(encoded_address));
1500 rinfo->set_target_address(target_object->instruction_start());
1501 }
1502
1503
1504 void Deserializer::VisitExternalReferences(Address* start, Address* end) {
1505 for (Address* p = start; p < end; ++p) {
1506 uint32_t code = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(*p));
1507 *p = reference_decoder_->Decode(code);
1508 }
1509 }
1510
1511
1512 void Deserializer::VisitRuntimeEntry(RelocInfo* rinfo) {
1513 uint32_t* pc = reinterpret_cast<uint32_t*>(rinfo->target_address_address());
1514 uint32_t encoding = *pc;
1515 Address target = reference_decoder_->Decode(encoding);
1516 rinfo->set_target_address(target);
1517 }
1518
1519
1520 void Deserializer::GetFlags() {
1521 reader_.ExpectC('F');
1522 int argc = reader_.GetInt() + 1;
1523 char** argv = NewArray<char*>(argc);
1524 reader_.ExpectC('[');
1525 for (int i = 1; i < argc; i++) {
1526 if (i > 1) reader_.ExpectC('|');
1527 argv[i] = reader_.GetString();
1528 }
1529 reader_.ExpectC(']');
1530 has_log_ = false;
1531 for (int i = 1; i < argc; i++) {
1532 if (strcmp("--log_code", argv[i]) == 0) {
1533 has_log_ = true;
1534 } else if (strcmp("--nouse_ic", argv[i]) == 0) {
1535 FLAG_use_ic = false;
1536 } else if (strcmp("--debug_code", argv[i]) == 0) {
1537 FLAG_debug_code = true;
1538 } else if (strcmp("--nolazy", argv[i]) == 0) {
1539 FLAG_lazy = false;
1540 }
1541 DeleteArray(argv[i]);
1542 }
1543
1544 DeleteArray(argv);
1545 }
1546
1547
1548 void Deserializer::GetLog() {
1549 if (has_log_) {
1550 reader_.ExpectC('L');
1551 char* snapshot_log = reader_.GetString();
1552 #ifdef ENABLE_LOGGING_AND_PROFILING
1553 if (FLAG_log_code) {
1554 LOG(Preamble(snapshot_log));
1555 }
1556 #endif
1557 DeleteArray(snapshot_log);
1558 }
1559 }
1560
1561
1562 static void InitPagedSpace(PagedSpace* space,
1563 int capacity,
1564 List<Page*>* page_list) {
1565 if (!space->EnsureCapacity(capacity)) {
1566 V8::FatalProcessOutOfMemory("InitPagedSpace");
1567 }
1568 PageIterator it(space, PageIterator::ALL_PAGES);
1569 while (it.has_next()) page_list->Add(it.next());
1570 }
1571
1572
1573 void Deserializer::GetHeader() {
1574 reader_.ExpectC('D');
1575 #ifdef DEBUG
1576 expect_debug_information_ = reader_.GetC() == '1';
1577 #else
1578 // In release mode, don't attempt to read a snapshot containing
1579 // synchronization tags.
1580 if (reader_.GetC() != '0') FATAL("Snapshot contains synchronization tags.");
1581 #endif
1582 #ifdef V8_NATIVE_REGEXP
1583 reader_.ExpectC('N');
1584 #else // Interpreted regexp.
1585 reader_.ExpectC('I');
1586 #endif
1587 // Ensure sufficient capacity in paged memory spaces to avoid growth
1588 // during deserialization.
1589 reader_.ExpectC('S');
1590 reader_.ExpectC('[');
1591 InitPagedSpace(Heap::old_pointer_space(),
1592 reader_.GetInt(),
1593 &old_pointer_pages_);
1594 reader_.ExpectC('|');
1595 InitPagedSpace(Heap::old_data_space(), reader_.GetInt(), &old_data_pages_);
1596 reader_.ExpectC('|');
1597 InitPagedSpace(Heap::code_space(), reader_.GetInt(), &code_pages_);
1598 reader_.ExpectC('|');
1599 InitPagedSpace(Heap::map_space(), reader_.GetInt(), &map_pages_);
1600 reader_.ExpectC('|');
1601 InitPagedSpace(Heap::cell_space(), reader_.GetInt(), &cell_pages_);
1602 reader_.ExpectC(']');
1603 // Create placeholders for global handles later to be fill during
1604 // IterateRoots.
1605 reader_.ExpectC('G');
1606 reader_.ExpectC('[');
1607 int c = reader_.GetC();
1608 while (c != ']') {
1609 ASSERT(c == 'N');
1610 global_handles_.Add(GlobalHandles::Create(NULL).location());
1611 c = reader_.GetC();
1612 }
1613 }
1614
1615
1616 void Deserializer::GetGlobalHandleStack(List<Handle<Object> >* stack) {
1617 reader_.ExpectC('[');
1618 int length = reader_.GetInt();
1619 for (int i = 0; i < length; i++) {
1620 reader_.ExpectC('|');
1621 int gh_index = reader_.GetInt();
1622 stack->Add(global_handles_[gh_index]);
1623 }
1624 reader_.ExpectC(']');
1625 }
1626
1627
1628 void Deserializer::GetContextStack() {
1629 reader_.ExpectC('C');
1630 CHECK_EQ(reader_.GetC(), '[');
1631 int count = reader_.GetInt();
1632 List<Context*> entered_contexts(count);
1633 if (count > 0) {
1634 Object** start = reinterpret_cast<Object**>(&entered_contexts.first());
1635 VisitPointers(start, start + count);
1636 }
1637 reader_.ExpectC(']');
1638 for (int i = 0; i < count; i++) {
1639 HandleScopeImplementer::instance()->SaveContext(entered_contexts[i]);
1640 }
1641 }
1642
1643
1644 Address Deserializer::GetEncodedAddress() {
1645 reader_.ExpectC('P');
1646 return reader_.GetAddress();
1647 }
1648
1649
1650 Object* Deserializer::GetObject() {
1651 // Read the prologue: type, size and encoded address.
1652 InstanceType type = static_cast<InstanceType>(reader_.GetInt());
1653 int size = reader_.GetInt() << kObjectAlignmentBits;
1654 Address a = GetEncodedAddress();
1655
1656 // Get a raw object of the right size in the right space.
1657 AllocationSpace space = GetSpace(a);
1658 Object* o;
1659 if (IsLargeExecutableObject(a)) {
1660 o = Heap::lo_space()->AllocateRawCode(size);
1661 } else if (IsLargeFixedArray(a)) {
1662 o = Heap::lo_space()->AllocateRawFixedArray(size);
1663 } else {
1664 AllocationSpace retry_space = (space == NEW_SPACE)
1665 ? Heap::TargetSpaceId(type)
1666 : space;
1667 o = Heap::AllocateRaw(size, space, retry_space);
1668 }
1669 ASSERT(!o->IsFailure());
1670 // Check that the simulation of heap allocation was correct.
1671 ASSERT(o == Resolve(a));
1672
1673 // Read any recursively embedded objects.
1674 int c = reader_.GetC();
1675 while (c == '[') {
1676 GetObject();
1677 c = reader_.GetC();
1678 }
1679 ASSERT(c == '|');
1680
1681 HeapObject* obj = reinterpret_cast<HeapObject*>(o);
1682 // Read the uninterpreted contents of the object after the map
1683 reader_.GetBytes(obj->address(), size);
1684 #ifdef DEBUG
1685 if (expect_debug_information_) {
1686 // Read in the epilogue to check that we're still synchronized
1687 ExpectEncodedAddress(a);
1688 reader_.ExpectC(']');
1689 }
1690 #endif
1691
1692 // Resolve the encoded pointers we just read in.
1693 // Same as obj->Iterate(this), but doesn't rely on the map pointer being set.
1694 VisitPointer(reinterpret_cast<Object**>(obj->address()));
1695 obj->IterateBody(type, size, this);
1696
1697 if (type == CODE_TYPE) {
1698 LOG(CodeMoveEvent(a, obj->address()));
1699 }
1700 objects_++;
1701 return o;
1702 }
1703
1704
1705 static inline Object* ResolvePaged(int page_index,
1706 int page_offset,
1707 PagedSpace* space,
1708 List<Page*>* page_list) {
1709 ASSERT(page_index < page_list->length());
1710 Address address = (*page_list)[page_index]->OffsetToAddress(page_offset);
1711 return HeapObject::FromAddress(address);
1712 }
1713
1714
1715 template<typename T>
1716 void ConcatReversed(List<T>* target, const List<T>& source) {
1717 for (int i = source.length() - 1; i >= 0; i--) {
1718 target->Add(source[i]);
1719 }
1720 }
1721
1722
1723 Object* Deserializer::Resolve(Address encoded) {
1724 Object* o = reinterpret_cast<Object*>(encoded);
1725 if (o->IsSmi()) return o;
1726
1727 // Encoded addresses of HeapObjects always have 'HeapObject' tags.
1728 ASSERT(o->IsHeapObject());
1729 switch (GetSpace(encoded)) {
1730 // For Map space and Old space, we cache the known Pages in map_pages,
1731 // old_pointer_pages and old_data_pages. Even though MapSpace keeps a list
1732 // of page addresses, we don't rely on it since GetObject uses AllocateRaw,
1733 // and that appears not to update the page list.
1734 case MAP_SPACE:
1735 return ResolvePaged(PageIndex(encoded), PageOffset(encoded),
1736 Heap::map_space(), &map_pages_);
1737 case CELL_SPACE:
1738 return ResolvePaged(PageIndex(encoded), PageOffset(encoded),
1739 Heap::cell_space(), &cell_pages_);
1740 case OLD_POINTER_SPACE:
1741 return ResolvePaged(PageIndex(encoded), PageOffset(encoded),
1742 Heap::old_pointer_space(), &old_pointer_pages_);
1743 case OLD_DATA_SPACE:
1744 return ResolvePaged(PageIndex(encoded), PageOffset(encoded),
1745 Heap::old_data_space(), &old_data_pages_);
1746 case CODE_SPACE:
1747 return ResolvePaged(PageIndex(encoded), PageOffset(encoded),
1748 Heap::code_space(), &code_pages_);
1749 case NEW_SPACE:
1750 return HeapObject::FromAddress(Heap::NewSpaceStart() +
1751 NewSpaceOffset(encoded));
1752 case LO_SPACE:
1753 // Cache the known large_objects, allocated one per 'page'
1754 int index = LargeObjectIndex(encoded);
1755 if (index >= large_objects_.length()) {
1756 int new_object_count =
1757 Heap::lo_space()->PageCount() - large_objects_.length();
1758 List<Object*> new_objects(new_object_count);
1759 LargeObjectIterator it(Heap::lo_space());
1760 for (int i = 0; i < new_object_count; i++) {
1761 new_objects.Add(it.next());
1762 }
1763 #ifdef DEBUG
1764 for (int i = large_objects_.length() - 1; i >= 0; i--) {
1765 ASSERT(it.next() == large_objects_[i]);
1766 }
1767 #endif
1768 ConcatReversed(&large_objects_, new_objects);
1769 ASSERT(index < large_objects_.length());
1770 }
1771 return large_objects_[index]; // s.page_offset() is ignored.
1772 }
1773 UNREACHABLE();
1774 return NULL;
1775 }
1776
1777
1778 Deserializer2::Deserializer2(SnapshotByteSource* source)
1779 : source_(source), 493 : source_(source),
1780 external_reference_decoder_(NULL) { 494 external_reference_decoder_(NULL) {
1781 } 495 }
1782 496
1783 497
1784 // This routine both allocates a new object, and also keeps 498 // This routine both allocates a new object, and also keeps
1785 // track of where objects have been allocated so that we can 499 // track of where objects have been allocated so that we can
1786 // fix back references when deserializing. 500 // fix back references when deserializing.
1787 Address Deserializer2::Allocate(int space_index, Space* space, int size) { 501 Address Deserializer::Allocate(int space_index, Space* space, int size) {
1788 Address address; 502 Address address;
1789 if (!SpaceIsLarge(space_index)) { 503 if (!SpaceIsLarge(space_index)) {
1790 ASSERT(!SpaceIsPaged(space_index) || 504 ASSERT(!SpaceIsPaged(space_index) ||
1791 size <= Page::kPageSize - Page::kObjectStartOffset); 505 size <= Page::kPageSize - Page::kObjectStartOffset);
1792 Object* new_allocation; 506 Object* new_allocation;
1793 if (space_index == NEW_SPACE) { 507 if (space_index == NEW_SPACE) {
1794 new_allocation = reinterpret_cast<NewSpace*>(space)->AllocateRaw(size); 508 new_allocation = reinterpret_cast<NewSpace*>(space)->AllocateRaw(size);
1795 } else { 509 } else {
1796 new_allocation = reinterpret_cast<PagedSpace*>(space)->AllocateRaw(size); 510 new_allocation = reinterpret_cast<PagedSpace*>(space)->AllocateRaw(size);
1797 } 511 }
(...skipping 20 matching lines...) Expand all
1818 address = new_object->address(); 532 address = new_object->address();
1819 high_water_[LO_SPACE] = address + size; 533 high_water_[LO_SPACE] = address + size;
1820 } 534 }
1821 last_object_address_ = address; 535 last_object_address_ = address;
1822 return address; 536 return address;
1823 } 537 }
1824 538
1825 539
1826 // This returns the address of an object that has been described in the 540 // This returns the address of an object that has been described in the
1827 // snapshot as being offset bytes back in a particular space. 541 // snapshot as being offset bytes back in a particular space.
1828 HeapObject* Deserializer2::GetAddressFromEnd(int space) { 542 HeapObject* Deserializer::GetAddressFromEnd(int space) {
1829 int offset = source_->GetInt(); 543 int offset = source_->GetInt();
1830 ASSERT(!SpaceIsLarge(space)); 544 ASSERT(!SpaceIsLarge(space));
1831 offset <<= kObjectAlignmentBits; 545 offset <<= kObjectAlignmentBits;
1832 return HeapObject::FromAddress(high_water_[space] - offset); 546 return HeapObject::FromAddress(high_water_[space] - offset);
1833 } 547 }
1834 548
1835 549
1836 // This returns the address of an object that has been described in the 550 // This returns the address of an object that has been described in the
1837 // snapshot as being offset bytes into a particular space. 551 // snapshot as being offset bytes into a particular space.
1838 HeapObject* Deserializer2::GetAddressFromStart(int space) { 552 HeapObject* Deserializer::GetAddressFromStart(int space) {
1839 int offset = source_->GetInt(); 553 int offset = source_->GetInt();
1840 if (SpaceIsLarge(space)) { 554 if (SpaceIsLarge(space)) {
1841 // Large spaces have one object per 'page'. 555 // Large spaces have one object per 'page'.
1842 return HeapObject::FromAddress(pages_[LO_SPACE][offset]); 556 return HeapObject::FromAddress(pages_[LO_SPACE][offset]);
1843 } 557 }
1844 offset <<= kObjectAlignmentBits; 558 offset <<= kObjectAlignmentBits;
1845 if (space == NEW_SPACE) { 559 if (space == NEW_SPACE) {
1846 // New space has only one space - numbered 0. 560 // New space has only one space - numbered 0.
1847 return HeapObject::FromAddress(pages_[space][0] + offset); 561 return HeapObject::FromAddress(pages_[space][0] + offset);
1848 } 562 }
1849 ASSERT(SpaceIsPaged(space)); 563 ASSERT(SpaceIsPaged(space));
1850 int page_of_pointee = offset >> Page::kPageSizeBits; 564 int page_of_pointee = offset >> Page::kPageSizeBits;
1851 Address object_address = pages_[space][page_of_pointee] + 565 Address object_address = pages_[space][page_of_pointee] +
1852 (offset & Page::kPageAlignmentMask); 566 (offset & Page::kPageAlignmentMask);
1853 return HeapObject::FromAddress(object_address); 567 return HeapObject::FromAddress(object_address);
1854 } 568 }
1855 569
1856 570
1857 void Deserializer2::Deserialize() { 571 void Deserializer::Deserialize() {
1858 // Don't GC while deserializing - just expand the heap. 572 // Don't GC while deserializing - just expand the heap.
1859 AlwaysAllocateScope always_allocate; 573 AlwaysAllocateScope always_allocate;
1860 // Don't use the free lists while deserializing. 574 // Don't use the free lists while deserializing.
1861 LinearAllocationScope allocate_linearly; 575 LinearAllocationScope allocate_linearly;
1862 // No active threads. 576 // No active threads.
1863 ASSERT_EQ(NULL, ThreadState::FirstInUse()); 577 ASSERT_EQ(NULL, ThreadState::FirstInUse());
1864 // No active handles. 578 // No active handles.
1865 ASSERT(HandleScopeImplementer::instance()->blocks()->is_empty()); 579 ASSERT(HandleScopeImplementer::instance()->blocks()->is_empty());
1866 ASSERT(external_reference_decoder_ == NULL); 580 ASSERT(external_reference_decoder_ == NULL);
1867 external_reference_decoder_ = new ExternalReferenceDecoder(); 581 external_reference_decoder_ = new ExternalReferenceDecoder();
1868 Heap::IterateRoots(this, VISIT_ONLY_STRONG); 582 Heap::IterateRoots(this, VISIT_ONLY_STRONG);
1869 ASSERT(source_->AtEOF()); 583 ASSERT(source_->AtEOF());
1870 delete external_reference_decoder_; 584 delete external_reference_decoder_;
1871 external_reference_decoder_ = NULL; 585 external_reference_decoder_ = NULL;
1872 } 586 }
1873 587
1874 588
1875 // This is called on the roots. It is the driver of the deserialization 589 // This is called on the roots. It is the driver of the deserialization
1876 // process. It is also called on the body of each function. 590 // process. It is also called on the body of each function.
1877 void Deserializer2::VisitPointers(Object** start, Object** end) { 591 void Deserializer::VisitPointers(Object** start, Object** end) {
1878 // The space must be new space. Any other space would cause ReadChunk to try 592 // The space must be new space. Any other space would cause ReadChunk to try
1879 // to update the remembered using NULL as the address. 593 // to update the remembered using NULL as the address.
1880 ReadChunk(start, end, NEW_SPACE, NULL); 594 ReadChunk(start, end, NEW_SPACE, NULL);
1881 } 595 }
1882 596
1883 597
1884 // This routine writes the new object into the pointer provided and then 598 // This routine writes the new object into the pointer provided and then
1885 // returns true if the new object was in young space and false otherwise. 599 // returns true if the new object was in young space and false otherwise.
1886 // The reason for this strange interface is that otherwise the object is 600 // The reason for this strange interface is that otherwise the object is
1887 // written very late, which means the ByteArray map is not set up by the 601 // written very late, which means the ByteArray map is not set up by the
1888 // time we need to use it to mark the space at the end of a page free (by 602 // time we need to use it to mark the space at the end of a page free (by
1889 // making it into a byte array). 603 // making it into a byte array).
1890 void Deserializer2::ReadObject(int space_number, 604 void Deserializer::ReadObject(int space_number,
1891 Space* space, 605 Space* space,
1892 Object** write_back) { 606 Object** write_back) {
1893 int size = source_->GetInt() << kObjectAlignmentBits; 607 int size = source_->GetInt() << kObjectAlignmentBits;
1894 Address address = Allocate(space_number, space, size); 608 Address address = Allocate(space_number, space, size);
1895 *write_back = HeapObject::FromAddress(address); 609 *write_back = HeapObject::FromAddress(address);
1896 Object** current = reinterpret_cast<Object**>(address); 610 Object** current = reinterpret_cast<Object**>(address);
1897 Object** limit = current + (size >> kPointerSizeLog2); 611 Object** limit = current + (size >> kPointerSizeLog2);
1898 ReadChunk(current, limit, space_number, address); 612 ReadChunk(current, limit, space_number, address);
1899 } 613 }
1900 614
1901 615
1902 #define ONE_CASE_PER_SPACE(base_tag) \ 616 #define ONE_CASE_PER_SPACE(base_tag) \
1903 case (base_tag) + NEW_SPACE: /* NOLINT */ \ 617 case (base_tag) + NEW_SPACE: /* NOLINT */ \
1904 case (base_tag) + OLD_POINTER_SPACE: /* NOLINT */ \ 618 case (base_tag) + OLD_POINTER_SPACE: /* NOLINT */ \
1905 case (base_tag) + OLD_DATA_SPACE: /* NOLINT */ \ 619 case (base_tag) + OLD_DATA_SPACE: /* NOLINT */ \
1906 case (base_tag) + CODE_SPACE: /* NOLINT */ \ 620 case (base_tag) + CODE_SPACE: /* NOLINT */ \
1907 case (base_tag) + MAP_SPACE: /* NOLINT */ \ 621 case (base_tag) + MAP_SPACE: /* NOLINT */ \
1908 case (base_tag) + CELL_SPACE: /* NOLINT */ \ 622 case (base_tag) + CELL_SPACE: /* NOLINT */ \
1909 case (base_tag) + kLargeData: /* NOLINT */ \ 623 case (base_tag) + kLargeData: /* NOLINT */ \
1910 case (base_tag) + kLargeCode: /* NOLINT */ \ 624 case (base_tag) + kLargeCode: /* NOLINT */ \
1911 case (base_tag) + kLargeFixedArray: /* NOLINT */ 625 case (base_tag) + kLargeFixedArray: /* NOLINT */
1912 626
1913 627
1914 void Deserializer2::ReadChunk(Object** current, 628 void Deserializer::ReadChunk(Object** current,
1915 Object** limit, 629 Object** limit,
1916 int space, 630 int space,
1917 Address address) { 631 Address address) {
1918 while (current < limit) { 632 while (current < limit) {
1919 int data = source_->Get(); 633 int data = source_->Get();
1920 switch (data) { 634 switch (data) {
1921 #define RAW_CASE(index, size) \ 635 #define RAW_CASE(index, size) \
1922 case RAW_DATA_SERIALIZATION + index: { \ 636 case RAW_DATA_SERIALIZATION + index: { \
1923 byte* raw_data_out = reinterpret_cast<byte*>(current); \ 637 byte* raw_data_out = reinterpret_cast<byte*>(current); \
1924 source_->CopyRaw(raw_data_out, size); \ 638 source_->CopyRaw(raw_data_out, size); \
1925 current = reinterpret_cast<Object**>(raw_data_out + size); \ 639 current = reinterpret_cast<Object**>(raw_data_out + size); \
1926 break; \ 640 break; \
1927 } 641 }
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
2094 for (int shift = max_shift; shift > 0; shift -= 7) { 808 for (int shift = max_shift; shift > 0; shift -= 7) {
2095 if (integer >= static_cast<uintptr_t>(1u) << shift) { 809 if (integer >= static_cast<uintptr_t>(1u) << shift) {
2096 Put(((integer >> shift) & 0x7f) | 0x80, "IntPart"); 810 Put(((integer >> shift) & 0x7f) | 0x80, "IntPart");
2097 } 811 }
2098 } 812 }
2099 PutSection(integer & 0x7f, "IntLastPart"); 813 PutSection(integer & 0x7f, "IntLastPart");
2100 } 814 }
2101 815
2102 #ifdef DEBUG 816 #ifdef DEBUG
2103 817
2104 void Deserializer2::Synchronize(const char* tag) { 818 void Deserializer::Synchronize(const char* tag) {
2105 int data = source_->Get(); 819 int data = source_->Get();
2106 // If this assert fails then that indicates that you have a mismatch between 820 // If this assert fails then that indicates that you have a mismatch between
2107 // the number of GC roots when serializing and deserializing. 821 // the number of GC roots when serializing and deserializing.
2108 ASSERT(data == SYNCHRONIZE); 822 CHECK(data == SYNCHRONIZE);
Christian Plesner Hansen 2009/11/13 13:43:36 Why is this not an ASSERT? Also CHECK_EQ?
2109 do { 823 do {
2110 int character = source_->Get(); 824 int character = source_->Get();
2111 if (character == 0) break; 825 if (character == 0) break;
2112 if (FLAG_debug_serialization) { 826 if (FLAG_debug_serialization) {
2113 PrintF("%c", character); 827 PrintF("%c", character);
2114 } 828 }
2115 } while (true); 829 } while (true);
2116 if (FLAG_debug_serialization) { 830 if (FLAG_debug_serialization) {
2117 PrintF("\n"); 831 PrintF("\n");
2118 } 832 }
2119 } 833 }
2120 834
2121 835
2122 void Serializer2::Synchronize(const char* tag) { 836 void Serializer::Synchronize(const char* tag) {
2123 sink_->Put(SYNCHRONIZE, tag); 837 sink_->Put(SYNCHRONIZE, tag);
2124 int character; 838 int character;
2125 do { 839 do {
2126 character = *tag++; 840 character = *tag++;
2127 sink_->PutSection(character, "TagCharacter"); 841 sink_->PutSection(character, "TagCharacter");
2128 } while (character != 0); 842 } while (character != 0);
2129 } 843 }
2130 844
2131 #endif 845 #endif
2132 846
2133 Serializer2::Serializer2(SnapshotByteSink* sink) 847 Serializer::Serializer(SnapshotByteSink* sink)
2134 : sink_(sink), 848 : sink_(sink),
2135 current_root_index_(0), 849 current_root_index_(0),
2136 external_reference_encoder_(NULL) { 850 external_reference_encoder_(NULL) {
2137 for (int i = 0; i <= LAST_SPACE; i++) { 851 for (int i = 0; i <= LAST_SPACE; i++) {
2138 fullness_[i] = 0; 852 fullness_[i] = 0;
2139 } 853 }
2140 } 854 }
2141 855
2142 856
2143 void Serializer2::Serialize() { 857 void Serializer::Serialize() {
2144 // No active threads. 858 // No active threads.
2145 CHECK_EQ(NULL, ThreadState::FirstInUse()); 859 CHECK_EQ(NULL, ThreadState::FirstInUse());
2146 // No active or weak handles. 860 // No active or weak handles.
2147 CHECK(HandleScopeImplementer::instance()->blocks()->is_empty()); 861 CHECK(HandleScopeImplementer::instance()->blocks()->is_empty());
2148 CHECK_EQ(0, GlobalHandles::NumberOfWeakHandles()); 862 CHECK_EQ(0, GlobalHandles::NumberOfWeakHandles());
2149 ASSERT(external_reference_encoder_ == NULL); 863 ASSERT(external_reference_encoder_ == NULL);
2150 external_reference_encoder_ = new ExternalReferenceEncoder(); 864 external_reference_encoder_ = new ExternalReferenceEncoder();
2151 Heap::IterateRoots(this, VISIT_ONLY_STRONG); 865 Heap::IterateRoots(this, VISIT_ONLY_STRONG);
2152 delete external_reference_encoder_; 866 delete external_reference_encoder_;
2153 external_reference_encoder_ = NULL; 867 external_reference_encoder_ = NULL;
2154 } 868 }
2155 869
2156 870
2157 void Serializer2::VisitPointers(Object** start, Object** end) { 871 void Serializer::VisitPointers(Object** start, Object** end) {
2158 for (Object** current = start; current < end; current++) { 872 for (Object** current = start; current < end; current++) {
2159 if ((*current)->IsSmi()) { 873 if ((*current)->IsSmi()) {
2160 sink_->Put(RAW_DATA_SERIALIZATION, "RawData"); 874 sink_->Put(RAW_DATA_SERIALIZATION, "RawData");
2161 sink_->PutInt(kPointerSize, "length"); 875 sink_->PutInt(kPointerSize, "length");
2162 for (int i = 0; i < kPointerSize; i++) { 876 for (int i = 0; i < kPointerSize; i++) {
2163 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); 877 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte");
2164 } 878 }
2165 } else { 879 } else {
2166 SerializeObject(*current, TAGGED_REPRESENTATION); 880 SerializeObject(*current, TAGGED_REPRESENTATION);
2167 } 881 }
2168 } 882 }
2169 } 883 }
2170 884
2171 885
2172 void Serializer2::SerializeObject( 886 void Serializer::SerializeObject(
2173 Object* o, 887 Object* o,
2174 ReferenceRepresentation reference_representation) { 888 ReferenceRepresentation reference_representation) {
2175 ASSERT(o->IsHeapObject()); 889 ASSERT(o->IsHeapObject());
2176 HeapObject* heap_object = HeapObject::cast(o); 890 HeapObject* heap_object = HeapObject::cast(o);
2177 MapWord map_word = heap_object->map_word(); 891 MapWord map_word = heap_object->map_word();
2178 if (map_word.IsSerializationAddress()) { 892 if (map_word.IsSerializationAddress()) {
2179 int space = SpaceOfAlreadySerializedObject(heap_object); 893 int space = SpaceOfAlreadySerializedObject(heap_object);
2180 int address = map_word.ToSerializationAddress(); 894 int address = map_word.ToSerializationAddress();
2181 int offset = CurrentAllocationAddress(space) - address; 895 int offset = CurrentAllocationAddress(space) - address;
2182 bool from_start = true; 896 bool from_start = true;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2226 ObjectSerializer serializer(this, 940 ObjectSerializer serializer(this,
2227 heap_object, 941 heap_object,
2228 sink_, 942 sink_,
2229 reference_representation); 943 reference_representation);
2230 serializer.Serialize(); 944 serializer.Serialize();
2231 } 945 }
2232 } 946 }
2233 947
2234 948
2235 949
2236 void Serializer2::ObjectSerializer::Serialize() { 950 void Serializer::ObjectSerializer::Serialize() {
2237 int space = Serializer2::SpaceOfObject(object_); 951 int space = Serializer::SpaceOfObject(object_);
2238 int size = object_->Size(); 952 int size = object_->Size();
2239 953
2240 if (reference_representation_ == TAGGED_REPRESENTATION) { 954 if (reference_representation_ == TAGGED_REPRESENTATION) {
2241 sink_->Put(OBJECT_SERIALIZATION + space, "ObjectSerialization"); 955 sink_->Put(OBJECT_SERIALIZATION + space, "ObjectSerialization");
2242 } else { 956 } else {
2243 ASSERT(reference_representation_ == CODE_TARGET_REPRESENTATION); 957 ASSERT(reference_representation_ == CODE_TARGET_REPRESENTATION);
2244 sink_->Put(CODE_OBJECT_SERIALIZATION + space, "ObjectSerialization"); 958 sink_->Put(CODE_OBJECT_SERIALIZATION + space, "ObjectSerialization");
2245 } 959 }
2246 sink_->PutInt(size >> kObjectAlignmentBits, "Size in words"); 960 sink_->PutInt(size >> kObjectAlignmentBits, "Size in words");
2247 961
(...skipping 12 matching lines...) Expand all
2260 serializer_->SerializeObject(map, TAGGED_REPRESENTATION); 974 serializer_->SerializeObject(map, TAGGED_REPRESENTATION);
2261 975
2262 // Serialize the rest of the object. 976 // Serialize the rest of the object.
2263 ASSERT(bytes_processed_so_far_ == 0); 977 ASSERT(bytes_processed_so_far_ == 0);
2264 bytes_processed_so_far_ = kPointerSize; 978 bytes_processed_so_far_ = kPointerSize;
2265 object_->IterateBody(map->instance_type(), size, this); 979 object_->IterateBody(map->instance_type(), size, this);
2266 OutputRawData(object_->address() + size); 980 OutputRawData(object_->address() + size);
2267 } 981 }
2268 982
2269 983
2270 void Serializer2::ObjectSerializer::VisitPointers(Object** start, 984 void Serializer::ObjectSerializer::VisitPointers(Object** start,
2271 Object** end) { 985 Object** end) {
2272 Object** current = start; 986 Object** current = start;
2273 while (current < end) { 987 while (current < end) {
2274 while (current < end && (*current)->IsSmi()) current++; 988 while (current < end && (*current)->IsSmi()) current++;
2275 if (current < end) OutputRawData(reinterpret_cast<Address>(current)); 989 if (current < end) OutputRawData(reinterpret_cast<Address>(current));
2276 990
2277 while (current < end && !(*current)->IsSmi()) { 991 while (current < end && !(*current)->IsSmi()) {
2278 serializer_->SerializeObject(*current, TAGGED_REPRESENTATION); 992 serializer_->SerializeObject(*current, TAGGED_REPRESENTATION);
2279 bytes_processed_so_far_ += kPointerSize; 993 bytes_processed_so_far_ += kPointerSize;
2280 current++; 994 current++;
2281 } 995 }
2282 } 996 }
2283 } 997 }
2284 998
2285 999
2286 void Serializer2::ObjectSerializer::VisitExternalReferences(Address* start, 1000 void Serializer::ObjectSerializer::VisitExternalReferences(Address* start,
2287 Address* end) { 1001 Address* end) {
2288 Address references_start = reinterpret_cast<Address>(start); 1002 Address references_start = reinterpret_cast<Address>(start);
2289 OutputRawData(references_start); 1003 OutputRawData(references_start);
2290 1004
2291 for (Address* current = start; current < end; current++) { 1005 for (Address* current = start; current < end; current++) {
2292 sink_->Put(EXTERNAL_REFERENCE_SERIALIZATION, "ExternalReference"); 1006 sink_->Put(EXTERNAL_REFERENCE_SERIALIZATION, "ExternalReference");
2293 int reference_id = serializer_->EncodeExternalReference(*current); 1007 int reference_id = serializer_->EncodeExternalReference(*current);
2294 sink_->PutInt(reference_id, "reference id"); 1008 sink_->PutInt(reference_id, "reference id");
2295 } 1009 }
2296 bytes_processed_so_far_ += static_cast<int>((end - start) * kPointerSize); 1010 bytes_processed_so_far_ += static_cast<int>((end - start) * kPointerSize);
2297 } 1011 }
2298 1012
2299 1013
2300 void Serializer2::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) { 1014 void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) {
2301 Address target_start = rinfo->target_address_address(); 1015 Address target_start = rinfo->target_address_address();
2302 OutputRawData(target_start); 1016 OutputRawData(target_start);
2303 Address target = rinfo->target_address(); 1017 Address target = rinfo->target_address();
2304 uint32_t encoding = serializer_->EncodeExternalReference(target); 1018 uint32_t encoding = serializer_->EncodeExternalReference(target);
2305 CHECK(target == NULL ? encoding == 0 : encoding != 0); 1019 CHECK(target == NULL ? encoding == 0 : encoding != 0);
2306 sink_->Put(EXTERNAL_BRANCH_TARGET_SERIALIZATION, "ExternalReference"); 1020 sink_->Put(EXTERNAL_BRANCH_TARGET_SERIALIZATION, "ExternalReference");
2307 sink_->PutInt(encoding, "reference id"); 1021 sink_->PutInt(encoding, "reference id");
2308 bytes_processed_so_far_ += Assembler::kExternalTargetSize; 1022 bytes_processed_so_far_ += Assembler::kExternalTargetSize;
2309 } 1023 }
2310 1024
2311 1025
2312 void Serializer2::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) { 1026 void Serializer::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) {
2313 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); 1027 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
2314 Address target_start = rinfo->target_address_address(); 1028 Address target_start = rinfo->target_address_address();
2315 OutputRawData(target_start); 1029 OutputRawData(target_start);
2316 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); 1030 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
2317 serializer_->SerializeObject(target, CODE_TARGET_REPRESENTATION); 1031 serializer_->SerializeObject(target, CODE_TARGET_REPRESENTATION);
2318 bytes_processed_so_far_ += Assembler::kCallTargetSize; 1032 bytes_processed_so_far_ += Assembler::kCallTargetSize;
2319 } 1033 }
2320 1034
2321 1035
2322 void Serializer2::ObjectSerializer::VisitExternalAsciiString( 1036 void Serializer::ObjectSerializer::VisitExternalAsciiString(
2323 v8::String::ExternalAsciiStringResource** resource_pointer) { 1037 v8::String::ExternalAsciiStringResource** resource_pointer) {
2324 Address references_start = reinterpret_cast<Address>(resource_pointer); 1038 Address references_start = reinterpret_cast<Address>(resource_pointer);
2325 OutputRawData(references_start); 1039 OutputRawData(references_start);
2326 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { 1040 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
2327 // Use raw_unchecked when maps are munged. 1041 // Use raw_unchecked when maps are munged.
2328 Object* source = Heap::raw_unchecked_natives_source_cache()->get(i); 1042 Object* source = Heap::raw_unchecked_natives_source_cache()->get(i);
2329 if (!source->IsUndefined()) { 1043 if (!source->IsUndefined()) {
2330 // Don't use cast when maps are munged. 1044 // Don't use cast when maps are munged.
2331 ExternalAsciiString* string = 1045 ExternalAsciiString* string =
2332 reinterpret_cast<ExternalAsciiString*>(source); 1046 reinterpret_cast<ExternalAsciiString*>(source);
2333 typedef v8::String::ExternalAsciiStringResource Resource; 1047 typedef v8::String::ExternalAsciiStringResource Resource;
2334 Resource* resource = string->resource(); 1048 Resource* resource = string->resource();
2335 if (resource == *resource_pointer) { 1049 if (resource == *resource_pointer) {
2336 sink_->Put(NATIVES_STRING_RESOURCE, "NativesStringResource"); 1050 sink_->Put(NATIVES_STRING_RESOURCE, "NativesStringResource");
2337 sink_->PutSection(i, "NativesStringResourceEnd"); 1051 sink_->PutSection(i, "NativesStringResourceEnd");
2338 bytes_processed_so_far_ += sizeof(resource); 1052 bytes_processed_so_far_ += sizeof(resource);
2339 return; 1053 return;
2340 } 1054 }
2341 } 1055 }
2342 } 1056 }
2343 // One of the strings in the natives cache should match the resource. We 1057 // One of the strings in the natives cache should match the resource. We
2344 // can't serialize any other kinds of external strings. 1058 // can't serialize any other kinds of external strings.
2345 UNREACHABLE(); 1059 UNREACHABLE();
2346 } 1060 }
2347 1061
2348 1062
2349 void Serializer2::ObjectSerializer::OutputRawData(Address up_to) { 1063 void Serializer::ObjectSerializer::OutputRawData(Address up_to) {
2350 Address object_start = object_->address(); 1064 Address object_start = object_->address();
2351 int up_to_offset = static_cast<int>(up_to - object_start); 1065 int up_to_offset = static_cast<int>(up_to - object_start);
2352 int skipped = up_to_offset - bytes_processed_so_far_; 1066 int skipped = up_to_offset - bytes_processed_so_far_;
2353 // This assert will fail if the reloc info gives us the target_address_address 1067 // This assert will fail if the reloc info gives us the target_address_address
2354 // locations in a non-ascending order. Luckily that doesn't happen. 1068 // locations in a non-ascending order. Luckily that doesn't happen.
2355 ASSERT(skipped >= 0); 1069 ASSERT(skipped >= 0);
2356 if (skipped != 0) { 1070 if (skipped != 0) {
2357 Address base = object_start + bytes_processed_so_far_; 1071 Address base = object_start + bytes_processed_so_far_;
2358 #define RAW_CASE(index, length) \ 1072 #define RAW_CASE(index, length) \
2359 if (skipped == length) { \ 1073 if (skipped == length) { \
2360 sink_->PutSection(RAW_DATA_SERIALIZATION + index, "RawDataFixed"); \ 1074 sink_->PutSection(RAW_DATA_SERIALIZATION + index, "RawDataFixed"); \
2361 } else /* NOLINT */ 1075 } else /* NOLINT */
2362 COMMON_RAW_LENGTHS(RAW_CASE) 1076 COMMON_RAW_LENGTHS(RAW_CASE)
2363 #undef RAW_CASE 1077 #undef RAW_CASE
2364 { /* NOLINT */ 1078 { /* NOLINT */
2365 sink_->Put(RAW_DATA_SERIALIZATION, "RawData"); 1079 sink_->Put(RAW_DATA_SERIALIZATION, "RawData");
2366 sink_->PutInt(skipped, "length"); 1080 sink_->PutInt(skipped, "length");
2367 } 1081 }
2368 for (int i = 0; i < skipped; i++) { 1082 for (int i = 0; i < skipped; i++) {
2369 unsigned int data = base[i]; 1083 unsigned int data = base[i];
2370 sink_->PutSection(data, "Byte"); 1084 sink_->PutSection(data, "Byte");
2371 } 1085 }
2372 bytes_processed_so_far_ += skipped; 1086 bytes_processed_so_far_ += skipped;
2373 } 1087 }
2374 } 1088 }
2375 1089
2376 1090
2377 int Serializer2::SpaceOfObject(HeapObject* object) { 1091 int Serializer::SpaceOfObject(HeapObject* object) {
2378 for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) { 1092 for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
2379 AllocationSpace s = static_cast<AllocationSpace>(i); 1093 AllocationSpace s = static_cast<AllocationSpace>(i);
2380 if (Heap::InSpace(object, s)) { 1094 if (Heap::InSpace(object, s)) {
2381 if (i == LO_SPACE) { 1095 if (i == LO_SPACE) {
2382 if (object->IsCode()) { 1096 if (object->IsCode()) {
2383 return kLargeCode; 1097 return kLargeCode;
2384 } else if (object->IsFixedArray()) { 1098 } else if (object->IsFixedArray()) {
2385 return kLargeFixedArray; 1099 return kLargeFixedArray;
2386 } else { 1100 } else {
2387 return kLargeData; 1101 return kLargeData;
2388 } 1102 }
2389 } 1103 }
2390 return i; 1104 return i;
2391 } 1105 }
2392 } 1106 }
2393 UNREACHABLE(); 1107 UNREACHABLE();
2394 return 0; 1108 return 0;
2395 } 1109 }
2396 1110
2397 1111
2398 int Serializer2::SpaceOfAlreadySerializedObject(HeapObject* object) { 1112 int Serializer::SpaceOfAlreadySerializedObject(HeapObject* object) {
2399 for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) { 1113 for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
2400 AllocationSpace s = static_cast<AllocationSpace>(i); 1114 AllocationSpace s = static_cast<AllocationSpace>(i);
2401 if (Heap::InSpace(object, s)) { 1115 if (Heap::InSpace(object, s)) {
2402 return i; 1116 return i;
2403 } 1117 }
2404 } 1118 }
2405 UNREACHABLE(); 1119 UNREACHABLE();
2406 return 0; 1120 return 0;
2407 } 1121 }
2408 1122
2409 1123
2410 int Serializer2::Allocate(int space, int size, bool* new_page) { 1124 int Serializer::Allocate(int space, int size, bool* new_page) {
2411 ASSERT(space >= 0 && space < kNumberOfSpaces); 1125 ASSERT(space >= 0 && space < kNumberOfSpaces);
2412 if (SpaceIsLarge(space)) { 1126 if (SpaceIsLarge(space)) {
2413 // In large object space we merely number the objects instead of trying to 1127 // In large object space we merely number the objects instead of trying to
2414 // determine some sort of address. 1128 // determine some sort of address.
2415 *new_page = true; 1129 *new_page = true;
2416 return fullness_[LO_SPACE]++; 1130 return fullness_[LO_SPACE]++;
2417 } 1131 }
2418 *new_page = false; 1132 *new_page = false;
2419 if (fullness_[space] == 0) { 1133 if (fullness_[space] == 0) {
2420 *new_page = true; 1134 *new_page = true;
(...skipping 13 matching lines...) Expand all
2434 fullness_[space] = RoundUp(fullness_[space], Page::kPageSize); 1148 fullness_[space] = RoundUp(fullness_[space], Page::kPageSize);
2435 } 1149 }
2436 } 1150 }
2437 int allocation_address = fullness_[space]; 1151 int allocation_address = fullness_[space];
2438 fullness_[space] = allocation_address + size; 1152 fullness_[space] = allocation_address + size;
2439 return allocation_address; 1153 return allocation_address;
2440 } 1154 }
2441 1155
2442 1156
2443 } } // namespace v8::internal 1157 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698