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

Side by Side Diff: src/serialize.cc

Issue 8352045: Fix missing write barrier in deserialization. Issue 1783. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 2 months 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
« src/heap-inl.h ('K') | « src/serialize.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 677 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 external_reference_decoder_ = NULL; 688 external_reference_decoder_ = NULL;
689 } 689 }
690 } 690 }
691 691
692 692
693 // This is called on the roots. It is the driver of the deserialization 693 // This is called on the roots. It is the driver of the deserialization
694 // process. It is also called on the body of each function. 694 // process. It is also called on the body of each function.
695 void Deserializer::VisitPointers(Object** start, Object** end) { 695 void Deserializer::VisitPointers(Object** start, Object** end) {
696 // The space must be new space. Any other space would cause ReadChunk to try 696 // The space must be new space. Any other space would cause ReadChunk to try
697 // to update the remembered using NULL as the address. 697 // to update the remembered using NULL as the address.
698 ReadChunk(start, end, NEW_SPACE, NULL); 698 ReadChunk(NULL, start, end, NEW_SPACE, NULL);
699 } 699 }
700 700
701 701
702 // This routine writes the new object into the pointer provided and then 702 // This routine writes the new object into the pointer provided and then
703 // returns true if the new object was in young space and false otherwise. 703 // returns true if the new object was in young space and false otherwise.
704 // The reason for this strange interface is that otherwise the object is 704 // The reason for this strange interface is that otherwise the object is
705 // written very late, which means the FreeSpace map is not set up by the 705 // written very late, which means the FreeSpace map is not set up by the
706 // time we need to use it to mark the space at the end of a page free. 706 // time we need to use it to mark the space at the end of a page free.
707 void Deserializer::ReadObject(int space_number, 707 void Deserializer::ReadObject(int space_number,
708 Space* space, 708 Space* space,
709 Object** write_back) { 709 Object** write_back) {
710 int size = source_->GetInt() << kObjectAlignmentBits; 710 int size = source_->GetInt() << kObjectAlignmentBits;
711 Address address = Allocate(space_number, space, size); 711 Address address = Allocate(space_number, space, size);
712 *write_back = HeapObject::FromAddress(address); 712 HeapObject* new_object = HeapObject::FromAddress(address);
713 *write_back = new_object;
713 Object** current = reinterpret_cast<Object**>(address); 714 Object** current = reinterpret_cast<Object**>(address);
714 Object** limit = current + (size >> kPointerSizeLog2); 715 Object** limit = current + (size >> kPointerSizeLog2);
715 if (FLAG_log_snapshot_positions) { 716 if (FLAG_log_snapshot_positions) {
716 LOG(isolate_, SnapshotPositionEvent(address, source_->position())); 717 LOG(isolate_, SnapshotPositionEvent(address, source_->position()));
717 } 718 }
718 ReadChunk(current, limit, space_number, address); 719 ReadChunk(new_object, current, limit, space_number, address);
719 #ifdef DEBUG 720 #ifdef DEBUG
720 bool is_codespace = (space == HEAP->code_space()) || 721 bool is_codespace = (space == HEAP->code_space()) ||
721 ((space == HEAP->lo_space()) && (space_number == kLargeCode)); 722 ((space == HEAP->lo_space()) && (space_number == kLargeCode));
722 ASSERT(HeapObject::FromAddress(address)->IsCode() == is_codespace); 723 ASSERT(HeapObject::FromAddress(address)->IsCode() == is_codespace);
723 #endif 724 #endif
724 } 725 }
725 726
726 727
727 // This macro is always used with a constant argument so it should all fold 728 // This macro is always used with a constant argument so it should all fold
728 // away to almost nothing in the generated code. It might be nicer to do this 729 // away to almost nothing in the generated code. It might be nicer to do this
(...skipping 14 matching lines...) Expand all
743 dest_space = isolate->heap()->cell_space(); \ 744 dest_space = isolate->heap()->cell_space(); \
744 } else { \ 745 } else { \
745 ASSERT(space_number >= LO_SPACE); \ 746 ASSERT(space_number >= LO_SPACE); \
746 dest_space = isolate->heap()->lo_space(); \ 747 dest_space = isolate->heap()->lo_space(); \
747 } 748 }
748 749
749 750
750 static const int kUnknownOffsetFromStart = -1; 751 static const int kUnknownOffsetFromStart = -1;
751 752
752 753
753 void Deserializer::ReadChunk(Object** current, 754 void Deserializer::ReadChunk(HeapObject* host,
755 Object** current,
754 Object** limit, 756 Object** limit,
755 int source_space, 757 int source_space,
756 Address address) { 758 Address address) {
757 Isolate* const isolate = isolate_; 759 Isolate* const isolate = isolate_;
758 while (current < limit) { 760 while (current < limit) {
759 int data = source_->Get(); 761 int data = source_->Get();
760 switch (data) { 762 switch (data) {
761 #define CASE_STATEMENT(where, how, within, space_number) \ 763 #define CASE_STATEMENT(where, how, within, space_number) \
762 case where + how + within + space_number: \ 764 case where + how + within + space_number: \
763 ASSERT((where & ~kPointedToMask) == 0); \ 765 ASSERT((where & ~kPointedToMask) == 0); \
764 ASSERT((how & ~kHowToCodeMask) == 0); \ 766 ASSERT((how & ~kHowToCodeMask) == 0); \
765 ASSERT((within & ~kWhereToPointMask) == 0); \ 767 ASSERT((within & ~kWhereToPointMask) == 0); \
766 ASSERT((space_number & ~kSpaceMask) == 0); 768 ASSERT((space_number & ~kSpaceMask) == 0);
767 769
768 #define CASE_BODY(where, how, within, space_number_if_any, offset_from_start) \ 770 #define CASE_BODY(where, how, within, space_number_if_any, offset_from_start) \
769 { \ 771 { \
770 bool emit_write_barrier = false; \ 772 bool emit_write_barrier = false; \
771 bool current_was_incremented = false; \ 773 bool current_was_incremented = false; \
774 bool cell_was_written = false; \
772 int space_number = space_number_if_any == kAnyOldSpace ? \ 775 int space_number = space_number_if_any == kAnyOldSpace ? \
773 (data & kSpaceMask) : space_number_if_any; \ 776 (data & kSpaceMask) : space_number_if_any; \
774 if (where == kNewObject && how == kPlain && within == kStartOfObject) {\ 777 if (where == kNewObject && how == kPlain && within == kStartOfObject) {\
775 ASSIGN_DEST_SPACE(space_number) \ 778 ASSIGN_DEST_SPACE(space_number) \
776 ReadObject(space_number, dest_space, current); \ 779 ReadObject(space_number, dest_space, current); \
777 emit_write_barrier = (space_number == NEW_SPACE && \ 780 emit_write_barrier = (space_number == NEW_SPACE && \
778 source_space != NEW_SPACE && \ 781 source_space != NEW_SPACE && \
779 source_space != CELL_SPACE); \ 782 source_space != CELL_SPACE); \
780 } else { \ 783 } else { \
781 Object* new_object = NULL; /* May not be a real Object pointer. */ \ 784 Object* new_object = NULL; /* May not be a real Object pointer. */ \
782 if (where == kNewObject) { \ 785 if (where == kNewObject) { \
783 ASSIGN_DEST_SPACE(space_number) \ 786 ASSIGN_DEST_SPACE(space_number) \
784 ReadObject(space_number, dest_space, &new_object); \ 787 ReadObject(space_number, dest_space, &new_object); \
785 } else if (where == kRootArray) { \ 788 } else if (where == kRootArray || where == kPartialSnapshotCache) { \
786 int root_id = source_->GetInt(); \ 789 if (where == kRootArray) { \
787 new_object = isolate->heap()->roots_array_start()[root_id]; \ 790 int root_id = source_->GetInt(); \
788 } else if (where == kPartialSnapshotCache) { \ 791 new_object = isolate->heap()->roots_array_start()[root_id]; \
789 int cache_index = source_->GetInt(); \ 792 } else { \
790 new_object = isolate->serialize_partial_snapshot_cache() \ 793 ASSERT(where == kPartialSnapshotCache); \
791 [cache_index]; \ 794 int cache_index = source_->GetInt(); \
795 new_object = isolate->serialize_partial_snapshot_cache() \
796 [cache_index]; \
797 } \
798 if (how != kFromCode) { \
799 cell_was_written = true; \
800 if (within == kFirstInstruction) { \
801 Code* new_code_object = reinterpret_cast<Code*>(new_object); \
802 new_object = reinterpret_cast<Object*>( \
803 new_code_object->instruction_start()); \
804 *current = new_object; \
805 isolate->heap()->incremental_marking()->RecordWriteOfCodeEntry(\
806 reinterpret_cast<JSFunction*>(host), \
807 current, \
808 new_code_object); \
809 } else { \
810 ASSERT(within == kStartOfObject); \
811 *current = new_object; \
812 isolate->heap()->incremental_marking()->RecordWrite( \
813 host, current, new_object); \
814 } \
815 } \
792 } else if (where == kExternalReference) { \ 816 } else if (where == kExternalReference) { \
793 int reference_id = source_->GetInt(); \ 817 int reference_id = source_->GetInt(); \
794 Address address = external_reference_decoder_-> \ 818 Address address = external_reference_decoder_-> \
795 Decode(reference_id); \ 819 Decode(reference_id); \
796 new_object = reinterpret_cast<Object*>(address); \ 820 new_object = reinterpret_cast<Object*>(address); \
797 } else if (where == kBackref) { \ 821 } else if (where == kBackref) { \
798 emit_write_barrier = (space_number == NEW_SPACE && \ 822 emit_write_barrier = (space_number == NEW_SPACE && \
799 source_space != NEW_SPACE && \ 823 source_space != NEW_SPACE && \
800 source_space != CELL_SPACE); \ 824 source_space != CELL_SPACE); \
801 new_object = GetAddressFromEnd(data & kSpaceMask); \ 825 new_object = GetAddressFromEnd(data & kSpaceMask); \
(...skipping 19 matching lines...) Expand all
821 Address location_of_branch_data = \ 845 Address location_of_branch_data = \
822 reinterpret_cast<Address>(current); \ 846 reinterpret_cast<Address>(current); \
823 Assembler::set_target_at(location_of_branch_data, \ 847 Assembler::set_target_at(location_of_branch_data, \
824 reinterpret_cast<Address>(new_object)); \ 848 reinterpret_cast<Address>(new_object)); \
825 if (within == kFirstInstruction) { \ 849 if (within == kFirstInstruction) { \
826 location_of_branch_data += Assembler::kCallTargetSize; \ 850 location_of_branch_data += Assembler::kCallTargetSize; \
827 current = reinterpret_cast<Object**>(location_of_branch_data); \ 851 current = reinterpret_cast<Object**>(location_of_branch_data); \
828 current_was_incremented = true; \ 852 current_was_incremented = true; \
829 } \ 853 } \
830 } else { \ 854 } else { \
831 *current = new_object; \ 855 if (!cell_was_written) *current = new_object; \
832 } \ 856 } \
833 } \ 857 } \
834 if (emit_write_barrier) { \ 858 if (emit_write_barrier) { \
835 isolate->heap()->RecordWrite(address, static_cast<int>( \ 859 isolate->heap()->RecordWrite(address, static_cast<int>( \
836 reinterpret_cast<Address>(current) - address)); \ 860 reinterpret_cast<Address>(current) - address)); \
837 } \ 861 } \
838 if (!current_was_incremented) { \ 862 if (!current_was_incremented) { \
839 current++; /* Increment current if it wasn't done above. */ \ 863 current++; /* Increment current if it wasn't done above. */ \
840 } \ 864 } \
841 break; \ 865 break; \
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 } 949 }
926 950
927 case kRepeat: { 951 case kRepeat: {
928 int repeats = source_->GetInt(); 952 int repeats = source_->GetInt();
929 Object* object = current[-1]; 953 Object* object = current[-1];
930 for (int i = 0; i < repeats; i++) current[i] = object; 954 for (int i = 0; i < repeats; i++) current[i] = object;
931 current += repeats; 955 current += repeats;
932 break; 956 break;
933 } 957 }
934 958
959 STATIC_ASSERT(kRootArrayNumberOfConstantEncodings ==
960 Heap::kOldSpaceRoots);
935 STATIC_ASSERT(kMaxRepeats == 12); 961 STATIC_ASSERT(kMaxRepeats == 12);
936 FOUR_CASES(kConstantRepeat) 962 FOUR_CASES(kConstantRepeat)
937 FOUR_CASES(kConstantRepeat + 4) 963 FOUR_CASES(kConstantRepeat + 4)
938 FOUR_CASES(kConstantRepeat + 8) { 964 FOUR_CASES(kConstantRepeat + 8) {
939 int repeats = RepeatsForCode(data); 965 int repeats = RepeatsForCode(data);
940 Object* object = current[-1]; 966 Object* object = current[-1];
941 for (int i = 0; i < repeats; i++) current[i] = object; 967 for (int i = 0; i < repeats; i++) current[i] = object;
942 current += repeats; 968 current += repeats;
943 break; 969 break;
944 } 970 }
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
1418 1444
1419 1445
1420 void Serializer::ObjectSerializer::VisitPointers(Object** start, 1446 void Serializer::ObjectSerializer::VisitPointers(Object** start,
1421 Object** end) { 1447 Object** end) {
1422 Object** current = start; 1448 Object** current = start;
1423 while (current < end) { 1449 while (current < end) {
1424 while (current < end && (*current)->IsSmi()) current++; 1450 while (current < end && (*current)->IsSmi()) current++;
1425 if (current < end) OutputRawData(reinterpret_cast<Address>(current)); 1451 if (current < end) OutputRawData(reinterpret_cast<Address>(current));
1426 1452
1427 while (current < end && !(*current)->IsSmi()) { 1453 while (current < end && !(*current)->IsSmi()) {
1454 HeapObject* current_contents = HeapObject::cast(*current);
1455 int root_index = serializer_->RootIndex(current_contents);
1456 // Repeats are not subject to the write barrier so there are only some
1457 // objects that can be used in a repeat encoding. These are the early
1458 // ones in the root array that are on the first page and never in new
1459 // space.
1428 if (current != start && 1460 if (current != start &&
1429 current[0] == current[-1] && 1461 root_index != kInvalidRootIndex &&
1430 !HEAP->InNewSpace(*current)) { 1462 root_index < kRootArrayNumberOfConstantEncodings &&
1463 current_contents == current[-1] &&
1464 !HEAP->InNewSpace(current_contents)) {
1431 int repeat_count = 1; 1465 int repeat_count = 1;
1432 while (current < end - 1 && current[repeat_count] == current[0]) { 1466 while (current < end - 1 && current[repeat_count] == current_contents) {
1433 repeat_count++; 1467 repeat_count++;
1434 } 1468 }
1435 current += repeat_count; 1469 current += repeat_count;
1436 bytes_processed_so_far_ += repeat_count * kPointerSize; 1470 bytes_processed_so_far_ += repeat_count * kPointerSize;
1437 if (repeat_count > kMaxRepeats) { 1471 if (repeat_count > kMaxRepeats) {
1438 sink_->Put(kRepeat, "SerializeRepeats"); 1472 sink_->Put(kRepeat, "SerializeRepeats");
1439 sink_->PutInt(repeat_count, "SerializeRepeats"); 1473 sink_->PutInt(repeat_count, "SerializeRepeats");
1440 } else { 1474 } else {
1441 sink_->Put(CodeForRepeats(repeat_count), "SerializeRepeats"); 1475 sink_->Put(CodeForRepeats(repeat_count), "SerializeRepeats");
1442 } 1476 }
1443 } else { 1477 } else {
1444 serializer_->SerializeObject(*current, kPlain, kStartOfObject); 1478 serializer_->SerializeObject(current_contents, kPlain, kStartOfObject);
1445 bytes_processed_so_far_ += kPointerSize; 1479 bytes_processed_so_far_ += kPointerSize;
1446 current++; 1480 current++;
1447 } 1481 }
1448 } 1482 }
1449 } 1483 }
1450 } 1484 }
1451 1485
1452 1486
1453 void Serializer::ObjectSerializer::VisitExternalReferences(Address* start, 1487 void Serializer::ObjectSerializer::VisitExternalReferences(Address* start,
1454 Address* end) { 1488 Address* end) {
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
1621 fullness_[space] = RoundUp(fullness_[space], Page::kPageSize); 1655 fullness_[space] = RoundUp(fullness_[space], Page::kPageSize);
1622 } 1656 }
1623 } 1657 }
1624 int allocation_address = fullness_[space]; 1658 int allocation_address = fullness_[space];
1625 fullness_[space] = allocation_address + size; 1659 fullness_[space] = allocation_address + size;
1626 return allocation_address; 1660 return allocation_address;
1627 } 1661 }
1628 1662
1629 1663
1630 } } // namespace v8::internal 1664 } } // namespace v8::internal
OLDNEW
« src/heap-inl.h ('K') | « src/serialize.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698