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 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
568 { | 568 { |
569 DisallowHeapAllocation no_gc; | 569 DisallowHeapAllocation no_gc; |
570 isolate_->heap()->IterateSmiRoots(this); | 570 isolate_->heap()->IterateSmiRoots(this); |
571 isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG); | 571 isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG); |
572 isolate_->heap()->RepairFreeListsAfterDeserialization(); | 572 isolate_->heap()->RepairFreeListsAfterDeserialization(); |
573 isolate_->heap()->IterateWeakRoots(this, VISIT_ALL); | 573 isolate_->heap()->IterateWeakRoots(this, VISIT_ALL); |
574 DeserializeDeferredObjects(); | 574 DeserializeDeferredObjects(); |
575 } | 575 } |
576 | 576 |
577 isolate_->heap()->set_native_contexts_list( | 577 isolate_->heap()->set_native_contexts_list( |
578 isolate_->heap()->undefined_value()); | 578 isolate_->heap()->code_stub_context()); |
579 | 579 |
580 // The allocation site list is build during root iteration, but if no sites | 580 // The allocation site list is build during root iteration, but if no sites |
581 // were encountered then it needs to be initialized to undefined. | 581 // were encountered then it needs to be initialized to undefined. |
582 if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { | 582 if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { |
583 isolate_->heap()->set_allocation_sites_list( | 583 isolate_->heap()->set_allocation_sites_list( |
584 isolate_->heap()->undefined_value()); | 584 isolate_->heap()->undefined_value()); |
585 } | 585 } |
586 | 586 |
587 // Update data pointers to the external strings containing natives sources. | 587 // Update data pointers to the external strings containing natives sources. |
588 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { | 588 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { |
589 Object* source = isolate_->heap()->natives_source_cache()->get(i); | 589 Object* source = isolate_->heap()->natives_source_cache()->get(i); |
590 if (!source->IsUndefined()) { | 590 if (!source->IsUndefined()) { |
591 ExternalOneByteString::cast(source)->update_data_cache(); | 591 ExternalOneByteString::cast(source)->update_data_cache(); |
592 } | 592 } |
593 } | 593 } |
594 | 594 |
| 595 for (int i = 0; i < CodeStubNatives::GetBuiltinsCount(); i++) { |
| 596 Object* source = isolate_->heap()->code_stub_natives_source_cache()->get(i); |
| 597 if (!source->IsUndefined()) { |
| 598 ExternalOneByteString::cast(source)->update_data_cache(); |
| 599 } |
| 600 } |
| 601 |
595 FlushICacheForNewCodeObjects(); | 602 FlushICacheForNewCodeObjects(); |
596 | 603 |
597 // Issue code events for newly deserialized code objects. | 604 // Issue code events for newly deserialized code objects. |
598 LOG_CODE_EVENT(isolate_, LogCodeObjects()); | 605 LOG_CODE_EVENT(isolate_, LogCodeObjects()); |
599 LOG_CODE_EVENT(isolate_, LogCompiledFunctions()); | 606 LOG_CODE_EVENT(isolate_, LogCompiledFunctions()); |
600 } | 607 } |
601 | 608 |
602 | 609 |
603 MaybeHandle<Object> Deserializer::DeserializePartial( | 610 MaybeHandle<Object> Deserializer::DeserializePartial( |
604 Isolate* isolate, Handle<JSGlobalProxy> global_proxy, | 611 Isolate* isolate, Handle<JSGlobalProxy> global_proxy, |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
900 // Assert that the current reserved chunk is still big enough. | 907 // Assert that the current reserved chunk is still big enough. |
901 const Heap::Reservation& reservation = reservations_[space_index]; | 908 const Heap::Reservation& reservation = reservations_[space_index]; |
902 int chunk_index = current_chunk_[space_index]; | 909 int chunk_index = current_chunk_[space_index]; |
903 CHECK_LE(high_water_[space_index], reservation[chunk_index].end); | 910 CHECK_LE(high_water_[space_index], reservation[chunk_index].end); |
904 #endif | 911 #endif |
905 return address; | 912 return address; |
906 } | 913 } |
907 } | 914 } |
908 | 915 |
909 | 916 |
| 917 Object** Deserializer::CopyInNativesSource(Vector<const char> source_vector, |
| 918 Object** current) { |
| 919 DCHECK(!isolate_->heap()->deserialization_complete()); |
| 920 NativesExternalStringResource* resource = new NativesExternalStringResource( |
| 921 source_vector.start(), source_vector.length()); |
| 922 Object* resource_obj = reinterpret_cast<Object*>(resource); |
| 923 UnalignedCopy(current++, &resource_obj); |
| 924 return current; |
| 925 } |
| 926 |
| 927 |
910 bool Deserializer::ReadData(Object** current, Object** limit, int source_space, | 928 bool Deserializer::ReadData(Object** current, Object** limit, int source_space, |
911 Address current_object_address) { | 929 Address current_object_address) { |
912 Isolate* const isolate = isolate_; | 930 Isolate* const isolate = isolate_; |
913 // Write barrier support costs around 1% in startup time. In fact there | 931 // Write barrier support costs around 1% in startup time. In fact there |
914 // are no new space objects in current boot snapshots, so it's not needed, | 932 // are no new space objects in current boot snapshots, so it's not needed, |
915 // but that may change. | 933 // but that may change. |
916 bool write_barrier_needed = | 934 bool write_barrier_needed = |
917 (current_object_address != NULL && source_space != NEW_SPACE && | 935 (current_object_address != NULL && source_space != NEW_SPACE && |
918 source_space != CODE_SPACE); | 936 source_space != CODE_SPACE); |
919 while (current < limit) { | 937 while (current < limit) { |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1166 current = limit; | 1184 current = limit; |
1167 return false; | 1185 return false; |
1168 } | 1186 } |
1169 | 1187 |
1170 case kSynchronize: | 1188 case kSynchronize: |
1171 // If we get here then that indicates that you have a mismatch between | 1189 // If we get here then that indicates that you have a mismatch between |
1172 // the number of GC roots when serializing and deserializing. | 1190 // the number of GC roots when serializing and deserializing. |
1173 CHECK(false); | 1191 CHECK(false); |
1174 break; | 1192 break; |
1175 | 1193 |
1176 case kNativesStringResource: { | 1194 case kNativesStringResource: |
1177 DCHECK(!isolate_->heap()->deserialization_complete()); | 1195 current = CopyInNativesSource(Natives::GetScriptSource(source_.Get()), |
1178 int index = source_.Get(); | 1196 current); |
1179 Vector<const char> source_vector = Natives::GetScriptSource(index); | |
1180 NativesExternalStringResource* resource = | |
1181 new NativesExternalStringResource(source_vector.start(), | |
1182 source_vector.length()); | |
1183 Object* resource_obj = reinterpret_cast<Object*>(resource); | |
1184 UnalignedCopy(current++, &resource_obj); | |
1185 break; | 1197 break; |
1186 } | 1198 |
| 1199 case kCodeStubNativesStringResource: |
| 1200 current = CopyInNativesSource( |
| 1201 CodeStubNatives::GetScriptSource(source_.Get()), current); |
| 1202 break; |
1187 | 1203 |
1188 // Deserialize raw data of variable length. | 1204 // Deserialize raw data of variable length. |
1189 case kVariableRawData: { | 1205 case kVariableRawData: { |
1190 int size_in_bytes = source_.GetInt(); | 1206 int size_in_bytes = source_.GetInt(); |
1191 byte* raw_data_out = reinterpret_cast<byte*>(current); | 1207 byte* raw_data_out = reinterpret_cast<byte*>(current); |
1192 source_.CopyRaw(raw_data_out, size_in_bytes); | 1208 source_.CopyRaw(raw_data_out, size_in_bytes); |
1193 break; | 1209 break; |
1194 } | 1210 } |
1195 | 1211 |
1196 case kVariableRepeat: { | 1212 case kVariableRepeat: { |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1412 } | 1428 } |
1413 } | 1429 } |
1414 } | 1430 } |
1415 | 1431 |
1416 | 1432 |
1417 void PartialSerializer::Serialize(Object** o) { | 1433 void PartialSerializer::Serialize(Object** o) { |
1418 if ((*o)->IsContext()) { | 1434 if ((*o)->IsContext()) { |
1419 Context* context = Context::cast(*o); | 1435 Context* context = Context::cast(*o); |
1420 global_object_ = context->global_object(); | 1436 global_object_ = context->global_object(); |
1421 back_reference_map()->AddGlobalProxy(context->global_proxy()); | 1437 back_reference_map()->AddGlobalProxy(context->global_proxy()); |
| 1438 // The bootstrap snapshot has a code-stub context. When serializing the |
| 1439 // partial snapshot, it is chained into the weak context list on the isolate |
| 1440 // and it's next context pointer may point to the code-stub context. Clear |
| 1441 // it before serializing, it will get re-added to the context list |
| 1442 // explicitly when it's loaded. |
| 1443 if (context->IsNativeContext()) { |
| 1444 context->set(Context::NEXT_CONTEXT_LINK, |
| 1445 isolate_->heap()->undefined_value()); |
| 1446 DCHECK(!context->global_object()->IsUndefined()); |
| 1447 DCHECK(!context->builtins()->IsUndefined()); |
| 1448 } |
1422 } | 1449 } |
1423 VisitPointer(o); | 1450 VisitPointer(o); |
1424 SerializeDeferredObjects(); | 1451 SerializeDeferredObjects(); |
1425 SerializeOutdatedContextsAsFixedArray(); | 1452 SerializeOutdatedContextsAsFixedArray(); |
1426 Pad(); | 1453 Pad(); |
1427 } | 1454 } |
1428 | 1455 |
1429 | 1456 |
1430 void PartialSerializer::SerializeOutdatedContextsAsFixedArray() { | 1457 void PartialSerializer::SerializeOutdatedContextsAsFixedArray() { |
1431 int length = outdated_contexts_.length(); | 1458 int length = outdated_contexts_.length(); |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1616 PutBackReference(obj, back_reference); | 1643 PutBackReference(obj, back_reference); |
1617 } | 1644 } |
1618 return true; | 1645 return true; |
1619 } | 1646 } |
1620 return false; | 1647 return false; |
1621 } | 1648 } |
1622 | 1649 |
1623 | 1650 |
1624 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, | 1651 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, |
1625 WhereToPoint where_to_point, int skip) { | 1652 WhereToPoint where_to_point, int skip) { |
1626 DCHECK(!obj->IsJSFunction()); | 1653 // Make sure that all functions are derived from the code-stub context |
| 1654 DCHECK(!obj->IsJSFunction() || |
| 1655 JSFunction::cast(obj)->GetCreationContext() == |
| 1656 isolate()->heap()->code_stub_context()); |
1627 | 1657 |
1628 int root_index = root_index_map_.Lookup(obj); | 1658 int root_index = root_index_map_.Lookup(obj); |
1629 // We can only encode roots as such if it has already been serialized. | 1659 // We can only encode roots as such if it has already been serialized. |
1630 // That applies to root indices below the wave front. | 1660 // That applies to root indices below the wave front. |
1631 if (root_index != RootIndexMap::kInvalidRootIndex && | 1661 if (root_index != RootIndexMap::kInvalidRootIndex && |
1632 root_index < root_index_wave_front_) { | 1662 root_index < root_index_wave_front_) { |
1633 PutRoot(root_index, obj, how_to_code, where_to_point, skip); | 1663 PutRoot(root_index, obj, how_to_code, where_to_point, skip); |
1634 return; | 1664 return; |
1635 } | 1665 } |
1636 | 1666 |
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2120 | 2150 |
2121 | 2151 |
2122 void Serializer::ObjectSerializer::VisitCell(RelocInfo* rinfo) { | 2152 void Serializer::ObjectSerializer::VisitCell(RelocInfo* rinfo) { |
2123 int skip = OutputRawData(rinfo->pc(), kCanReturnSkipInsteadOfSkipping); | 2153 int skip = OutputRawData(rinfo->pc(), kCanReturnSkipInsteadOfSkipping); |
2124 Cell* object = Cell::cast(rinfo->target_cell()); | 2154 Cell* object = Cell::cast(rinfo->target_cell()); |
2125 serializer_->SerializeObject(object, kPlain, kInnerPointer, skip); | 2155 serializer_->SerializeObject(object, kPlain, kInnerPointer, skip); |
2126 bytes_processed_so_far_ += kPointerSize; | 2156 bytes_processed_so_far_ += kPointerSize; |
2127 } | 2157 } |
2128 | 2158 |
2129 | 2159 |
| 2160 bool Serializer::ObjectSerializer::SerializeExternalNativeSourceString( |
| 2161 int builtin_count, |
| 2162 v8::String::ExternalOneByteStringResource** resource_pointer, |
| 2163 FixedArray* source_cache, int resource_index) { |
| 2164 for (int i = 0; i < builtin_count; i++) { |
| 2165 Object* source = source_cache->get(i); |
| 2166 if (!source->IsUndefined()) { |
| 2167 ExternalOneByteString* string = ExternalOneByteString::cast(source); |
| 2168 typedef v8::String::ExternalOneByteStringResource Resource; |
| 2169 const Resource* resource = string->resource(); |
| 2170 if (resource == *resource_pointer) { |
| 2171 sink_->Put(resource_index, "NativesStringResource"); |
| 2172 sink_->PutSection(i, "NativesStringResourceEnd"); |
| 2173 bytes_processed_so_far_ += sizeof(resource); |
| 2174 return true; |
| 2175 } |
| 2176 } |
| 2177 } |
| 2178 return false; |
| 2179 } |
| 2180 |
| 2181 |
2130 void Serializer::ObjectSerializer::VisitExternalOneByteString( | 2182 void Serializer::ObjectSerializer::VisitExternalOneByteString( |
2131 v8::String::ExternalOneByteStringResource** resource_pointer) { | 2183 v8::String::ExternalOneByteStringResource** resource_pointer) { |
2132 Address references_start = reinterpret_cast<Address>(resource_pointer); | 2184 Address references_start = reinterpret_cast<Address>(resource_pointer); |
2133 OutputRawData(references_start); | 2185 OutputRawData(references_start); |
2134 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { | 2186 if (SerializeExternalNativeSourceString( |
2135 Object* source = | 2187 Natives::GetBuiltinsCount(), resource_pointer, |
2136 serializer_->isolate()->heap()->natives_source_cache()->get(i); | 2188 serializer_->isolate()->heap()->natives_source_cache(), |
2137 if (!source->IsUndefined()) { | 2189 kNativesStringResource)) { |
2138 ExternalOneByteString* string = ExternalOneByteString::cast(source); | 2190 return; |
2139 typedef v8::String::ExternalOneByteStringResource Resource; | 2191 } |
2140 const Resource* resource = string->resource(); | 2192 if (SerializeExternalNativeSourceString( |
2141 if (resource == *resource_pointer) { | 2193 CodeStubNatives::GetBuiltinsCount(), resource_pointer, |
2142 sink_->Put(kNativesStringResource, "NativesStringResource"); | 2194 serializer_->isolate()->heap()->code_stub_natives_source_cache(), |
2143 sink_->PutSection(i, "NativesStringResourceEnd"); | 2195 kCodeStubNativesStringResource)) { |
2144 bytes_processed_so_far_ += sizeof(resource); | 2196 return; |
2145 return; | |
2146 } | |
2147 } | |
2148 } | 2197 } |
2149 // One of the strings in the natives cache should match the resource. We | 2198 // One of the strings in the natives cache should match the resource. We |
2150 // don't expect any other kinds of external strings here. | 2199 // don't expect any other kinds of external strings here. |
2151 UNREACHABLE(); | 2200 UNREACHABLE(); |
2152 } | 2201 } |
2153 | 2202 |
2154 | 2203 |
2155 Address Serializer::ObjectSerializer::PrepareCode() { | 2204 Address Serializer::ObjectSerializer::PrepareCode() { |
2156 // To make snapshots reproducible, we make a copy of the code object | 2205 // To make snapshots reproducible, we make a copy of the code object |
2157 // and wipe all pointers in the copy, which we then serialize. | 2206 // and wipe all pointers in the copy, which we then serialize. |
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2749 SerializedCodeData* scd = new SerializedCodeData(cached_data); | 2798 SerializedCodeData* scd = new SerializedCodeData(cached_data); |
2750 SanityCheckResult r = scd->SanityCheck(isolate, source); | 2799 SanityCheckResult r = scd->SanityCheck(isolate, source); |
2751 if (r == CHECK_SUCCESS) return scd; | 2800 if (r == CHECK_SUCCESS) return scd; |
2752 cached_data->Reject(); | 2801 cached_data->Reject(); |
2753 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); | 2802 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); |
2754 delete scd; | 2803 delete scd; |
2755 return NULL; | 2804 return NULL; |
2756 } | 2805 } |
2757 } // namespace internal | 2806 } // namespace internal |
2758 } // namespace v8 | 2807 } // namespace v8 |
OLD | NEW |