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 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
711 address_to_name_map_.Insert(code->address(), name, length); | 711 address_to_name_map_.Insert(code->address(), name, length); |
712 } | 712 } |
713 | 713 |
714 NameMap address_to_name_map_; | 714 NameMap address_to_name_map_; |
715 Isolate* isolate_; | 715 Isolate* isolate_; |
716 }; | 716 }; |
717 | 717 |
718 | 718 |
719 Deserializer::Deserializer(SnapshotByteSource* source) | 719 Deserializer::Deserializer(SnapshotByteSource* source) |
720 : isolate_(NULL), | 720 : isolate_(NULL), |
| 721 deserialize_code_(false), |
721 source_(source), | 722 source_(source), |
722 external_reference_decoder_(NULL) { | 723 external_reference_decoder_(NULL) { |
723 for (int i = 0; i < LAST_SPACE + 1; i++) { | 724 for (int i = 0; i < LAST_SPACE + 1; i++) { |
724 reservations_[i] = kUninitializedReservation; | 725 reservations_[i] = kUninitializedReservation; |
725 } | 726 } |
726 } | 727 } |
727 | 728 |
728 | 729 |
729 void Deserializer::FlushICacheForNewCodeObjects() { | 730 void Deserializer::FlushICacheForNewCodeObjects() { |
730 PageIterator it(isolate_->heap()->code_space()); | 731 PageIterator it(isolate_->heap()->code_space()); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
825 void Deserializer::RelinkAllocationSite(AllocationSite* site) { | 826 void Deserializer::RelinkAllocationSite(AllocationSite* site) { |
826 if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { | 827 if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { |
827 site->set_weak_next(isolate_->heap()->undefined_value()); | 828 site->set_weak_next(isolate_->heap()->undefined_value()); |
828 } else { | 829 } else { |
829 site->set_weak_next(isolate_->heap()->allocation_sites_list()); | 830 site->set_weak_next(isolate_->heap()->allocation_sites_list()); |
830 } | 831 } |
831 isolate_->heap()->set_allocation_sites_list(site); | 832 isolate_->heap()->set_allocation_sites_list(site); |
832 } | 833 } |
833 | 834 |
834 | 835 |
| 836 // Used to insert a deserialized internalized string into the string table. |
| 837 class StringTableInsertionKey : public HashTableKey { |
| 838 public: |
| 839 explicit StringTableInsertionKey(String* string) |
| 840 : string_(string), hash_(HashForObject(string)) { |
| 841 ASSERT(string->IsInternalizedString()); |
| 842 } |
| 843 |
| 844 virtual bool IsMatch(Object* string) { |
| 845 // We know that all entries in a hash table had their hash keys created. |
| 846 // Use that knowledge to have fast failure. |
| 847 if (hash_ != HashForObject(string)) return false; |
| 848 // We want to compare the content of two internalized strings here. |
| 849 return string_->SlowEquals(String::cast(string)); |
| 850 } |
| 851 |
| 852 virtual uint32_t Hash() V8_OVERRIDE { return hash_; } |
| 853 |
| 854 virtual uint32_t HashForObject(Object* key) V8_OVERRIDE { |
| 855 return String::cast(key)->Hash(); |
| 856 } |
| 857 |
| 858 MUST_USE_RESULT virtual Handle<Object> AsHandle(Isolate* isolate) |
| 859 V8_OVERRIDE { |
| 860 return handle(string_, isolate); |
| 861 } |
| 862 |
| 863 String* string_; |
| 864 uint32_t hash_; |
| 865 }; |
| 866 |
| 867 |
| 868 HeapObject* Deserializer::ProcessObjectFromSerializedCode(HeapObject* obj) { |
| 869 if (obj->IsString()) { |
| 870 String* string = String::cast(obj); |
| 871 // Uninitialize hash field as the hash seed may have changed. |
| 872 string->set_hash_field(String::kEmptyHashField); |
| 873 if (string->IsInternalizedString()) { |
| 874 DisallowHeapAllocation no_gc; |
| 875 HandleScope scope(isolate_); |
| 876 StringTableInsertionKey key(string); |
| 877 return *StringTable::LookupKey(isolate_, &key); |
| 878 } |
| 879 } |
| 880 return obj; |
| 881 } |
| 882 |
| 883 |
835 // This routine writes the new object into the pointer provided and then | 884 // This routine writes the new object into the pointer provided and then |
836 // returns true if the new object was in young space and false otherwise. | 885 // returns true if the new object was in young space and false otherwise. |
837 // The reason for this strange interface is that otherwise the object is | 886 // The reason for this strange interface is that otherwise the object is |
838 // written very late, which means the FreeSpace map is not set up by the | 887 // written very late, which means the FreeSpace map is not set up by the |
839 // time we need to use it to mark the space at the end of a page free. | 888 // time we need to use it to mark the space at the end of a page free. |
840 void Deserializer::ReadObject(int space_number, | 889 void Deserializer::ReadObject(int space_number, |
841 Object** write_back) { | 890 Object** write_back) { |
842 int size = source_->GetInt() << kObjectAlignmentBits; | 891 int size = source_->GetInt() << kObjectAlignmentBits; |
843 Address address = Allocate(space_number, size); | 892 Address address = Allocate(space_number, size); |
844 HeapObject* obj = HeapObject::FromAddress(address); | 893 HeapObject* obj = HeapObject::FromAddress(address); |
845 isolate_->heap()->OnAllocationEvent(obj, size); | 894 isolate_->heap()->OnAllocationEvent(obj, size); |
846 *write_back = obj; | |
847 Object** current = reinterpret_cast<Object**>(address); | 895 Object** current = reinterpret_cast<Object**>(address); |
848 Object** limit = current + (size >> kPointerSizeLog2); | 896 Object** limit = current + (size >> kPointerSizeLog2); |
849 if (FLAG_log_snapshot_positions) { | 897 if (FLAG_log_snapshot_positions) { |
850 LOG(isolate_, SnapshotPositionEvent(address, source_->position())); | 898 LOG(isolate_, SnapshotPositionEvent(address, source_->position())); |
851 } | 899 } |
852 ReadChunk(current, limit, space_number, address); | 900 ReadChunk(current, limit, space_number, address); |
853 | 901 |
854 // TODO(mvstanton): consider treating the heap()->allocation_sites_list() | 902 // TODO(mvstanton): consider treating the heap()->allocation_sites_list() |
855 // as a (weak) root. If this root is relocated correctly, | 903 // as a (weak) root. If this root is relocated correctly, |
856 // RelinkAllocationSite() isn't necessary. | 904 // RelinkAllocationSite() isn't necessary. |
857 if (obj->IsAllocationSite()) { | 905 if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj)); |
858 RelinkAllocationSite(AllocationSite::cast(obj)); | |
859 } | |
860 | 906 |
| 907 // Fix up strings from serialized user code. |
| 908 if (deserialize_code_) obj = ProcessObjectFromSerializedCode(obj); |
| 909 |
| 910 *write_back = obj; |
861 #ifdef DEBUG | 911 #ifdef DEBUG |
862 bool is_codespace = (space_number == CODE_SPACE); | 912 bool is_codespace = (space_number == CODE_SPACE); |
863 ASSERT(obj->IsCode() == is_codespace); | 913 ASSERT(obj->IsCode() == is_codespace); |
864 #endif | 914 #endif |
865 } | 915 } |
866 | 916 |
867 void Deserializer::ReadChunk(Object** current, | 917 void Deserializer::ReadChunk(Object** current, |
868 Object** limit, | 918 Object** limit, |
869 int source_space, | 919 int source_space, |
870 Address current_object_address) { | 920 Address current_object_address) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
914 int skip = source_->GetInt(); \ | 964 int skip = source_->GetInt(); \ |
915 current = reinterpret_cast<Object**>( \ | 965 current = reinterpret_cast<Object**>( \ |
916 reinterpret_cast<Address>(current) + skip); \ | 966 reinterpret_cast<Address>(current) + skip); \ |
917 int reference_id = source_->GetInt(); \ | 967 int reference_id = source_->GetInt(); \ |
918 Address address = external_reference_decoder_->Decode(reference_id); \ | 968 Address address = external_reference_decoder_->Decode(reference_id); \ |
919 new_object = reinterpret_cast<Object*>(address); \ | 969 new_object = reinterpret_cast<Object*>(address); \ |
920 } else if (where == kBackref) { \ | 970 } else if (where == kBackref) { \ |
921 emit_write_barrier = (space_number == NEW_SPACE); \ | 971 emit_write_barrier = (space_number == NEW_SPACE); \ |
922 new_object = GetAddressFromEnd(data & kSpaceMask); \ | 972 new_object = GetAddressFromEnd(data & kSpaceMask); \ |
923 } else if (where == kBuiltin) { \ | 973 } else if (where == kBuiltin) { \ |
| 974 ASSERT(deserialize_code_); \ |
924 int builtin_id = source_->GetInt(); \ | 975 int builtin_id = source_->GetInt(); \ |
925 ASSERT_LE(0, builtin_id); \ | 976 ASSERT_LE(0, builtin_id); \ |
926 ASSERT_LT(builtin_id, Builtins::builtin_count); \ | 977 ASSERT_LT(builtin_id, Builtins::builtin_count); \ |
927 Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ | 978 Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ |
928 new_object = isolate->builtins()->builtin(name); \ | 979 new_object = isolate->builtins()->builtin(name); \ |
929 emit_write_barrier = false; \ | 980 emit_write_barrier = false; \ |
930 PrintF("BUILTIN how within %d, %d\n", how, within); \ | |
931 } else { \ | 981 } else { \ |
932 ASSERT(where == kBackrefWithSkip); \ | 982 ASSERT(where == kBackrefWithSkip); \ |
933 int skip = source_->GetInt(); \ | 983 int skip = source_->GetInt(); \ |
934 current = reinterpret_cast<Object**>( \ | 984 current = reinterpret_cast<Object**>( \ |
935 reinterpret_cast<Address>(current) + skip); \ | 985 reinterpret_cast<Address>(current) + skip); \ |
936 emit_write_barrier = (space_number == NEW_SPACE); \ | 986 emit_write_barrier = (space_number == NEW_SPACE); \ |
937 new_object = GetAddressFromEnd(data & kSpaceMask); \ | 987 new_object = GetAddressFromEnd(data & kSpaceMask); \ |
938 } \ | 988 } \ |
939 if (within == kInnerPointer) { \ | 989 if (within == kInnerPointer) { \ |
940 if (space_number != CODE_SPACE || new_object->IsCode()) { \ | 990 if (space_number != CODE_SPACE || new_object->IsCode()) { \ |
(...skipping 911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1852 heap_object->GetHeap()->empty_fixed_array()); | 1902 heap_object->GetHeap()->empty_fixed_array()); |
1853 | 1903 |
1854 int root_index; | 1904 int root_index; |
1855 if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) { | 1905 if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) { |
1856 PutRoot(root_index, heap_object, how_to_code, where_to_point, skip); | 1906 PutRoot(root_index, heap_object, how_to_code, where_to_point, skip); |
1857 return; | 1907 return; |
1858 } | 1908 } |
1859 | 1909 |
1860 // TODO(yangguo) wire up stubs from stub cache. | 1910 // TODO(yangguo) wire up stubs from stub cache. |
1861 // TODO(yangguo) wire up script source. | 1911 // TODO(yangguo) wire up script source. |
1862 // TODO(yangguo) wire up internalized strings | |
1863 ASSERT(!heap_object->IsInternalizedString()); | |
1864 // TODO(yangguo) We cannot deal with different hash seeds yet. | 1912 // TODO(yangguo) We cannot deal with different hash seeds yet. |
1865 ASSERT(!heap_object->IsHashTable()); | 1913 ASSERT(!heap_object->IsHashTable()); |
1866 | 1914 |
1867 if (heap_object->IsCode()) { | 1915 if (heap_object->IsCode()) { |
1868 Code* code_object = Code::cast(heap_object); | 1916 Code* code_object = Code::cast(heap_object); |
1869 if (code_object->kind() == Code::BUILTIN) { | 1917 if (code_object->kind() == Code::BUILTIN) { |
1870 SerializeBuiltin(code_object, how_to_code, where_to_point, skip); | 1918 SerializeBuiltin(code_object, how_to_code, where_to_point, skip); |
1871 return; | 1919 return; |
1872 } | 1920 } |
1873 } | 1921 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1909 | 1957 |
1910 sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin"); | 1958 sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin"); |
1911 sink_->PutInt(id, "builtin_index"); | 1959 sink_->PutInt(id, "builtin_index"); |
1912 } | 1960 } |
1913 | 1961 |
1914 | 1962 |
1915 Object* CodeSerializer::Deserialize(Isolate* isolate, ScriptData* data) { | 1963 Object* CodeSerializer::Deserialize(Isolate* isolate, ScriptData* data) { |
1916 SerializedCodeData scd(data); | 1964 SerializedCodeData scd(data); |
1917 SnapshotByteSource payload(scd.Payload(), scd.PayloadLength()); | 1965 SnapshotByteSource payload(scd.Payload(), scd.PayloadLength()); |
1918 Deserializer deserializer(&payload); | 1966 Deserializer deserializer(&payload); |
| 1967 deserializer.ExpectSerializedCode(); |
1919 STATIC_ASSERT(NEW_SPACE == 0); | 1968 STATIC_ASSERT(NEW_SPACE == 0); |
1920 // TODO(yangguo) what happens if remaining new space is too small? | 1969 // TODO(yangguo) what happens if remaining new space is too small? |
1921 for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) { | 1970 for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) { |
1922 deserializer.set_reservation(i, scd.GetReservation(i)); | 1971 deserializer.set_reservation(i, scd.GetReservation(i)); |
1923 } | 1972 } |
1924 Object* root; | 1973 Object* root; |
1925 deserializer.DeserializePartial(isolate, &root); | 1974 deserializer.DeserializePartial(isolate, &root); |
1926 deserializer.FlushICacheForNewCodeObjects(); | 1975 deserializer.FlushICacheForNewCodeObjects(); |
1927 ASSERT(root->IsSharedFunctionInfo()); | 1976 ASSERT(root->IsSharedFunctionInfo()); |
1928 return root; | 1977 return root; |
(...skipping 15 matching lines...) Expand all Loading... |
1944 SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i)); | 1993 SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i)); |
1945 } | 1994 } |
1946 } | 1995 } |
1947 | 1996 |
1948 | 1997 |
1949 bool SerializedCodeData::IsSane() { | 1998 bool SerializedCodeData::IsSane() { |
1950 return GetHeaderValue(kVersionHashOffset) == Version::Hash() && | 1999 return GetHeaderValue(kVersionHashOffset) == Version::Hash() && |
1951 PayloadLength() >= SharedFunctionInfo::kSize; | 2000 PayloadLength() >= SharedFunctionInfo::kSize; |
1952 } | 2001 } |
1953 } } // namespace v8::internal | 2002 } } // namespace v8::internal |
OLD | NEW |