Chromium Code Reviews| 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 789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 800 } | 800 } |
| 801 return obj; | 801 return obj; |
| 802 } | 802 } |
| 803 | 803 |
| 804 | 804 |
| 805 // This routine writes the new object into the pointer provided and then | 805 // This routine writes the new object into the pointer provided and then |
| 806 // returns true if the new object was in young space and false otherwise. | 806 // returns true if the new object was in young space and false otherwise. |
| 807 // The reason for this strange interface is that otherwise the object is | 807 // The reason for this strange interface is that otherwise the object is |
| 808 // written very late, which means the FreeSpace map is not set up by the | 808 // written very late, which means the FreeSpace map is not set up by the |
| 809 // time we need to use it to mark the space at the end of a page free. | 809 // time we need to use it to mark the space at the end of a page free. |
| 810 void Deserializer::ReadObject(int space_number, | 810 void Deserializer::ReadObject(int space_number, Object** write_back, |
| 811 Object** write_back) { | 811 bool double_align) { |
| 812 int size = source_->GetInt() << kObjectAlignmentBits; | 812 int size = source_->GetInt() << kObjectAlignmentBits; |
| 813 Address address = Allocate(space_number, size); | 813 Address address; |
| 814 HeapObject* obj = HeapObject::FromAddress(address); | 814 HeapObject* obj; |
| 815 if (double_align) { | |
| 816 DCHECK_NE(LO_SPACE, space_number); | |
| 817 address = Allocate(space_number, size + kPointerSize); | |
|
rmcilroy
2014/11/26 17:44:40
You should only need to add kPointerSize if not a
Yang
2014/11/26 18:59:49
I think this entire if-branch can be omitted for 6
rmcilroy
2014/11/26 19:24:46
agreed.
| |
| 818 obj = isolate_->heap()->DoubleAlignForDeserialization( | |
| 819 HeapObject::FromAddress(address), size + kPointerSize); | |
| 820 address = obj->address(); | |
| 821 } else { | |
| 822 address = Allocate(space_number, size); | |
| 823 obj = HeapObject::FromAddress(address); | |
| 824 } | |
| 815 isolate_->heap()->OnAllocationEvent(obj, size); | 825 isolate_->heap()->OnAllocationEvent(obj, size); |
| 816 Object** current = reinterpret_cast<Object**>(address); | 826 Object** current = reinterpret_cast<Object**>(address); |
| 817 Object** limit = current + (size >> kPointerSizeLog2); | 827 Object** limit = current + (size >> kPointerSizeLog2); |
| 818 if (FLAG_log_snapshot_positions) { | 828 if (FLAG_log_snapshot_positions) { |
| 819 LOG(isolate_, SnapshotPositionEvent(address, source_->position())); | 829 LOG(isolate_, SnapshotPositionEvent(address, source_->position())); |
| 820 } | 830 } |
| 821 ReadData(current, limit, space_number, address); | 831 ReadData(current, limit, space_number, address); |
| 822 | 832 |
| 823 // TODO(mvstanton): consider treating the heap()->allocation_sites_list() | 833 // TODO(mvstanton): consider treating the heap()->allocation_sites_list() |
| 824 // as a (weak) root. If this root is relocated correctly, | 834 // as a (weak) root. If this root is relocated correctly, |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 887 Isolate* const isolate = isolate_; | 897 Isolate* const isolate = isolate_; |
| 888 // Write barrier support costs around 1% in startup time. In fact there | 898 // Write barrier support costs around 1% in startup time. In fact there |
| 889 // are no new space objects in current boot snapshots, so it's not needed, | 899 // are no new space objects in current boot snapshots, so it's not needed, |
| 890 // but that may change. | 900 // but that may change. |
| 891 bool write_barrier_needed = (current_object_address != NULL && | 901 bool write_barrier_needed = (current_object_address != NULL && |
| 892 source_space != NEW_SPACE && | 902 source_space != NEW_SPACE && |
| 893 source_space != CELL_SPACE && | 903 source_space != CELL_SPACE && |
| 894 source_space != PROPERTY_CELL_SPACE && | 904 source_space != PROPERTY_CELL_SPACE && |
| 895 source_space != CODE_SPACE && | 905 source_space != CODE_SPACE && |
| 896 source_space != OLD_DATA_SPACE); | 906 source_space != OLD_DATA_SPACE); |
| 907 bool double_align_next_object = false; | |
| 897 while (current < limit) { | 908 while (current < limit) { |
| 898 int data = source_->Get(); | 909 int data = source_->Get(); |
| 899 switch (data) { | 910 switch (data) { |
| 900 #define CASE_STATEMENT(where, how, within, space_number) \ | 911 #define CASE_STATEMENT(where, how, within, space_number) \ |
| 901 case where + how + within + space_number: \ | 912 case where + how + within + space_number: \ |
| 902 STATIC_ASSERT((where & ~kPointedToMask) == 0); \ | 913 STATIC_ASSERT((where & ~kPointedToMask) == 0); \ |
| 903 STATIC_ASSERT((how & ~kHowToCodeMask) == 0); \ | 914 STATIC_ASSERT((how & ~kHowToCodeMask) == 0); \ |
| 904 STATIC_ASSERT((within & ~kWhereToPointMask) == 0); \ | 915 STATIC_ASSERT((within & ~kWhereToPointMask) == 0); \ |
| 905 STATIC_ASSERT((space_number & ~kSpaceMask) == 0); | 916 STATIC_ASSERT((space_number & ~kSpaceMask) == 0); |
| 906 | 917 |
| 907 #define CASE_BODY(where, how, within, space_number_if_any) \ | 918 #define CASE_BODY(where, how, within, space_number_if_any) \ |
| 908 { \ | 919 { \ |
| 909 bool emit_write_barrier = false; \ | 920 bool emit_write_barrier = false; \ |
| 910 bool current_was_incremented = false; \ | 921 bool current_was_incremented = false; \ |
| 911 int space_number = space_number_if_any == kAnyOldSpace \ | 922 int space_number = space_number_if_any == kAnyOldSpace \ |
| 912 ? (data & kSpaceMask) \ | 923 ? (data & kSpaceMask) \ |
| 913 : space_number_if_any; \ | 924 : space_number_if_any; \ |
| 925 DCHECK(!double_align_next_object || where == kNewObject); \ | |
| 914 if (where == kNewObject && how == kPlain && within == kStartOfObject) { \ | 926 if (where == kNewObject && how == kPlain && within == kStartOfObject) { \ |
| 915 ReadObject(space_number, current); \ | 927 ReadObject(space_number, current, double_align_next_object); \ |
| 928 double_align_next_object = false; \ | |
| 916 emit_write_barrier = (space_number == NEW_SPACE); \ | 929 emit_write_barrier = (space_number == NEW_SPACE); \ |
| 917 } else { \ | 930 } else { \ |
| 918 Object* new_object = NULL; /* May not be a real Object pointer. */ \ | 931 Object* new_object = NULL; /* May not be a real Object pointer. */ \ |
| 919 if (where == kNewObject) { \ | 932 if (where == kNewObject) { \ |
| 920 ReadObject(space_number, &new_object); \ | 933 ReadObject(space_number, &new_object, double_align_next_object); \ |
| 934 double_align_next_object = false; \ | |
| 921 } else if (where == kRootArray) { \ | 935 } else if (where == kRootArray) { \ |
| 922 int root_id = source_->GetInt(); \ | 936 int root_id = source_->GetInt(); \ |
| 923 new_object = isolate->heap()->roots_array_start()[root_id]; \ | 937 new_object = isolate->heap()->roots_array_start()[root_id]; \ |
| 924 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ | 938 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
| 925 } else if (where == kPartialSnapshotCache) { \ | 939 } else if (where == kPartialSnapshotCache) { \ |
| 926 int cache_index = source_->GetInt(); \ | 940 int cache_index = source_->GetInt(); \ |
| 927 new_object = isolate->serialize_partial_snapshot_cache()[cache_index]; \ | 941 new_object = isolate->serialize_partial_snapshot_cache()[cache_index]; \ |
| 928 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ | 942 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
| 929 } else if (where == kExternalReference) { \ | 943 } else if (where == kExternalReference) { \ |
| 930 int skip = source_->GetInt(); \ | 944 int skip = source_->GetInt(); \ |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1231 int index = source_->Get(); | 1245 int index = source_->Get(); |
| 1232 Vector<const char> source_vector = Natives::GetRawScriptSource(index); | 1246 Vector<const char> source_vector = Natives::GetRawScriptSource(index); |
| 1233 NativesExternalStringResource* resource = | 1247 NativesExternalStringResource* resource = |
| 1234 new NativesExternalStringResource(isolate->bootstrapper(), | 1248 new NativesExternalStringResource(isolate->bootstrapper(), |
| 1235 source_vector.start(), | 1249 source_vector.start(), |
| 1236 source_vector.length()); | 1250 source_vector.length()); |
| 1237 *current++ = reinterpret_cast<Object*>(resource); | 1251 *current++ = reinterpret_cast<Object*>(resource); |
| 1238 break; | 1252 break; |
| 1239 } | 1253 } |
| 1240 | 1254 |
| 1255 #ifndef V8_HOST_ARCH_64_BIT | |
| 1256 case kDoubleAlignPrefix: { | |
| 1257 DCHECK(!double_align_next_object); | |
| 1258 double_align_next_object = true; | |
| 1259 break; | |
| 1260 } | |
| 1261 #endif | |
| 1262 | |
| 1241 case kSynchronize: { | 1263 case kSynchronize: { |
| 1242 // If we get here then that indicates that you have a mismatch between | 1264 // If we get here then that indicates that you have a mismatch between |
| 1243 // the number of GC roots when serializing and deserializing. | 1265 // the number of GC roots when serializing and deserializing. |
| 1244 UNREACHABLE(); | 1266 UNREACHABLE(); |
| 1245 } | 1267 } |
| 1246 | 1268 |
| 1247 default: | 1269 default: |
| 1248 UNREACHABLE(); | 1270 UNREACHABLE(); |
| 1249 } | 1271 } |
| 1250 } | 1272 } |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1542 sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); | 1564 sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); |
| 1543 } | 1565 } |
| 1544 // Object has not yet been serialized. Serialize it here. | 1566 // Object has not yet been serialized. Serialize it here. |
| 1545 ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point); | 1567 ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point); |
| 1546 serializer.Serialize(); | 1568 serializer.Serialize(); |
| 1547 } | 1569 } |
| 1548 | 1570 |
| 1549 | 1571 |
| 1550 void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space, | 1572 void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space, |
| 1551 int size, Map* map) { | 1573 int size, Map* map) { |
| 1574 int reserved_size = size; | |
| 1575 // Objects on the large object space are always double-aligned. | |
| 1576 if (space != LO_SPACE && object_->NeedsToEnsureDoubleAlignment()) { | |
| 1577 sink_->Put(kDoubleAlignPrefix, "double align next object"); | |
| 1578 // Add wriggle room for double alignment padding. | |
| 1579 reserved_size += kPointerSize; | |
| 1580 } | |
| 1581 | |
| 1552 sink_->Put(kNewObject + reference_representation_ + space, | 1582 sink_->Put(kNewObject + reference_representation_ + space, |
| 1553 "ObjectSerialization"); | 1583 "ObjectSerialization"); |
| 1554 sink_->PutInt(size >> kObjectAlignmentBits, "Size in words"); | 1584 sink_->PutInt(size >> kObjectAlignmentBits, "Size in words"); |
| 1555 | 1585 |
| 1556 if (serializer_->code_address_map_) { | 1586 if (serializer_->code_address_map_) { |
| 1557 const char* code_name = | 1587 const char* code_name = |
| 1558 serializer_->code_address_map_->Lookup(object_->address()); | 1588 serializer_->code_address_map_->Lookup(object_->address()); |
| 1559 LOG(serializer_->isolate_, | 1589 LOG(serializer_->isolate_, |
| 1560 CodeNameEvent(object_->address(), sink_->Position(), code_name)); | 1590 CodeNameEvent(object_->address(), sink_->Position(), code_name)); |
| 1561 LOG(serializer_->isolate_, | 1591 LOG(serializer_->isolate_, |
| 1562 SnapshotPositionEvent(object_->address(), sink_->Position())); | 1592 SnapshotPositionEvent(object_->address(), sink_->Position())); |
| 1563 } | 1593 } |
| 1564 | 1594 |
| 1565 // Mark this object as already serialized. | 1595 // Mark this object as already serialized. |
| 1566 BackReference back_reference; | 1596 BackReference back_reference; |
| 1567 if (space == LO_SPACE) { | 1597 if (space == LO_SPACE) { |
| 1568 if (object_->IsCode()) { | 1598 if (object_->IsCode()) { |
| 1569 sink_->Put(EXECUTABLE, "executable large object"); | 1599 sink_->Put(EXECUTABLE, "executable large object"); |
| 1570 } else { | 1600 } else { |
| 1571 sink_->Put(NOT_EXECUTABLE, "not executable large object"); | 1601 sink_->Put(NOT_EXECUTABLE, "not executable large object"); |
| 1572 } | 1602 } |
| 1573 back_reference = serializer_->AllocateLargeObject(size); | 1603 back_reference = serializer_->AllocateLargeObject(size); |
| 1574 } else { | 1604 } else { |
| 1575 back_reference = serializer_->Allocate(space, size); | 1605 back_reference = serializer_->Allocate(space, reserved_size); |
| 1576 } | 1606 } |
| 1577 serializer_->back_reference_map()->Add(object_, back_reference); | 1607 serializer_->back_reference_map()->Add(object_, back_reference); |
| 1578 | 1608 |
| 1579 // Serialize the map (first word of the object). | 1609 // Serialize the map (first word of the object). |
| 1580 serializer_->SerializeObject(map, kPlain, kStartOfObject, 0); | 1610 serializer_->SerializeObject(map, kPlain, kStartOfObject, 0); |
| 1581 } | 1611 } |
| 1582 | 1612 |
| 1583 | 1613 |
| 1584 void Serializer::ObjectSerializer::SerializeExternalString() { | 1614 void Serializer::ObjectSerializer::SerializeExternalString() { |
| 1585 // Instead of serializing this as an external string, we serialize | 1615 // Instead of serializing this as an external string, we serialize |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1911 | 1941 |
| 1912 BackReference Serializer::AllocateLargeObject(int size) { | 1942 BackReference Serializer::AllocateLargeObject(int size) { |
| 1913 // Large objects are allocated one-by-one when deserializing. We do not | 1943 // Large objects are allocated one-by-one when deserializing. We do not |
| 1914 // have to keep track of multiple chunks. | 1944 // have to keep track of multiple chunks. |
| 1915 large_objects_total_size_ += size; | 1945 large_objects_total_size_ += size; |
| 1916 return BackReference::LargeObjectReference(seen_large_objects_index_++); | 1946 return BackReference::LargeObjectReference(seen_large_objects_index_++); |
| 1917 } | 1947 } |
| 1918 | 1948 |
| 1919 | 1949 |
| 1920 BackReference Serializer::Allocate(AllocationSpace space, int size) { | 1950 BackReference Serializer::Allocate(AllocationSpace space, int size) { |
| 1921 CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); | 1951 DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); |
| 1922 DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space))); | 1952 DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space))); |
| 1923 uint32_t new_chunk_size = pending_chunk_[space] + size; | 1953 uint32_t new_chunk_size = pending_chunk_[space] + size; |
| 1924 if (new_chunk_size > max_chunk_size(space)) { | 1954 if (new_chunk_size > max_chunk_size(space)) { |
| 1925 // The new chunk size would not fit onto a single page. Complete the | 1955 // The new chunk size would not fit onto a single page. Complete the |
| 1926 // current chunk and start a new one. | 1956 // current chunk and start a new one. |
| 1927 completed_chunks_[space].Add(pending_chunk_[space]); | 1957 completed_chunks_[space].Add(pending_chunk_[space]); |
| 1928 pending_chunk_[space] = 0; | 1958 pending_chunk_[space] = 0; |
| 1929 new_chunk_size = size; | 1959 new_chunk_size = size; |
| 1930 } | 1960 } |
| 1931 uint32_t offset = pending_chunk_[space]; | 1961 uint32_t offset = pending_chunk_[space]; |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2321 bool SerializedCodeData::IsSane(String* source) { | 2351 bool SerializedCodeData::IsSane(String* source) { |
| 2322 return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && | 2352 return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && |
| 2323 PayloadLength() >= SharedFunctionInfo::kSize; | 2353 PayloadLength() >= SharedFunctionInfo::kSize; |
| 2324 } | 2354 } |
| 2325 | 2355 |
| 2326 | 2356 |
| 2327 int SerializedCodeData::CheckSum(String* string) { | 2357 int SerializedCodeData::CheckSum(String* string) { |
| 2328 return Version::Hash() ^ string->length(); | 2358 return Version::Hash() ^ string->length(); |
| 2329 } | 2359 } |
| 2330 } } // namespace v8::internal | 2360 } } // namespace v8::internal |
| OLD | NEW |