OLD | NEW |
---|---|
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/snapshot/serializer.h" | 5 #include "src/snapshot/serializer.h" |
6 | 6 |
7 #include "src/assembler-inl.h" | 7 #include "src/assembler-inl.h" |
8 #include "src/deoptimizer.h" | 8 #include "src/deoptimizer.h" |
9 #include "src/heap/heap-inl.h" | 9 #include "src/heap/heap-inl.h" |
10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
394 #endif // OBJECT_PRINT | 394 #endif // OBJECT_PRINT |
395 | 395 |
396 // Mark this object as already serialized. | 396 // Mark this object as already serialized. |
397 serializer_->reference_map()->Add(object_, back_reference); | 397 serializer_->reference_map()->Add(object_, back_reference); |
398 | 398 |
399 // Serialize the map (first word of the object). | 399 // Serialize the map (first word of the object). |
400 serializer_->SerializeObject(map, kPlain, kStartOfObject, 0); | 400 serializer_->SerializeObject(map, kPlain, kStartOfObject, 0); |
401 } | 401 } |
402 | 402 |
403 void Serializer::ObjectSerializer::SerializeExternalString() { | 403 void Serializer::ObjectSerializer::SerializeExternalString() { |
404 Heap* heap = serializer_->isolate()->heap(); | |
405 if (object_->map() != heap->native_source_string_map()) { | |
406 // Usually we cannot recreate resources for external strings. To work | |
407 // around this, external strings are serialized to look like ordinary | |
408 // sequential strings. | |
409 // The exception are native source code strings, since we can recreate | |
410 // their resources. | |
411 SerializeExternalStringAsSequentialString(); | |
412 } else { | |
413 DCHECK(object_->IsExternalOneByteString()); | |
414 DCHECK(ExternalOneByteString::cast(object_)->is_short()); | |
415 int size = object_->Size(); | |
416 Map* map = object_->map(); | |
417 AllocationSpace space = | |
418 MemoryChunk::FromAddress(object_->address())->owner()->identity(); | |
419 SerializePrologue(space, size, map); | |
420 // Serialize the rest of the object. | |
421 CHECK_EQ(0, bytes_processed_so_far_); | |
ulan
2017/04/06 17:53:08
Lines 413-421 are from the Serialize function.
Th
| |
422 bytes_processed_so_far_ = kPointerSize; | |
423 typedef v8::String::ExternalOneByteStringResource Resource; | |
424 Resource** resource_pointer = reinterpret_cast<Resource**>( | |
425 HeapObject::RawField(object_, ExternalString::kResourceOffset)); | |
426 | |
427 Address references_start = reinterpret_cast<Address>(resource_pointer); | |
428 OutputRawData(references_start); | |
429 if (!SerializeExternalNativeSourceString( | |
430 Natives::GetBuiltinsCount(), resource_pointer, | |
431 Natives::GetSourceCache(heap), kNativesStringResource)) { | |
432 bool result = SerializeExternalNativeSourceString( | |
433 ExtraNatives::GetBuiltinsCount(), resource_pointer, | |
434 ExtraNatives::GetSourceCache(heap), kExtraNativesStringResource); | |
435 // One of the strings in the natives cache should match the resource. We | |
436 // don't expect any other kinds of external strings here. | |
437 USE(result); | |
438 DCHECK(result); | |
439 } | |
440 OutputRawData(object_->address() + size); | |
441 } | |
442 } | |
443 | |
444 bool Serializer::ObjectSerializer::SerializeExternalNativeSourceString( | |
445 int builtin_count, | |
446 v8::String::ExternalOneByteStringResource** resource_pointer, | |
447 FixedArray* source_cache, int resource_index) { | |
448 Isolate* isolate = serializer_->isolate(); | |
ulan
2017/04/06 17:53:08
This function moved without any change.
| |
449 for (int i = 0; i < builtin_count; i++) { | |
450 Object* source = source_cache->get(i); | |
451 if (!source->IsUndefined(isolate)) { | |
452 ExternalOneByteString* string = ExternalOneByteString::cast(source); | |
453 typedef v8::String::ExternalOneByteStringResource Resource; | |
454 const Resource* resource = string->resource(); | |
455 if (resource == *resource_pointer) { | |
456 sink_->Put(resource_index, "NativesStringResource"); | |
457 sink_->PutSection(i, "NativesStringResourceEnd"); | |
458 bytes_processed_so_far_ += sizeof(resource); | |
459 return true; | |
460 } | |
461 } | |
462 } | |
463 return false; | |
464 } | |
465 | |
466 void Serializer::ObjectSerializer::SerializeExternalStringAsSequentialString() { | |
404 // Instead of serializing this as an external string, we serialize | 467 // Instead of serializing this as an external string, we serialize |
405 // an imaginary sequential string with the same content. | 468 // an imaginary sequential string with the same content. |
406 Isolate* isolate = serializer_->isolate(); | 469 Isolate* isolate = serializer_->isolate(); |
407 DCHECK(object_->IsExternalString()); | 470 DCHECK(object_->IsExternalString()); |
408 DCHECK(object_->map() != isolate->heap()->native_source_string_map()); | 471 DCHECK(object_->map() != isolate->heap()->native_source_string_map()); |
409 ExternalString* string = ExternalString::cast(object_); | 472 ExternalString* string = ExternalString::cast(object_); |
410 int length = string->length(); | 473 int length = string->length(); |
411 Map* map; | 474 Map* map; |
412 int content_size; | 475 int content_size; |
413 int allocation_size; | 476 int allocation_size; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
494 DisallowHeapAllocation no_gc_; | 557 DisallowHeapAllocation no_gc_; |
495 }; | 558 }; |
496 | 559 |
497 void Serializer::ObjectSerializer::Serialize() { | 560 void Serializer::ObjectSerializer::Serialize() { |
498 if (FLAG_trace_serializer) { | 561 if (FLAG_trace_serializer) { |
499 PrintF(" Encoding heap object: "); | 562 PrintF(" Encoding heap object: "); |
500 object_->ShortPrint(); | 563 object_->ShortPrint(); |
501 PrintF("\n"); | 564 PrintF("\n"); |
502 } | 565 } |
503 | 566 |
504 // We cannot serialize typed array objects correctly. | 567 if (object_->IsExternalString()) { |
505 DCHECK(!object_->IsJSTypedArray()); | 568 SerializeExternalString(); |
569 } else { | |
570 // We cannot serialize typed array objects correctly. | |
571 DCHECK(!object_->IsJSTypedArray()); | |
506 | 572 |
507 // We don't expect fillers. | 573 // We don't expect fillers. |
508 DCHECK(!object_->IsFiller()); | 574 DCHECK(!object_->IsFiller()); |
509 | 575 |
510 if (object_->IsScript()) { | 576 if (object_->IsScript()) { |
511 // Clear cached line ends. | 577 // Clear cached line ends. |
512 Object* undefined = serializer_->isolate()->heap()->undefined_value(); | 578 Object* undefined = serializer_->isolate()->heap()->undefined_value(); |
513 Script::cast(object_)->set_line_ends(undefined); | 579 Script::cast(object_)->set_line_ends(undefined); |
514 } | 580 } |
515 | 581 |
516 if (object_->IsExternalString()) { | 582 int size = object_->Size(); |
ulan
2017/04/06 17:53:08
This code just moved verbatim from 529.
| |
517 Heap* heap = serializer_->isolate()->heap(); | 583 Map* map = object_->map(); |
518 if (object_->map() != heap->native_source_string_map()) { | 584 AllocationSpace space = |
519 // Usually we cannot recreate resources for external strings. To work | 585 MemoryChunk::FromAddress(object_->address())->owner()->identity(); |
520 // around this, external strings are serialized to look like ordinary | 586 SerializePrologue(space, size, map); |
521 // sequential strings. | 587 |
522 // The exception are native source code strings, since we can recreate | 588 // Serialize the rest of the object. |
523 // their resources. In that case we fall through and leave it to | 589 CHECK_EQ(0, bytes_processed_so_far_); |
524 // VisitExternalOneByteString further down. | 590 bytes_processed_so_far_ = kPointerSize; |
525 SerializeExternalString(); | 591 |
592 RecursionScope recursion(serializer_); | |
593 // Objects that are immediately post processed during deserialization | |
594 // cannot be deferred, since post processing requires the object content. | |
595 if (recursion.ExceedsMaximum() && CanBeDeferred(object_)) { | |
596 serializer_->QueueDeferredObject(object_); | |
597 sink_->Put(kDeferred, "Deferring object content"); | |
526 return; | 598 return; |
527 } | 599 } |
600 | |
601 UnlinkWeakNextScope unlink_weak_next(object_); | |
602 | |
603 object_->IterateBody(map->instance_type(), size, this); | |
604 OutputRawData(object_->address() + size); | |
528 } | 605 } |
529 | |
530 int size = object_->Size(); | |
531 Map* map = object_->map(); | |
532 AllocationSpace space = | |
533 MemoryChunk::FromAddress(object_->address())->owner()->identity(); | |
534 SerializePrologue(space, size, map); | |
535 | |
536 // Serialize the rest of the object. | |
537 CHECK_EQ(0, bytes_processed_so_far_); | |
538 bytes_processed_so_far_ = kPointerSize; | |
539 | |
540 RecursionScope recursion(serializer_); | |
541 // Objects that are immediately post processed during deserialization | |
542 // cannot be deferred, since post processing requires the object content. | |
543 if (recursion.ExceedsMaximum() && CanBeDeferred(object_)) { | |
544 serializer_->QueueDeferredObject(object_); | |
545 sink_->Put(kDeferred, "Deferring object content"); | |
546 return; | |
547 } | |
548 | |
549 UnlinkWeakNextScope unlink_weak_next(object_); | |
550 | |
551 object_->IterateBody(map->instance_type(), size, this); | |
552 OutputRawData(object_->address() + size); | |
553 } | 606 } |
554 | 607 |
555 void Serializer::ObjectSerializer::SerializeDeferred() { | 608 void Serializer::ObjectSerializer::SerializeDeferred() { |
556 if (FLAG_trace_serializer) { | 609 if (FLAG_trace_serializer) { |
557 PrintF(" Encoding deferred heap object: "); | 610 PrintF(" Encoding deferred heap object: "); |
558 object_->ShortPrint(); | 611 object_->ShortPrint(); |
559 PrintF("\n"); | 612 PrintF("\n"); |
560 } | 613 } |
561 | 614 |
562 int size = object_->Size(); | 615 int size = object_->Size(); |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
708 bytes_processed_so_far_ += kPointerSize; | 761 bytes_processed_so_far_ += kPointerSize; |
709 } | 762 } |
710 | 763 |
711 void Serializer::ObjectSerializer::VisitCell(RelocInfo* rinfo) { | 764 void Serializer::ObjectSerializer::VisitCell(RelocInfo* rinfo) { |
712 int skip = OutputRawData(rinfo->pc(), kCanReturnSkipInsteadOfSkipping); | 765 int skip = OutputRawData(rinfo->pc(), kCanReturnSkipInsteadOfSkipping); |
713 Cell* object = Cell::cast(rinfo->target_cell()); | 766 Cell* object = Cell::cast(rinfo->target_cell()); |
714 serializer_->SerializeObject(object, kPlain, kInnerPointer, skip); | 767 serializer_->SerializeObject(object, kPlain, kInnerPointer, skip); |
715 bytes_processed_so_far_ += kPointerSize; | 768 bytes_processed_so_far_ += kPointerSize; |
716 } | 769 } |
717 | 770 |
718 bool Serializer::ObjectSerializer::SerializeExternalNativeSourceString( | |
719 int builtin_count, | |
720 v8::String::ExternalOneByteStringResource** resource_pointer, | |
721 FixedArray* source_cache, int resource_index) { | |
722 Isolate* isolate = serializer_->isolate(); | |
723 for (int i = 0; i < builtin_count; i++) { | |
724 Object* source = source_cache->get(i); | |
725 if (!source->IsUndefined(isolate)) { | |
726 ExternalOneByteString* string = ExternalOneByteString::cast(source); | |
727 typedef v8::String::ExternalOneByteStringResource Resource; | |
728 const Resource* resource = string->resource(); | |
729 if (resource == *resource_pointer) { | |
730 sink_->Put(resource_index, "NativesStringResource"); | |
731 sink_->PutSection(i, "NativesStringResourceEnd"); | |
732 bytes_processed_so_far_ += sizeof(resource); | |
733 return true; | |
734 } | |
735 } | |
736 } | |
737 return false; | |
738 } | |
739 | |
740 void Serializer::ObjectSerializer::VisitExternalOneByteString( | |
741 v8::String::ExternalOneByteStringResource** resource_pointer) { | |
742 DCHECK_EQ(serializer_->isolate()->heap()->native_source_string_map(), | |
743 object_->map()); | |
744 DCHECK(ExternalOneByteString::cast(object_)->is_short()); | |
745 Address references_start = reinterpret_cast<Address>(resource_pointer); | |
746 OutputRawData(references_start); | |
747 if (SerializeExternalNativeSourceString( | |
748 Natives::GetBuiltinsCount(), resource_pointer, | |
749 Natives::GetSourceCache(serializer_->isolate()->heap()), | |
750 kNativesStringResource)) { | |
751 return; | |
752 } | |
753 if (SerializeExternalNativeSourceString( | |
754 ExtraNatives::GetBuiltinsCount(), resource_pointer, | |
755 ExtraNatives::GetSourceCache(serializer_->isolate()->heap()), | |
756 kExtraNativesStringResource)) { | |
757 return; | |
758 } | |
759 // One of the strings in the natives cache should match the resource. We | |
760 // don't expect any other kinds of external strings here. | |
761 UNREACHABLE(); | |
762 } | |
763 | |
764 Address Serializer::ObjectSerializer::PrepareCode() { | 771 Address Serializer::ObjectSerializer::PrepareCode() { |
765 Code* code = Code::cast(object_); | 772 Code* code = Code::cast(object_); |
766 if (FLAG_predictable) { | 773 if (FLAG_predictable) { |
767 // To make snapshots reproducible, we make a copy of the code object | 774 // To make snapshots reproducible, we make a copy of the code object |
768 // and wipe all pointers in the copy, which we then serialize. | 775 // and wipe all pointers in the copy, which we then serialize. |
769 code = serializer_->CopyCode(code); | 776 code = serializer_->CopyCode(code); |
770 int mode_mask = RelocInfo::kCodeTargetMask | | 777 int mode_mask = RelocInfo::kCodeTargetMask | |
771 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 778 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
772 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | | 779 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | |
773 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) | | 780 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) | |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
826 if (to_skip != 0 && return_skip == kIgnoringReturn) { | 833 if (to_skip != 0 && return_skip == kIgnoringReturn) { |
827 sink_->Put(kSkip, "Skip"); | 834 sink_->Put(kSkip, "Skip"); |
828 sink_->PutInt(to_skip, "SkipDistance"); | 835 sink_->PutInt(to_skip, "SkipDistance"); |
829 to_skip = 0; | 836 to_skip = 0; |
830 } | 837 } |
831 return to_skip; | 838 return to_skip; |
832 } | 839 } |
833 | 840 |
834 } // namespace internal | 841 } // namespace internal |
835 } // namespace v8 | 842 } // namespace v8 |
OLD | NEW |