OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/base/platform/platform.h" | 9 #include "src/base/platform/platform.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
882 int data = source_->Get(); | 882 int data = source_->Get(); |
883 switch (data) { | 883 switch (data) { |
884 #define CASE_STATEMENT(where, how, within, space_number) \ | 884 #define CASE_STATEMENT(where, how, within, space_number) \ |
885 case where + how + within + space_number: \ | 885 case where + how + within + space_number: \ |
886 STATIC_ASSERT((where & ~kPointedToMask) == 0); \ | 886 STATIC_ASSERT((where & ~kPointedToMask) == 0); \ |
887 STATIC_ASSERT((how & ~kHowToCodeMask) == 0); \ | 887 STATIC_ASSERT((how & ~kHowToCodeMask) == 0); \ |
888 STATIC_ASSERT((within & ~kWhereToPointMask) == 0); \ | 888 STATIC_ASSERT((within & ~kWhereToPointMask) == 0); \ |
889 STATIC_ASSERT((space_number & ~kSpaceMask) == 0); | 889 STATIC_ASSERT((space_number & ~kSpaceMask) == 0); |
890 | 890 |
891 #define CASE_BODY(where, how, within, space_number_if_any) \ | 891 #define CASE_BODY(where, how, within, space_number_if_any) \ |
892 { \ | 892 { \ |
893 bool emit_write_barrier = false; \ | 893 bool emit_write_barrier = false; \ |
894 bool current_was_incremented = false; \ | 894 bool current_was_incremented = false; \ |
895 int space_number = space_number_if_any == kAnyOldSpace ? \ | 895 int space_number = space_number_if_any == kAnyOldSpace \ |
896 (data & kSpaceMask) : space_number_if_any; \ | 896 ? (data & kSpaceMask) \ |
897 if (where == kNewObject && how == kPlain && within == kStartOfObject) {\ | 897 : space_number_if_any; \ |
898 ReadObject(space_number, current); \ | 898 if (where == kNewObject && how == kPlain && within == kStartOfObject) { \ |
899 emit_write_barrier = (space_number == NEW_SPACE); \ | 899 ReadObject(space_number, current); \ |
| 900 emit_write_barrier = (space_number == NEW_SPACE); \ |
| 901 } else { \ |
| 902 Object* new_object = NULL; /* May not be a real Object pointer. */ \ |
| 903 if (where == kNewObject) { \ |
| 904 ReadObject(space_number, &new_object); \ |
| 905 } else if (where == kRootArray) { \ |
| 906 int root_id = source_->GetInt(); \ |
| 907 new_object = isolate->heap()->roots_array_start()[root_id]; \ |
| 908 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
| 909 } else if (where == kPartialSnapshotCache) { \ |
| 910 int cache_index = source_->GetInt(); \ |
| 911 new_object = isolate->serialize_partial_snapshot_cache()[cache_index]; \ |
| 912 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
| 913 } else if (where == kExternalReference) { \ |
| 914 int skip = source_->GetInt(); \ |
| 915 current = reinterpret_cast<Object**>( \ |
| 916 reinterpret_cast<Address>(current) + skip); \ |
| 917 int reference_id = source_->GetInt(); \ |
| 918 Address address = external_reference_decoder_->Decode(reference_id); \ |
| 919 new_object = reinterpret_cast<Object*>(address); \ |
| 920 } else if (where == kBackref) { \ |
| 921 emit_write_barrier = (space_number == NEW_SPACE); \ |
| 922 new_object = GetAddressFromEnd(data & kSpaceMask); \ |
| 923 } else if (where == kBuiltin) { \ |
| 924 int builtin_id = source_->GetInt(); \ |
| 925 ASSERT_LE(0, builtin_id); \ |
| 926 ASSERT_LT(builtin_id, Builtins::builtin_count); \ |
| 927 Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ |
| 928 new_object = isolate->builtins()->builtin(name); \ |
| 929 emit_write_barrier = false; \ |
| 930 PrintF("BUILTIN how within %d, %d\n", how, within); \ |
| 931 } else { \ |
| 932 ASSERT(where == kBackrefWithSkip); \ |
| 933 int skip = source_->GetInt(); \ |
| 934 current = reinterpret_cast<Object**>( \ |
| 935 reinterpret_cast<Address>(current) + skip); \ |
| 936 emit_write_barrier = (space_number == NEW_SPACE); \ |
| 937 new_object = GetAddressFromEnd(data & kSpaceMask); \ |
| 938 } \ |
| 939 if (within == kInnerPointer) { \ |
| 940 if (space_number != CODE_SPACE || new_object->IsCode()) { \ |
| 941 Code* new_code_object = reinterpret_cast<Code*>(new_object); \ |
| 942 new_object = \ |
| 943 reinterpret_cast<Object*>(new_code_object->instruction_start()); \ |
900 } else { \ | 944 } else { \ |
901 Object* new_object = NULL; /* May not be a real Object pointer. */ \ | 945 ASSERT(space_number == CODE_SPACE); \ |
902 if (where == kNewObject) { \ | 946 Cell* cell = Cell::cast(new_object); \ |
903 ReadObject(space_number, &new_object); \ | 947 new_object = reinterpret_cast<Object*>(cell->ValueAddress()); \ |
904 } else if (where == kRootArray) { \ | |
905 int root_id = source_->GetInt(); \ | |
906 new_object = isolate->heap()->roots_array_start()[root_id]; \ | |
907 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ | |
908 } else if (where == kPartialSnapshotCache) { \ | |
909 int cache_index = source_->GetInt(); \ | |
910 new_object = isolate->serialize_partial_snapshot_cache() \ | |
911 [cache_index]; \ | |
912 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ | |
913 } else if (where == kExternalReference) { \ | |
914 int skip = source_->GetInt(); \ | |
915 current = reinterpret_cast<Object**>(reinterpret_cast<Address>( \ | |
916 current) + skip); \ | |
917 int reference_id = source_->GetInt(); \ | |
918 Address address = external_reference_decoder_-> \ | |
919 Decode(reference_id); \ | |
920 new_object = reinterpret_cast<Object*>(address); \ | |
921 } else if (where == kBackref) { \ | |
922 emit_write_barrier = (space_number == NEW_SPACE); \ | |
923 new_object = GetAddressFromEnd(data & kSpaceMask); \ | |
924 } else { \ | |
925 ASSERT(where == kBackrefWithSkip); \ | |
926 int skip = source_->GetInt(); \ | |
927 current = reinterpret_cast<Object**>( \ | |
928 reinterpret_cast<Address>(current) + skip); \ | |
929 emit_write_barrier = (space_number == NEW_SPACE); \ | |
930 new_object = GetAddressFromEnd(data & kSpaceMask); \ | |
931 } \ | |
932 if (within == kInnerPointer) { \ | |
933 if (space_number != CODE_SPACE || new_object->IsCode()) { \ | |
934 Code* new_code_object = reinterpret_cast<Code*>(new_object); \ | |
935 new_object = reinterpret_cast<Object*>( \ | |
936 new_code_object->instruction_start()); \ | |
937 } else { \ | |
938 ASSERT(space_number == CODE_SPACE); \ | |
939 Cell* cell = Cell::cast(new_object); \ | |
940 new_object = reinterpret_cast<Object*>( \ | |
941 cell->ValueAddress()); \ | |
942 } \ | |
943 } \ | |
944 if (how == kFromCode) { \ | |
945 Address location_of_branch_data = \ | |
946 reinterpret_cast<Address>(current); \ | |
947 Assembler::deserialization_set_special_target_at( \ | |
948 location_of_branch_data, \ | |
949 Code::cast(HeapObject::FromAddress(current_object_address)), \ | |
950 reinterpret_cast<Address>(new_object)); \ | |
951 location_of_branch_data += Assembler::kSpecialTargetSize; \ | |
952 current = reinterpret_cast<Object**>(location_of_branch_data); \ | |
953 current_was_incremented = true; \ | |
954 } else { \ | |
955 *current = new_object; \ | |
956 } \ | |
957 } \ | 948 } \ |
958 if (emit_write_barrier && write_barrier_needed) { \ | |
959 Address current_address = reinterpret_cast<Address>(current); \ | |
960 isolate->heap()->RecordWrite( \ | |
961 current_object_address, \ | |
962 static_cast<int>(current_address - current_object_address)); \ | |
963 } \ | |
964 if (!current_was_incremented) { \ | |
965 current++; \ | |
966 } \ | |
967 break; \ | |
968 } \ | 949 } \ |
| 950 if (how == kFromCode) { \ |
| 951 Address location_of_branch_data = reinterpret_cast<Address>(current); \ |
| 952 Assembler::deserialization_set_special_target_at( \ |
| 953 location_of_branch_data, \ |
| 954 Code::cast(HeapObject::FromAddress(current_object_address)), \ |
| 955 reinterpret_cast<Address>(new_object)); \ |
| 956 location_of_branch_data += Assembler::kSpecialTargetSize; \ |
| 957 current = reinterpret_cast<Object**>(location_of_branch_data); \ |
| 958 current_was_incremented = true; \ |
| 959 } else { \ |
| 960 *current = new_object; \ |
| 961 } \ |
| 962 } \ |
| 963 if (emit_write_barrier && write_barrier_needed) { \ |
| 964 Address current_address = reinterpret_cast<Address>(current); \ |
| 965 isolate->heap()->RecordWrite( \ |
| 966 current_object_address, \ |
| 967 static_cast<int>(current_address - current_object_address)); \ |
| 968 } \ |
| 969 if (!current_was_incremented) { \ |
| 970 current++; \ |
| 971 } \ |
| 972 break; \ |
| 973 } |
969 | 974 |
970 // This generates a case and a body for the new space (which has to do extra | 975 // This generates a case and a body for the new space (which has to do extra |
971 // write barrier handling) and handles the other spaces with 8 fall-through | 976 // write barrier handling) and handles the other spaces with 8 fall-through |
972 // cases and one body. | 977 // cases and one body. |
973 #define ALL_SPACES(where, how, within) \ | 978 #define ALL_SPACES(where, how, within) \ |
974 CASE_STATEMENT(where, how, within, NEW_SPACE) \ | 979 CASE_STATEMENT(where, how, within, NEW_SPACE) \ |
975 CASE_BODY(where, how, within, NEW_SPACE) \ | 980 CASE_BODY(where, how, within, NEW_SPACE) \ |
976 CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \ | 981 CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \ |
977 CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \ | 982 CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \ |
978 CASE_STATEMENT(where, how, within, CODE_SPACE) \ | 983 CASE_STATEMENT(where, how, within, CODE_SPACE) \ |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1154 kPlain, | 1159 kPlain, |
1155 kStartOfObject, | 1160 kStartOfObject, |
1156 0) | 1161 0) |
1157 // Find an external reference and write a pointer to it in the current | 1162 // Find an external reference and write a pointer to it in the current |
1158 // code object. | 1163 // code object. |
1159 CASE_STATEMENT(kExternalReference, kFromCode, kStartOfObject, 0) | 1164 CASE_STATEMENT(kExternalReference, kFromCode, kStartOfObject, 0) |
1160 CASE_BODY(kExternalReference, | 1165 CASE_BODY(kExternalReference, |
1161 kFromCode, | 1166 kFromCode, |
1162 kStartOfObject, | 1167 kStartOfObject, |
1163 0) | 1168 0) |
| 1169 // Find a builtin and write a pointer to it to the current object. |
| 1170 CASE_STATEMENT(kBuiltin, kPlain, kStartOfObject, 0) |
| 1171 CASE_BODY(kBuiltin, kPlain, kStartOfObject, 0) |
| 1172 // Find a builtin and write a pointer to it in the current code object. |
| 1173 CASE_STATEMENT(kBuiltin, kFromCode, kInnerPointer, 0) |
| 1174 CASE_BODY(kBuiltin, kFromCode, kInnerPointer, 0) |
1164 | 1175 |
1165 #undef CASE_STATEMENT | 1176 #undef CASE_STATEMENT |
1166 #undef CASE_BODY | 1177 #undef CASE_BODY |
1167 #undef ALL_SPACES | 1178 #undef ALL_SPACES |
1168 | 1179 |
1169 case kSkip: { | 1180 case kSkip: { |
1170 int size = source_->GetInt(); | 1181 int size = source_->GetInt(); |
1171 current = reinterpret_cast<Object**>( | 1182 current = reinterpret_cast<Object**>( |
1172 reinterpret_cast<intptr_t>(current) + size); | 1183 reinterpret_cast<intptr_t>(current) + size); |
1173 break; | 1184 break; |
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1710 } | 1721 } |
1711 | 1722 |
1712 | 1723 |
1713 int Serializer::ObjectSerializer::OutputRawData( | 1724 int Serializer::ObjectSerializer::OutputRawData( |
1714 Address up_to, Serializer::ObjectSerializer::ReturnSkip return_skip) { | 1725 Address up_to, Serializer::ObjectSerializer::ReturnSkip return_skip) { |
1715 Address object_start = object_->address(); | 1726 Address object_start = object_->address(); |
1716 int base = bytes_processed_so_far_; | 1727 int base = bytes_processed_so_far_; |
1717 int up_to_offset = static_cast<int>(up_to - object_start); | 1728 int up_to_offset = static_cast<int>(up_to - object_start); |
1718 int to_skip = up_to_offset - bytes_processed_so_far_; | 1729 int to_skip = up_to_offset - bytes_processed_so_far_; |
1719 int bytes_to_output = to_skip; | 1730 int bytes_to_output = to_skip; |
1720 bytes_processed_so_far_ += to_skip; | 1731 bytes_processed_so_far_ += to_skip; |
1721 // This assert will fail if the reloc info gives us the target_address_address | 1732 // This assert will fail if the reloc info gives us the target_address_address |
1722 // locations in a non-ascending order. Luckily that doesn't happen. | 1733 // locations in a non-ascending order. Luckily that doesn't happen. |
1723 ASSERT(to_skip >= 0); | 1734 ASSERT(to_skip >= 0); |
1724 bool outputting_code = false; | 1735 bool outputting_code = false; |
1725 if (to_skip != 0 && code_object_ && !code_has_been_output_) { | 1736 if (to_skip != 0 && code_object_ && !code_has_been_output_) { |
1726 // Output the code all at once and fix later. | 1737 // Output the code all at once and fix later. |
1727 bytes_to_output = object_->Size() + to_skip - bytes_processed_so_far_; | 1738 bytes_to_output = object_->Size() + to_skip - bytes_processed_so_far_; |
1728 outputting_code = true; | 1739 outputting_code = true; |
1729 code_has_been_output_ = true; | 1740 code_has_been_output_ = true; |
1730 } | 1741 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1839 ASSERT(!heap_object->IsMap() || | 1850 ASSERT(!heap_object->IsMap() || |
1840 Map::cast(heap_object)->code_cache() == | 1851 Map::cast(heap_object)->code_cache() == |
1841 heap_object->GetHeap()->empty_fixed_array()); | 1852 heap_object->GetHeap()->empty_fixed_array()); |
1842 | 1853 |
1843 int root_index; | 1854 int root_index; |
1844 if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) { | 1855 if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) { |
1845 PutRoot(root_index, heap_object, how_to_code, where_to_point, skip); | 1856 PutRoot(root_index, heap_object, how_to_code, where_to_point, skip); |
1846 return; | 1857 return; |
1847 } | 1858 } |
1848 | 1859 |
1849 // TODO(yangguo) wire up builtins. | |
1850 // TODO(yangguo) wire up stubs from stub cache. | 1860 // TODO(yangguo) wire up stubs from stub cache. |
1851 // TODO(yangguo) wire up script source. | 1861 // TODO(yangguo) wire up script source. |
1852 // TODO(yangguo) wire up internalized strings | 1862 // TODO(yangguo) wire up internalized strings |
1853 ASSERT(!heap_object->IsInternalizedString()); | 1863 ASSERT(!heap_object->IsInternalizedString()); |
1854 // TODO(yangguo) We cannot deal with different hash seeds yet. | 1864 // TODO(yangguo) We cannot deal with different hash seeds yet. |
1855 ASSERT(!heap_object->IsHashTable()); | 1865 ASSERT(!heap_object->IsHashTable()); |
1856 | 1866 |
| 1867 if (heap_object->IsCode()) { |
| 1868 Code* code_object = Code::cast(heap_object); |
| 1869 if (code_object->kind() == Code::BUILTIN) { |
| 1870 SerializeBuiltin(code_object, how_to_code, where_to_point, skip); |
| 1871 return; |
| 1872 } |
| 1873 } |
| 1874 |
1857 if (address_mapper_.IsMapped(heap_object)) { | 1875 if (address_mapper_.IsMapped(heap_object)) { |
1858 int space = SpaceOfObject(heap_object); | 1876 int space = SpaceOfObject(heap_object); |
1859 int address = address_mapper_.MappedTo(heap_object); | 1877 int address = address_mapper_.MappedTo(heap_object); |
1860 SerializeReferenceToPreviousObject(space, address, how_to_code, | 1878 SerializeReferenceToPreviousObject(space, address, how_to_code, |
1861 where_to_point, skip); | 1879 where_to_point, skip); |
1862 return; | 1880 return; |
1863 } | 1881 } |
1864 | 1882 |
1865 if (skip != 0) { | 1883 if (skip != 0) { |
1866 sink_->Put(kSkip, "SkipFromSerializeObject"); | 1884 sink_->Put(kSkip, "SkipFromSerializeObject"); |
1867 sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); | 1885 sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); |
1868 } | 1886 } |
1869 // Object has not yet been serialized. Serialize it here. | 1887 // Object has not yet been serialized. Serialize it here. |
1870 ObjectSerializer serializer(this, heap_object, sink_, how_to_code, | 1888 ObjectSerializer serializer(this, heap_object, sink_, how_to_code, |
1871 where_to_point); | 1889 where_to_point); |
1872 serializer.Serialize(); | 1890 serializer.Serialize(); |
1873 } | 1891 } |
1874 | 1892 |
1875 | 1893 |
| 1894 void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code, |
| 1895 WhereToPoint where_to_point, int skip) { |
| 1896 if (skip != 0) { |
| 1897 sink_->Put(kSkip, "SkipFromSerializeBuiltin"); |
| 1898 sink_->PutInt(skip, "SkipDistanceFromSerializeBuiltin"); |
| 1899 } |
| 1900 |
| 1901 ASSERT((how_to_code == kPlain && where_to_point == kStartOfObject) || |
| 1902 (how_to_code == kFromCode && where_to_point == kInnerPointer)); |
| 1903 int id = 0; |
| 1904 do { // Look for existing builtins in the list. |
| 1905 Code* b = isolate()->builtins()->builtin(static_cast<Builtins::Name>(id)); |
| 1906 if (builtin == b) break; |
| 1907 } while (++id < Builtins::builtin_count); |
| 1908 ASSERT(id < Builtins::builtin_count); // We must have found a one. |
| 1909 |
| 1910 sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin"); |
| 1911 sink_->PutInt(id, "builtin_index"); |
| 1912 } |
| 1913 |
| 1914 |
1876 Object* CodeSerializer::Deserialize(Isolate* isolate, ScriptData* data) { | 1915 Object* CodeSerializer::Deserialize(Isolate* isolate, ScriptData* data) { |
1877 SerializedCodeData scd(data); | 1916 SerializedCodeData scd(data); |
1878 SnapshotByteSource payload(scd.Payload(), scd.PayloadLength()); | 1917 SnapshotByteSource payload(scd.Payload(), scd.PayloadLength()); |
1879 Deserializer deserializer(&payload); | 1918 Deserializer deserializer(&payload); |
1880 STATIC_ASSERT(NEW_SPACE == 0); | 1919 STATIC_ASSERT(NEW_SPACE == 0); |
1881 // TODO(yangguo) what happens if remaining new space is too small? | 1920 // TODO(yangguo) what happens if remaining new space is too small? |
1882 for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) { | 1921 for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) { |
1883 deserializer.set_reservation(i, scd.GetReservation(i)); | 1922 deserializer.set_reservation(i, scd.GetReservation(i)); |
1884 } | 1923 } |
1885 Object* root; | 1924 Object* root; |
(...skipping 19 matching lines...) Expand all Loading... |
1905 SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i)); | 1944 SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i)); |
1906 } | 1945 } |
1907 } | 1946 } |
1908 | 1947 |
1909 | 1948 |
1910 bool SerializedCodeData::IsSane() { | 1949 bool SerializedCodeData::IsSane() { |
1911 return GetHeaderValue(kVersionHashOffset) == Version::Hash() && | 1950 return GetHeaderValue(kVersionHashOffset) == Version::Hash() && |
1912 PayloadLength() >= SharedFunctionInfo::kSize; | 1951 PayloadLength() >= SharedFunctionInfo::kSize; |
1913 } | 1952 } |
1914 } } // namespace v8::internal | 1953 } } // namespace v8::internal |
OLD | NEW |