OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |