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/snapshot/serialize.h" | 5 #include "src/snapshot/serialize.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 1354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1365 PrintF("%10d %10" V8_PTR_PREFIX "d %s\n", instance_type_count_[Name], \ | 1365 PrintF("%10d %10" V8_PTR_PREFIX "d %s\n", instance_type_count_[Name], \ |
1366 instance_type_size_[Name], #Name); \ | 1366 instance_type_size_[Name], #Name); \ |
1367 } | 1367 } |
1368 INSTANCE_TYPE_LIST(PRINT_INSTANCE_TYPE) | 1368 INSTANCE_TYPE_LIST(PRINT_INSTANCE_TYPE) |
1369 #undef PRINT_INSTANCE_TYPE | 1369 #undef PRINT_INSTANCE_TYPE |
1370 PrintF("\n"); | 1370 PrintF("\n"); |
1371 #endif // OBJECT_PRINT | 1371 #endif // OBJECT_PRINT |
1372 } | 1372 } |
1373 | 1373 |
1374 | 1374 |
| 1375 class Serializer::ObjectSerializer : public ObjectVisitor { |
| 1376 public: |
| 1377 ObjectSerializer(Serializer* serializer, Object* o, SnapshotByteSink* sink, |
| 1378 HowToCode how_to_code, WhereToPoint where_to_point) |
| 1379 : serializer_(serializer), |
| 1380 object_(HeapObject::cast(o)), |
| 1381 sink_(sink), |
| 1382 reference_representation_(how_to_code + where_to_point), |
| 1383 bytes_processed_so_far_(0), |
| 1384 is_code_object_(o->IsCode()), |
| 1385 code_has_been_output_(false) {} |
| 1386 void Serialize(); |
| 1387 void SerializeDeferred(); |
| 1388 void VisitPointers(Object** start, Object** end); |
| 1389 void VisitEmbeddedPointer(RelocInfo* target); |
| 1390 void VisitExternalReference(Address* p); |
| 1391 void VisitExternalReference(RelocInfo* rinfo); |
| 1392 void VisitInternalReference(RelocInfo* rinfo); |
| 1393 void VisitCodeTarget(RelocInfo* target); |
| 1394 void VisitCodeEntry(Address entry_address); |
| 1395 void VisitCell(RelocInfo* rinfo); |
| 1396 void VisitRuntimeEntry(RelocInfo* reloc); |
| 1397 // Used for seralizing the external strings that hold the natives source. |
| 1398 void VisitExternalOneByteString( |
| 1399 v8::String::ExternalOneByteStringResource** resource); |
| 1400 // We can't serialize a heap with external two byte strings. |
| 1401 void VisitExternalTwoByteString( |
| 1402 v8::String::ExternalStringResource** resource) { |
| 1403 UNREACHABLE(); |
| 1404 } |
| 1405 |
| 1406 private: |
| 1407 void SerializePrologue(AllocationSpace space, int size, Map* map); |
| 1408 |
| 1409 bool SerializeExternalNativeSourceString( |
| 1410 int builtin_count, |
| 1411 v8::String::ExternalOneByteStringResource** resource_pointer, |
| 1412 FixedArray* source_cache, int resource_index); |
| 1413 |
| 1414 enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn }; |
| 1415 // This function outputs or skips the raw data between the last pointer and |
| 1416 // up to the current position. It optionally can just return the number of |
| 1417 // bytes to skip instead of performing a skip instruction, in case the skip |
| 1418 // can be merged into the next instruction. |
| 1419 int OutputRawData(Address up_to, ReturnSkip return_skip = kIgnoringReturn); |
| 1420 // External strings are serialized in a way to resemble sequential strings. |
| 1421 void SerializeExternalString(); |
| 1422 |
| 1423 Address PrepareCode(); |
| 1424 |
| 1425 Serializer* serializer_; |
| 1426 HeapObject* object_; |
| 1427 SnapshotByteSink* sink_; |
| 1428 int reference_representation_; |
| 1429 int bytes_processed_so_far_; |
| 1430 bool is_code_object_; |
| 1431 bool code_has_been_output_; |
| 1432 }; |
| 1433 |
| 1434 |
1375 void Serializer::SerializeDeferredObjects() { | 1435 void Serializer::SerializeDeferredObjects() { |
1376 while (deferred_objects_.length() > 0) { | 1436 while (deferred_objects_.length() > 0) { |
1377 HeapObject* obj = deferred_objects_.RemoveLast(); | 1437 HeapObject* obj = deferred_objects_.RemoveLast(); |
1378 ObjectSerializer obj_serializer(this, obj, sink_, kPlain, kStartOfObject); | 1438 ObjectSerializer obj_serializer(this, obj, sink_, kPlain, kStartOfObject); |
1379 obj_serializer.SerializeDeferred(); | 1439 obj_serializer.SerializeDeferred(); |
1380 } | 1440 } |
1381 sink_->Put(kSynchronize, "Finished with deferred objects"); | 1441 sink_->Put(kSynchronize, "Finished with deferred objects"); |
1382 } | 1442 } |
1383 | 1443 |
1384 | 1444 |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1526 // Extend the array ready to get a value when deserializing. | 1586 // Extend the array ready to get a value when deserializing. |
1527 if (cache->length() <= i) cache->Add(Smi::FromInt(0)); | 1587 if (cache->length() <= i) cache->Add(Smi::FromInt(0)); |
1528 visitor->VisitPointer(&cache->at(i)); | 1588 visitor->VisitPointer(&cache->at(i)); |
1529 // Sentinel is the undefined object, which is a root so it will not normally | 1589 // Sentinel is the undefined object, which is a root so it will not normally |
1530 // be found in the cache. | 1590 // be found in the cache. |
1531 if (cache->at(i)->IsUndefined()) break; | 1591 if (cache->at(i)->IsUndefined()) break; |
1532 } | 1592 } |
1533 } | 1593 } |
1534 | 1594 |
1535 | 1595 |
| 1596 bool SerializerDeserializer::CanBeDeferred(HeapObject* o) { |
| 1597 return !o->IsString() && !o->IsScript(); |
| 1598 } |
| 1599 |
| 1600 |
1536 int PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) { | 1601 int PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) { |
1537 Isolate* isolate = this->isolate(); | 1602 Isolate* isolate = this->isolate(); |
1538 List<Object*>* cache = isolate->partial_snapshot_cache(); | 1603 List<Object*>* cache = isolate->partial_snapshot_cache(); |
1539 int new_index = cache->length(); | 1604 int new_index = cache->length(); |
1540 | 1605 |
1541 int index = partial_cache_index_map_.LookupOrInsert(heap_object, new_index); | 1606 int index = partial_cache_index_map_.LookupOrInsert(heap_object, new_index); |
1542 if (index == PartialCacheIndexMap::kInvalidIndex) { | 1607 if (index == PartialCacheIndexMap::kInvalidIndex) { |
1543 // We didn't find the object in the cache. So we add it to the cache and | 1608 // We didn't find the object in the cache. So we add it to the cache and |
1544 // then visit the pointer so that it becomes part of the startup snapshot | 1609 // then visit the pointer so that it becomes part of the startup snapshot |
1545 // and we can refer to it from the partial snapshot. | 1610 // and we can refer to it from the partial snapshot. |
1546 cache->Add(heap_object); | 1611 cache->Add(heap_object); |
1547 startup_serializer_->VisitPointer(reinterpret_cast<Object**>(&heap_object)); | 1612 startup_serializer_->VisitPointer(reinterpret_cast<Object**>(&heap_object)); |
1548 // We don't recurse from the startup snapshot generator into the partial | 1613 // We don't recurse from the startup snapshot generator into the partial |
1549 // snapshot generator. | 1614 // snapshot generator. |
1550 return new_index; | 1615 return new_index; |
1551 } | 1616 } |
1552 return index; | 1617 return index; |
1553 } | 1618 } |
1554 | 1619 |
1555 | 1620 |
| 1621 bool PartialSerializer::ShouldBeInThePartialSnapshotCache(HeapObject* o) { |
| 1622 // Scripts should be referred only through shared function infos. We can't |
| 1623 // allow them to be part of the partial snapshot because they contain a |
| 1624 // unique ID, and deserializing several partial snapshots containing script |
| 1625 // would cause dupes. |
| 1626 DCHECK(!o->IsScript()); |
| 1627 return o->IsName() || o->IsSharedFunctionInfo() || o->IsHeapNumber() || |
| 1628 o->IsCode() || o->IsScopeInfo() || o->IsExecutableAccessorInfo() || |
| 1629 o->map() == |
| 1630 startup_serializer_->isolate()->heap()->fixed_cow_array_map(); |
| 1631 } |
| 1632 |
| 1633 |
1556 #ifdef DEBUG | 1634 #ifdef DEBUG |
1557 bool Serializer::BackReferenceIsAlreadyAllocated(BackReference reference) { | 1635 bool Serializer::BackReferenceIsAlreadyAllocated(BackReference reference) { |
1558 DCHECK(reference.is_valid()); | 1636 DCHECK(reference.is_valid()); |
1559 DCHECK(!reference.is_source()); | 1637 DCHECK(!reference.is_source()); |
1560 DCHECK(!reference.is_global_proxy()); | 1638 DCHECK(!reference.is_global_proxy()); |
1561 AllocationSpace space = reference.space(); | 1639 AllocationSpace space = reference.space(); |
1562 int chunk_index = reference.chunk_index(); | 1640 int chunk_index = reference.chunk_index(); |
1563 if (space == LO_SPACE) { | 1641 if (space == LO_SPACE) { |
1564 return chunk_index == 0 && | 1642 return chunk_index == 0 && |
1565 reference.large_object_index() < seen_large_objects_index_; | 1643 reference.large_object_index() < seen_large_objects_index_; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1629 sink_->PutInt(skip, "BackRefSkipDistance"); | 1707 sink_->PutInt(skip, "BackRefSkipDistance"); |
1630 } | 1708 } |
1631 PutBackReference(obj, back_reference); | 1709 PutBackReference(obj, back_reference); |
1632 } | 1710 } |
1633 return true; | 1711 return true; |
1634 } | 1712 } |
1635 return false; | 1713 return false; |
1636 } | 1714 } |
1637 | 1715 |
1638 | 1716 |
| 1717 StartupSerializer::StartupSerializer(Isolate* isolate, SnapshotByteSink* sink) |
| 1718 : Serializer(isolate, sink), root_index_wave_front_(0) { |
| 1719 // Clear the cache of objects used by the partial snapshot. After the |
| 1720 // strong roots have been serialized we can create a partial snapshot |
| 1721 // which will repopulate the cache with objects needed by that partial |
| 1722 // snapshot. |
| 1723 isolate->partial_snapshot_cache()->Clear(); |
| 1724 InitializeCodeAddressMap(); |
| 1725 } |
| 1726 |
| 1727 |
1639 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, | 1728 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, |
1640 WhereToPoint where_to_point, int skip) { | 1729 WhereToPoint where_to_point, int skip) { |
1641 // Make sure that all functions are derived from the code-stub context | 1730 // Make sure that all functions are derived from the code-stub context |
1642 DCHECK(!obj->IsJSFunction() || | 1731 DCHECK(!obj->IsJSFunction() || |
1643 JSFunction::cast(obj)->GetCreationContext() == | 1732 JSFunction::cast(obj)->GetCreationContext() == |
1644 isolate()->heap()->code_stub_context()); | 1733 isolate()->heap()->code_stub_context()); |
1645 | 1734 |
1646 int root_index = root_index_map_.Lookup(obj); | 1735 int root_index = root_index_map_.Lookup(obj); |
1647 // We can only encode roots as such if it has already been serialized. | 1736 // We can only encode roots as such if it has already been serialized. |
1648 // That applies to root indices below the wave front. | 1737 // That applies to root indices below the wave front. |
(...skipping 1074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2723 if (source_hash != SourceHash(source)) return SOURCE_MISMATCH; | 2812 if (source_hash != SourceHash(source)) return SOURCE_MISMATCH; |
2724 if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) { | 2813 if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) { |
2725 return CPU_FEATURES_MISMATCH; | 2814 return CPU_FEATURES_MISMATCH; |
2726 } | 2815 } |
2727 if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH; | 2816 if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH; |
2728 if (!Checksum(Payload()).Check(c1, c2)) return CHECKSUM_MISMATCH; | 2817 if (!Checksum(Payload()).Check(c1, c2)) return CHECKSUM_MISMATCH; |
2729 return CHECK_SUCCESS; | 2818 return CHECK_SUCCESS; |
2730 } | 2819 } |
2731 | 2820 |
2732 | 2821 |
| 2822 uint32_t SerializedCodeData::SourceHash(String* source) const { |
| 2823 return source->length(); |
| 2824 } |
| 2825 |
| 2826 |
2733 // Return ScriptData object and relinquish ownership over it to the caller. | 2827 // Return ScriptData object and relinquish ownership over it to the caller. |
2734 ScriptData* SerializedCodeData::GetScriptData() { | 2828 ScriptData* SerializedCodeData::GetScriptData() { |
2735 DCHECK(owns_data_); | 2829 DCHECK(owns_data_); |
2736 ScriptData* result = new ScriptData(data_, size_); | 2830 ScriptData* result = new ScriptData(data_, size_); |
2737 result->AcquireDataOwnership(); | 2831 result->AcquireDataOwnership(); |
2738 owns_data_ = false; | 2832 owns_data_ = false; |
2739 data_ = NULL; | 2833 data_ = NULL; |
2740 return result; | 2834 return result; |
2741 } | 2835 } |
2742 | 2836 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2781 SerializedCodeData* scd = new SerializedCodeData(cached_data); | 2875 SerializedCodeData* scd = new SerializedCodeData(cached_data); |
2782 SanityCheckResult r = scd->SanityCheck(isolate, source); | 2876 SanityCheckResult r = scd->SanityCheck(isolate, source); |
2783 if (r == CHECK_SUCCESS) return scd; | 2877 if (r == CHECK_SUCCESS) return scd; |
2784 cached_data->Reject(); | 2878 cached_data->Reject(); |
2785 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); | 2879 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); |
2786 delete scd; | 2880 delete scd; |
2787 return NULL; | 2881 return NULL; |
2788 } | 2882 } |
2789 } // namespace internal | 2883 } // namespace internal |
2790 } // namespace v8 | 2884 } // namespace v8 |
OLD | NEW |