OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 SnapshotByteSource(const byte* array, int length) | 163 SnapshotByteSource(const byte* array, int length) |
164 : data_(array), length_(length), position_(0) { } | 164 : data_(array), length_(length), position_(0) { } |
165 | 165 |
166 bool HasMore() { return position_ < length_; } | 166 bool HasMore() { return position_ < length_; } |
167 | 167 |
168 int Get() { | 168 int Get() { |
169 ASSERT(position_ < length_); | 169 ASSERT(position_ < length_); |
170 return data_[position_++]; | 170 return data_[position_++]; |
171 } | 171 } |
172 | 172 |
173 int32_t GetUnalignedInt() { | |
174 #if defined(V8_HOST_CAN_READ_UNALIGNED) && __BYTE_ORDER == __LITTLE_ENDIAN | |
175 int32_t answer; | |
176 ASSERT(position_ + sizeof(answer) <= length_ + 0u); | |
177 answer = *reinterpret_cast<const int32_t*>(data_ + position_); | |
178 #else | |
179 int32_t answer = data_[position_]; | |
180 answer |= data_[position_ + 1] << 8; | |
181 answer |= data_[position_ + 2] << 16; | |
182 answer |= data_[position_ + 3] << 24; | |
183 #endif | |
184 return answer; | |
185 } | |
186 | |
187 void Advance(int by) { position_ += by; } | |
188 | |
189 inline void CopyRaw(byte* to, int number_of_bytes); | 173 inline void CopyRaw(byte* to, int number_of_bytes); |
190 | 174 |
191 inline int GetInt(); | 175 inline int GetInt(); |
192 | 176 |
193 bool AtEOF(); | 177 bool AtEOF() { |
| 178 return position_ == length_; |
| 179 } |
194 | 180 |
195 int position() { return position_; } | 181 int position() { return position_; } |
196 | 182 |
197 private: | 183 private: |
198 const byte* data_; | 184 const byte* data_; |
199 int length_; | 185 int length_; |
200 int position_; | 186 int position_; |
201 }; | 187 }; |
202 | 188 |
203 | 189 |
| 190 #define COMMON_RAW_LENGTHS(f) \ |
| 191 f(1, 1) \ |
| 192 f(2, 2) \ |
| 193 f(3, 3) \ |
| 194 f(4, 4) \ |
| 195 f(5, 5) \ |
| 196 f(6, 6) \ |
| 197 f(7, 7) \ |
| 198 f(8, 8) \ |
| 199 f(9, 12) \ |
| 200 f(10, 16) \ |
| 201 f(11, 20) \ |
| 202 f(12, 24) \ |
| 203 f(13, 28) \ |
| 204 f(14, 32) \ |
| 205 f(15, 36) |
| 206 |
204 // The Serializer/Deserializer class is a common superclass for Serializer and | 207 // The Serializer/Deserializer class is a common superclass for Serializer and |
205 // Deserializer which is used to store common constants and methods used by | 208 // Deserializer which is used to store common constants and methods used by |
206 // both. | 209 // both. |
207 class SerializerDeserializer: public ObjectVisitor { | 210 class SerializerDeserializer: public ObjectVisitor { |
208 public: | 211 public: |
209 static void Iterate(ObjectVisitor* visitor); | 212 static void Iterate(ObjectVisitor* visitor); |
210 | 213 |
211 static int nop() { return kNop; } | |
212 | |
213 protected: | 214 protected: |
214 // Where the pointed-to object can be found: | 215 // Where the pointed-to object can be found: |
215 enum Where { | 216 enum Where { |
216 kNewObject = 0, // Object is next in snapshot. | 217 kNewObject = 0, // Object is next in snapshot. |
217 // 1-6 One per space. | 218 // 1-8 One per space. |
218 kRootArray = 0x9, // Object is found in root array. | 219 kRootArray = 0x9, // Object is found in root array. |
219 kPartialSnapshotCache = 0xa, // Object is in the cache. | 220 kPartialSnapshotCache = 0xa, // Object is in the cache. |
220 kExternalReference = 0xb, // Pointer to an external reference. | 221 kExternalReference = 0xb, // Pointer to an external reference. |
221 kSkip = 0xc, // Skip n bytes. | 222 kSkip = 0xc, // Skip a pointer sized cell. |
222 kNop = 0xd, // Does nothing, used to pad. | 223 // 0xd-0xf Free. |
223 // 0xe-0xf Free. | 224 kBackref = 0x10, // Object is described relative to end. |
224 kBackref = 0x10, // Object is described relative to end. | 225 // 0x11-0x18 One per space. |
225 // 0x11-0x16 One per space. | 226 // 0x19-0x1f Free. |
226 kBackrefWithSkip = 0x18, // Object is described relative to end. | 227 kFromStart = 0x20, // Object is described relative to start. |
227 // 0x19-0x1e One per space. | 228 // 0x21-0x28 One per space. |
228 // 0x20-0x3f Used by misc. tags below. | 229 // 0x29-0x2f Free. |
| 230 // 0x30-0x3f Used by misc. tags below. |
229 kPointedToMask = 0x3f | 231 kPointedToMask = 0x3f |
230 }; | 232 }; |
231 | 233 |
232 // How to code the pointer to the object. | 234 // How to code the pointer to the object. |
233 enum HowToCode { | 235 enum HowToCode { |
234 kPlain = 0, // Straight pointer. | 236 kPlain = 0, // Straight pointer. |
235 // What this means depends on the architecture: | 237 // What this means depends on the architecture: |
236 kFromCode = 0x40, // A pointer inlined in code. | 238 kFromCode = 0x40, // A pointer inlined in code. |
237 kHowToCodeMask = 0x40 | 239 kHowToCodeMask = 0x40 |
238 }; | 240 }; |
239 | 241 |
240 // For kRootArrayConstants | |
241 enum WithSkip { | |
242 kNoSkipDistance = 0, | |
243 kHasSkipDistance = 0x40, | |
244 kWithSkipMask = 0x40 | |
245 }; | |
246 | |
247 // Where to point within the object. | 242 // Where to point within the object. |
248 enum WhereToPoint { | 243 enum WhereToPoint { |
249 kStartOfObject = 0, | 244 kStartOfObject = 0, |
250 kInnerPointer = 0x80, // First insn in code object or payload of cell. | 245 kInnerPointer = 0x80, // First insn in code object or payload of cell. |
251 kWhereToPointMask = 0x80 | 246 kWhereToPointMask = 0x80 |
252 }; | 247 }; |
253 | 248 |
254 // Misc. | 249 // Misc. |
255 // Raw data to be copied from the snapshot. This byte code does not advance | 250 // Raw data to be copied from the snapshot. |
256 // the current pointer, which is used for code objects, where we write the | 251 static const int kRawData = 0x30; |
257 // entire code in one memcpy, then fix up stuff with kSkip and other byte | 252 // Some common raw lengths: 0x31-0x3f |
258 // codes that overwrite data. | |
259 static const int kRawData = 0x20; | |
260 // Some common raw lengths: 0x21-0x3f. These autoadvance the current pointer. | |
261 // A tag emitted at strategic points in the snapshot to delineate sections. | 253 // A tag emitted at strategic points in the snapshot to delineate sections. |
262 // If the deserializer does not find these at the expected moments then it | 254 // If the deserializer does not find these at the expected moments then it |
263 // is an indication that the snapshot and the VM do not fit together. | 255 // is an indication that the snapshot and the VM do not fit together. |
264 // Examine the build process for architecture, version or configuration | 256 // Examine the build process for architecture, version or configuration |
265 // mismatches. | 257 // mismatches. |
266 static const int kSynchronize = 0x70; | 258 static const int kSynchronize = 0x70; |
267 // Used for the source code of the natives, which is in the executable, but | 259 // Used for the source code of the natives, which is in the executable, but |
268 // is referred to from external strings in the snapshot. | 260 // is referred to from external strings in the snapshot. |
269 static const int kNativesStringResource = 0x71; | 261 static const int kNativesStringResource = 0x71; |
270 static const int kRepeat = 0x72; | 262 static const int kNewPage = 0x72; |
271 static const int kConstantRepeat = 0x73; | 263 static const int kRepeat = 0x73; |
272 // 0x73-0x7f Repeat last word (subtract 0x72 to get the count). | 264 static const int kConstantRepeat = 0x74; |
273 static const int kMaxRepeats = 0x7f - 0x72; | 265 // 0x74-0x7f Repeat last word (subtract 0x73 to get the count). |
| 266 static const int kMaxRepeats = 0x7f - 0x73; |
274 static int CodeForRepeats(int repeats) { | 267 static int CodeForRepeats(int repeats) { |
275 ASSERT(repeats >= 1 && repeats <= kMaxRepeats); | 268 ASSERT(repeats >= 1 && repeats <= kMaxRepeats); |
276 return 0x72 + repeats; | 269 return 0x73 + repeats; |
277 } | 270 } |
278 static int RepeatsForCode(int byte_code) { | 271 static int RepeatsForCode(int byte_code) { |
279 ASSERT(byte_code >= kConstantRepeat && byte_code <= 0x7f); | 272 ASSERT(byte_code >= kConstantRepeat && byte_code <= 0x7f); |
280 return byte_code - 0x72; | 273 return byte_code - 0x73; |
281 } | 274 } |
282 static const int kRootArrayConstants = 0xa0; | 275 static const int kRootArrayLowConstants = 0xb0; |
283 // 0xa0-0xbf Things from the first 32 elements of the root array. | 276 // 0xb0-0xbf Things from the first 16 elements of the root array. |
| 277 static const int kRootArrayHighConstants = 0xf0; |
| 278 // 0xf0-0xff Things from the next 16 elements of the root array. |
284 static const int kRootArrayNumberOfConstantEncodings = 0x20; | 279 static const int kRootArrayNumberOfConstantEncodings = 0x20; |
| 280 static const int kRootArrayNumberOfLowConstantEncodings = 0x10; |
285 static int RootArrayConstantFromByteCode(int byte_code) { | 281 static int RootArrayConstantFromByteCode(int byte_code) { |
286 return byte_code & 0x1f; | 282 int constant = (byte_code & 0xf) | ((byte_code & 0x40) >> 2); |
| 283 ASSERT(constant >= 0 && constant < kRootArrayNumberOfConstantEncodings); |
| 284 return constant; |
287 } | 285 } |
288 | 286 |
289 static const int kNumberOfSpaces = LO_SPACE; | 287 |
| 288 static const int kLargeData = LAST_SPACE; |
| 289 static const int kLargeCode = kLargeData + 1; |
| 290 static const int kLargeFixedArray = kLargeCode + 1; |
| 291 static const int kNumberOfSpaces = kLargeFixedArray + 1; |
290 static const int kAnyOldSpace = -1; | 292 static const int kAnyOldSpace = -1; |
291 | 293 |
292 // A bitmask for getting the space out of an instruction. | 294 // A bitmask for getting the space out of an instruction. |
293 static const int kSpaceMask = 7; | 295 static const int kSpaceMask = 15; |
| 296 |
| 297 static inline bool SpaceIsLarge(int space) { return space >= kLargeData; } |
| 298 static inline bool SpaceIsPaged(int space) { |
| 299 return space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE; |
| 300 } |
294 }; | 301 }; |
295 | 302 |
296 | 303 |
297 int SnapshotByteSource::GetInt() { | 304 int SnapshotByteSource::GetInt() { |
298 // This way of variable-length encoding integers does not suffer from branch | 305 // A little unwind to catch the really small ints. |
299 // mispredictions. | 306 int snapshot_byte = Get(); |
300 uint32_t answer = GetUnalignedInt(); | 307 if ((snapshot_byte & 0x80) == 0) { |
301 int bytes = answer & 3; | 308 return snapshot_byte; |
302 Advance(bytes); | 309 } |
303 uint32_t mask = 0xffffffffu; | 310 int accumulator = (snapshot_byte & 0x7f) << 7; |
304 mask >>= 32 - (bytes << 3); | 311 while (true) { |
305 answer &= mask; | 312 snapshot_byte = Get(); |
306 answer >>= 2; | 313 if ((snapshot_byte & 0x80) == 0) { |
307 return answer; | 314 return accumulator | snapshot_byte; |
| 315 } |
| 316 accumulator = (accumulator | (snapshot_byte & 0x7f)) << 7; |
| 317 } |
| 318 UNREACHABLE(); |
| 319 return accumulator; |
308 } | 320 } |
309 | 321 |
310 | 322 |
311 void SnapshotByteSource::CopyRaw(byte* to, int number_of_bytes) { | 323 void SnapshotByteSource::CopyRaw(byte* to, int number_of_bytes) { |
312 memcpy(to, data_ + position_, number_of_bytes); | 324 memcpy(to, data_ + position_, number_of_bytes); |
313 position_ += number_of_bytes; | 325 position_ += number_of_bytes; |
314 } | 326 } |
315 | 327 |
316 | 328 |
317 // A Deserializer reads a snapshot and reconstructs the Object graph it defines. | 329 // A Deserializer reads a snapshot and reconstructs the Object graph it defines. |
318 class Deserializer: public SerializerDeserializer { | 330 class Deserializer: public SerializerDeserializer { |
319 public: | 331 public: |
320 // Create a deserializer from a snapshot byte source. | 332 // Create a deserializer from a snapshot byte source. |
321 explicit Deserializer(SnapshotByteSource* source); | 333 explicit Deserializer(SnapshotByteSource* source); |
322 | 334 |
323 virtual ~Deserializer(); | 335 virtual ~Deserializer(); |
324 | 336 |
325 // Deserialize the snapshot into an empty heap. | 337 // Deserialize the snapshot into an empty heap. |
326 void Deserialize(); | 338 void Deserialize(); |
327 | 339 |
328 // Deserialize a single object and the objects reachable from it. | 340 // Deserialize a single object and the objects reachable from it. |
329 void DeserializePartial(Object** root); | 341 void DeserializePartial(Object** root); |
330 | 342 |
331 void set_reservation(int space_number, int reservation) { | |
332 ASSERT(space_number >= 0); | |
333 ASSERT(space_number <= LAST_SPACE); | |
334 reservations_[space_number] = reservation; | |
335 } | |
336 | |
337 private: | 343 private: |
338 virtual void VisitPointers(Object** start, Object** end); | 344 virtual void VisitPointers(Object** start, Object** end); |
339 | 345 |
340 virtual void VisitExternalReferences(Address* start, Address* end) { | 346 virtual void VisitExternalReferences(Address* start, Address* end) { |
341 UNREACHABLE(); | 347 UNREACHABLE(); |
342 } | 348 } |
343 | 349 |
344 virtual void VisitRuntimeEntry(RelocInfo* rinfo) { | 350 virtual void VisitRuntimeEntry(RelocInfo* rinfo) { |
345 UNREACHABLE(); | 351 UNREACHABLE(); |
346 } | 352 } |
347 | 353 |
348 // Fills in some heap data in an area from start to end (non-inclusive). The | 354 // Fills in some heap data in an area from start to end (non-inclusive). The |
349 // space id is used for the write barrier. The object_address is the address | 355 // space id is used for the write barrier. The object_address is the address |
350 // of the object we are writing into, or NULL if we are not writing into an | 356 // of the object we are writing into, or NULL if we are not writing into an |
351 // object, i.e. if we are writing a series of tagged values that are not on | 357 // object, i.e. if we are writing a series of tagged values that are not on |
352 // the heap. | 358 // the heap. |
353 void ReadChunk( | 359 void ReadChunk( |
354 Object** start, Object** end, int space, Address object_address); | 360 Object** start, Object** end, int space, Address object_address); |
355 void ReadObject(int space_number, Object** write_back); | 361 HeapObject* GetAddressFromStart(int space); |
356 | 362 inline HeapObject* GetAddressFromEnd(int space); |
357 // This routine both allocates a new object, and also keeps | 363 Address Allocate(int space_number, Space* space, int size); |
358 // track of where objects have been allocated so that we can | 364 void ReadObject(int space_number, Space* space, Object** write_back); |
359 // fix back references when deserializing. | |
360 Address Allocate(int space_index, int size) { | |
361 Address address = high_water_[space_index]; | |
362 high_water_[space_index] = address + size; | |
363 return address; | |
364 } | |
365 | |
366 // This returns the address of an object that has been described in the | |
367 // snapshot as being offset bytes back in a particular space. | |
368 HeapObject* GetAddressFromEnd(int space) { | |
369 int offset = source_->GetInt(); | |
370 offset <<= kObjectAlignmentBits; | |
371 return HeapObject::FromAddress(high_water_[space] - offset); | |
372 } | |
373 | |
374 | 365 |
375 // Cached current isolate. | 366 // Cached current isolate. |
376 Isolate* isolate_; | 367 Isolate* isolate_; |
377 | 368 |
| 369 // Keep track of the pages in the paged spaces. |
| 370 // (In large object space we are keeping track of individual objects |
| 371 // rather than pages.) In new space we just need the address of the |
| 372 // first object and the others will flow from that. |
| 373 List<Address> pages_[SerializerDeserializer::kNumberOfSpaces]; |
| 374 |
378 SnapshotByteSource* source_; | 375 SnapshotByteSource* source_; |
379 // This is the address of the next object that will be allocated in each | 376 // This is the address of the next object that will be allocated in each |
380 // space. It is used to calculate the addresses of back-references. | 377 // space. It is used to calculate the addresses of back-references. |
381 Address high_water_[LAST_SPACE + 1]; | 378 Address high_water_[LAST_SPACE + 1]; |
382 | 379 // This is the address of the most recent object that was allocated. It |
383 int reservations_[LAST_SPACE + 1]; | 380 // is used to set the location of the new page when we encounter a |
384 static const intptr_t kUninitializedReservation = -1; | 381 // START_NEW_PAGE_SERIALIZATION tag. |
| 382 Address last_object_address_; |
385 | 383 |
386 ExternalReferenceDecoder* external_reference_decoder_; | 384 ExternalReferenceDecoder* external_reference_decoder_; |
387 | 385 |
388 DISALLOW_COPY_AND_ASSIGN(Deserializer); | 386 DISALLOW_COPY_AND_ASSIGN(Deserializer); |
389 }; | 387 }; |
390 | 388 |
391 | 389 |
392 class SnapshotByteSink { | 390 class SnapshotByteSink { |
393 public: | 391 public: |
394 virtual ~SnapshotByteSink() { } | 392 virtual ~SnapshotByteSink() { } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 | 454 |
457 // There can be only one serializer per V8 process. | 455 // There can be only one serializer per V8 process. |
458 class Serializer : public SerializerDeserializer { | 456 class Serializer : public SerializerDeserializer { |
459 public: | 457 public: |
460 explicit Serializer(SnapshotByteSink* sink); | 458 explicit Serializer(SnapshotByteSink* sink); |
461 ~Serializer(); | 459 ~Serializer(); |
462 void VisitPointers(Object** start, Object** end); | 460 void VisitPointers(Object** start, Object** end); |
463 // You can call this after serialization to find out how much space was used | 461 // You can call this after serialization to find out how much space was used |
464 // in each space. | 462 // in each space. |
465 int CurrentAllocationAddress(int space) { | 463 int CurrentAllocationAddress(int space) { |
466 ASSERT(space < kNumberOfSpaces); | 464 if (SpaceIsLarge(space)) return large_object_total_; |
467 return fullness_[space]; | 465 return fullness_[space]; |
468 } | 466 } |
469 | 467 |
470 static void Enable() { | 468 static void Enable() { |
471 if (!serialization_enabled_) { | 469 if (!serialization_enabled_) { |
472 ASSERT(!too_late_to_enable_now_); | 470 ASSERT(!too_late_to_enable_now_); |
473 } | 471 } |
474 serialization_enabled_ = true; | 472 serialization_enabled_ = true; |
475 } | 473 } |
476 | 474 |
477 static void Disable() { serialization_enabled_ = false; } | 475 static void Disable() { serialization_enabled_ = false; } |
478 // Call this when you have made use of the fact that there is no serialization | 476 // Call this when you have made use of the fact that there is no serialization |
479 // going on. | 477 // going on. |
480 static void TooLateToEnableNow() { too_late_to_enable_now_ = true; } | 478 static void TooLateToEnableNow() { too_late_to_enable_now_ = true; } |
481 static bool enabled() { return serialization_enabled_; } | 479 static bool enabled() { return serialization_enabled_; } |
482 SerializationAddressMapper* address_mapper() { return &address_mapper_; } | 480 SerializationAddressMapper* address_mapper() { return &address_mapper_; } |
483 void PutRoot(int index, | 481 void PutRoot( |
484 HeapObject* object, | 482 int index, HeapObject* object, HowToCode how, WhereToPoint where); |
485 HowToCode how, | |
486 WhereToPoint where, | |
487 int skip); | |
488 | 483 |
489 protected: | 484 protected: |
490 static const int kInvalidRootIndex = -1; | 485 static const int kInvalidRootIndex = -1; |
491 | 486 |
492 int RootIndex(HeapObject* heap_object, HowToCode from); | 487 int RootIndex(HeapObject* heap_object, HowToCode from); |
493 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) = 0; | 488 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) = 0; |
494 intptr_t root_index_wave_front() { return root_index_wave_front_; } | 489 intptr_t root_index_wave_front() { return root_index_wave_front_; } |
495 void set_root_index_wave_front(intptr_t value) { | 490 void set_root_index_wave_front(intptr_t value) { |
496 ASSERT(value >= root_index_wave_front_); | 491 ASSERT(value >= root_index_wave_front_); |
497 root_index_wave_front_ = value; | 492 root_index_wave_front_ = value; |
498 } | 493 } |
499 | 494 |
500 class ObjectSerializer : public ObjectVisitor { | 495 class ObjectSerializer : public ObjectVisitor { |
501 public: | 496 public: |
502 ObjectSerializer(Serializer* serializer, | 497 ObjectSerializer(Serializer* serializer, |
503 Object* o, | 498 Object* o, |
504 SnapshotByteSink* sink, | 499 SnapshotByteSink* sink, |
505 HowToCode how_to_code, | 500 HowToCode how_to_code, |
506 WhereToPoint where_to_point) | 501 WhereToPoint where_to_point) |
507 : serializer_(serializer), | 502 : serializer_(serializer), |
508 object_(HeapObject::cast(o)), | 503 object_(HeapObject::cast(o)), |
509 sink_(sink), | 504 sink_(sink), |
510 reference_representation_(how_to_code + where_to_point), | 505 reference_representation_(how_to_code + where_to_point), |
511 bytes_processed_so_far_(0), | 506 bytes_processed_so_far_(0) { } |
512 code_object_(o->IsCode()), | |
513 code_has_been_output_(false) { } | |
514 void Serialize(); | 507 void Serialize(); |
515 void VisitPointers(Object** start, Object** end); | 508 void VisitPointers(Object** start, Object** end); |
516 void VisitEmbeddedPointer(RelocInfo* target); | 509 void VisitEmbeddedPointer(RelocInfo* target); |
517 void VisitExternalReferences(Address* start, Address* end); | 510 void VisitExternalReferences(Address* start, Address* end); |
518 void VisitExternalReference(RelocInfo* rinfo); | 511 void VisitExternalReference(RelocInfo* rinfo); |
519 void VisitCodeTarget(RelocInfo* target); | 512 void VisitCodeTarget(RelocInfo* target); |
520 void VisitCodeEntry(Address entry_address); | 513 void VisitCodeEntry(Address entry_address); |
521 void VisitGlobalPropertyCell(RelocInfo* rinfo); | 514 void VisitGlobalPropertyCell(RelocInfo* rinfo); |
522 void VisitRuntimeEntry(RelocInfo* reloc); | 515 void VisitRuntimeEntry(RelocInfo* reloc); |
523 // Used for seralizing the external strings that hold the natives source. | 516 // Used for seralizing the external strings that hold the natives source. |
524 void VisitExternalAsciiString( | 517 void VisitExternalAsciiString( |
525 v8::String::ExternalAsciiStringResource** resource); | 518 v8::String::ExternalAsciiStringResource** resource); |
526 // We can't serialize a heap with external two byte strings. | 519 // We can't serialize a heap with external two byte strings. |
527 void VisitExternalTwoByteString( | 520 void VisitExternalTwoByteString( |
528 v8::String::ExternalStringResource** resource) { | 521 v8::String::ExternalStringResource** resource) { |
529 UNREACHABLE(); | 522 UNREACHABLE(); |
530 } | 523 } |
531 | 524 |
532 private: | 525 private: |
533 enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn }; | 526 void OutputRawData(Address up_to); |
534 // This function outputs or skips the raw data between the last pointer and | |
535 // up to the current position. It optionally can just return the number of | |
536 // bytes to skip instead of performing a skip instruction, in case the skip | |
537 // can be merged into the next instruction. | |
538 int OutputRawData(Address up_to, ReturnSkip return_skip = kIgnoringReturn); | |
539 | 527 |
540 Serializer* serializer_; | 528 Serializer* serializer_; |
541 HeapObject* object_; | 529 HeapObject* object_; |
542 SnapshotByteSink* sink_; | 530 SnapshotByteSink* sink_; |
543 int reference_representation_; | 531 int reference_representation_; |
544 int bytes_processed_so_far_; | 532 int bytes_processed_so_far_; |
545 bool code_object_; | |
546 bool code_has_been_output_; | |
547 }; | 533 }; |
548 | 534 |
549 virtual void SerializeObject(Object* o, | 535 virtual void SerializeObject(Object* o, |
550 HowToCode how_to_code, | 536 HowToCode how_to_code, |
551 WhereToPoint where_to_point, | 537 WhereToPoint where_to_point) = 0; |
552 int skip) = 0; | |
553 void SerializeReferenceToPreviousObject( | 538 void SerializeReferenceToPreviousObject( |
554 int space, | 539 int space, |
555 int address, | 540 int address, |
556 HowToCode how_to_code, | 541 HowToCode how_to_code, |
557 WhereToPoint where_to_point, | 542 WhereToPoint where_to_point); |
558 int skip); | |
559 void InitializeAllocators(); | 543 void InitializeAllocators(); |
560 // This will return the space for an object. | 544 // This will return the space for an object. If the object is in large |
| 545 // object space it may return kLargeCode or kLargeFixedArray in order |
| 546 // to indicate to the deserializer what kind of large object allocation |
| 547 // to make. |
561 static int SpaceOfObject(HeapObject* object); | 548 static int SpaceOfObject(HeapObject* object); |
562 int Allocate(int space, int size); | 549 // This just returns the space of the object. It will return LO_SPACE |
| 550 // for all large objects since you can't check the type of the object |
| 551 // once the map has been used for the serialization address. |
| 552 static int SpaceOfAlreadySerializedObject(HeapObject* object); |
| 553 int Allocate(int space, int size, bool* new_page_started); |
563 int EncodeExternalReference(Address addr) { | 554 int EncodeExternalReference(Address addr) { |
564 return external_reference_encoder_->Encode(addr); | 555 return external_reference_encoder_->Encode(addr); |
565 } | 556 } |
566 | 557 |
567 int SpaceAreaSize(int space); | 558 int SpaceAreaSize(int space); |
568 | 559 |
569 Isolate* isolate_; | 560 Isolate* isolate_; |
570 // Keep track of the fullness of each space in order to generate | 561 // Keep track of the fullness of each space in order to generate |
571 // relative addresses for back references. | 562 // relative addresses for back references. Large objects are |
| 563 // just numbered sequentially since relative addresses make no |
| 564 // sense in large object space. |
572 int fullness_[LAST_SPACE + 1]; | 565 int fullness_[LAST_SPACE + 1]; |
573 SnapshotByteSink* sink_; | 566 SnapshotByteSink* sink_; |
574 int current_root_index_; | 567 int current_root_index_; |
575 ExternalReferenceEncoder* external_reference_encoder_; | 568 ExternalReferenceEncoder* external_reference_encoder_; |
576 static bool serialization_enabled_; | 569 static bool serialization_enabled_; |
577 // Did we already make use of the fact that serialization was not enabled? | 570 // Did we already make use of the fact that serialization was not enabled? |
578 static bool too_late_to_enable_now_; | 571 static bool too_late_to_enable_now_; |
| 572 int large_object_total_; |
579 SerializationAddressMapper address_mapper_; | 573 SerializationAddressMapper address_mapper_; |
580 intptr_t root_index_wave_front_; | 574 intptr_t root_index_wave_front_; |
581 void Pad(); | |
582 | 575 |
583 friend class ObjectSerializer; | 576 friend class ObjectSerializer; |
584 friend class Deserializer; | 577 friend class Deserializer; |
585 | 578 |
586 private: | 579 private: |
587 DISALLOW_COPY_AND_ASSIGN(Serializer); | 580 DISALLOW_COPY_AND_ASSIGN(Serializer); |
588 }; | 581 }; |
589 | 582 |
590 | 583 |
591 class PartialSerializer : public Serializer { | 584 class PartialSerializer : public Serializer { |
592 public: | 585 public: |
593 PartialSerializer(Serializer* startup_snapshot_serializer, | 586 PartialSerializer(Serializer* startup_snapshot_serializer, |
594 SnapshotByteSink* sink) | 587 SnapshotByteSink* sink) |
595 : Serializer(sink), | 588 : Serializer(sink), |
596 startup_serializer_(startup_snapshot_serializer) { | 589 startup_serializer_(startup_snapshot_serializer) { |
597 set_root_index_wave_front(Heap::kStrongRootListLength); | 590 set_root_index_wave_front(Heap::kStrongRootListLength); |
598 } | 591 } |
599 | 592 |
600 // Serialize the objects reachable from a single object pointer. | 593 // Serialize the objects reachable from a single object pointer. |
601 virtual void Serialize(Object** o); | 594 virtual void Serialize(Object** o); |
602 virtual void SerializeObject(Object* o, | 595 virtual void SerializeObject(Object* o, |
603 HowToCode how_to_code, | 596 HowToCode how_to_code, |
604 WhereToPoint where_to_point, | 597 WhereToPoint where_to_point); |
605 int skip); | |
606 | 598 |
607 protected: | 599 protected: |
608 virtual int PartialSnapshotCacheIndex(HeapObject* o); | 600 virtual int PartialSnapshotCacheIndex(HeapObject* o); |
609 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) { | 601 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) { |
610 // Scripts should be referred only through shared function infos. We can't | 602 // Scripts should be referred only through shared function infos. We can't |
611 // allow them to be part of the partial snapshot because they contain a | 603 // allow them to be part of the partial snapshot because they contain a |
612 // unique ID, and deserializing several partial snapshots containing script | 604 // unique ID, and deserializing several partial snapshots containing script |
613 // would cause dupes. | 605 // would cause dupes. |
614 ASSERT(!o->IsScript()); | 606 ASSERT(!o->IsScript()); |
615 return o->IsString() || o->IsSharedFunctionInfo() || | 607 return o->IsString() || o->IsSharedFunctionInfo() || |
(...skipping 17 matching lines...) Expand all Loading... |
633 // snapshot. | 625 // snapshot. |
634 Isolate::Current()->set_serialize_partial_snapshot_cache_length(0); | 626 Isolate::Current()->set_serialize_partial_snapshot_cache_length(0); |
635 } | 627 } |
636 // Serialize the current state of the heap. The order is: | 628 // Serialize the current state of the heap. The order is: |
637 // 1) Strong references. | 629 // 1) Strong references. |
638 // 2) Partial snapshot cache. | 630 // 2) Partial snapshot cache. |
639 // 3) Weak references (e.g. the symbol table). | 631 // 3) Weak references (e.g. the symbol table). |
640 virtual void SerializeStrongReferences(); | 632 virtual void SerializeStrongReferences(); |
641 virtual void SerializeObject(Object* o, | 633 virtual void SerializeObject(Object* o, |
642 HowToCode how_to_code, | 634 HowToCode how_to_code, |
643 WhereToPoint where_to_point, | 635 WhereToPoint where_to_point); |
644 int skip); | |
645 void SerializeWeakReferences(); | 636 void SerializeWeakReferences(); |
646 void Serialize() { | 637 void Serialize() { |
647 SerializeStrongReferences(); | 638 SerializeStrongReferences(); |
648 SerializeWeakReferences(); | 639 SerializeWeakReferences(); |
649 Pad(); | |
650 } | 640 } |
651 | 641 |
652 private: | 642 private: |
653 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) { | 643 virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) { |
654 return false; | 644 return false; |
655 } | 645 } |
656 }; | 646 }; |
657 | 647 |
658 | 648 |
659 } } // namespace v8::internal | 649 } } // namespace v8::internal |
660 | 650 |
661 #endif // V8_SERIALIZE_H_ | 651 #endif // V8_SERIALIZE_H_ |
OLD | NEW |