diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-10-13 13:24:50 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-10-14 10:57:25 +0000 |
commit | af3d4809763ef308f08ced947a73b624729ac7ea (patch) | |
tree | 4402b911e30383f6c6dace1e8cf3b8e85355db3a /chromium/v8/src/snapshot | |
parent | 0e8ff63a407fe323e215bb1a2c423c09a4747c8a (diff) | |
download | qtwebengine-chromium-af3d4809763ef308f08ced947a73b624729ac7ea.tar.gz |
BASELINE: Update Chromium to 47.0.2526.14
Also adding in sources needed for spellchecking.
Change-Id: Idd44170fa1616f26315188970a8d5ba7d472b18a
Reviewed-by: Michael BrĂ¼ning <michael.bruning@theqtcompany.com>
Diffstat (limited to 'chromium/v8/src/snapshot')
-rw-r--r-- | chromium/v8/src/snapshot/OWNERS | 3 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/mksnapshot.cc | 29 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/natives-common.cc | 64 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/natives-external.cc | 25 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/natives.h | 21 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/serialize.cc | 319 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/serialize.h | 121 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/snapshot-common.cc | 14 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/snapshot-empty.cc | 2 | ||||
-rw-r--r-- | chromium/v8/src/snapshot/snapshot.h | 16 |
10 files changed, 390 insertions, 224 deletions
diff --git a/chromium/v8/src/snapshot/OWNERS b/chromium/v8/src/snapshot/OWNERS index 003bdad6bc1..6c84c07df77 100644 --- a/chromium/v8/src/snapshot/OWNERS +++ b/chromium/v8/src/snapshot/OWNERS @@ -1,2 +1,5 @@ +set noparent + verwaest@chromium.org +vogelheim@chromium.org yangguo@chromium.org diff --git a/chromium/v8/src/snapshot/mksnapshot.cc b/chromium/v8/src/snapshot/mksnapshot.cc index f44eca523a8..09cbf93e1ef 100644 --- a/chromium/v8/src/snapshot/mksnapshot.cc +++ b/chromium/v8/src/snapshot/mksnapshot.cc @@ -6,14 +6,13 @@ #include <signal.h> #include <stdio.h> -#include "src/v8.h" - #include "include/libplatform/libplatform.h" #include "src/assembler.h" #include "src/base/platform/platform.h" #include "src/bootstrapper.h" #include "src/flags.h" #include "src/list.h" +#include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! #include "src/snapshot/natives.h" #include "src/snapshot/serialize.h" @@ -22,15 +21,17 @@ using namespace v8; class SnapshotWriter { public: - explicit SnapshotWriter(const char* snapshot_file) - : fp_(GetFileDescriptorOrDie(snapshot_file)), - startup_blob_file_(NULL) {} + SnapshotWriter() : fp_(NULL), startup_blob_file_(NULL) {} ~SnapshotWriter() { - fclose(fp_); + if (fp_) fclose(fp_); if (startup_blob_file_) fclose(startup_blob_file_); } + void SetSnapshotFile(const char* snapshot_file) { + if (snapshot_file != NULL) fp_ = GetFileDescriptorOrDie(snapshot_file); + } + void SetStartupBlobFile(const char* startup_blob_file) { if (startup_blob_file != NULL) startup_blob_file_ = GetFileDescriptorOrDie(startup_blob_file); @@ -39,7 +40,7 @@ class SnapshotWriter { void WriteSnapshot(v8::StartupData blob) const { i::Vector<const i::byte> blob_vector( reinterpret_cast<const i::byte*>(blob.data), blob.raw_size); - WriteSnapshotFile(blob_vector); + MaybeWriteSnapshotFile(blob_vector); MaybeWriteStartupBlob(blob_vector); } @@ -54,7 +55,9 @@ class SnapshotWriter { } } - void WriteSnapshotFile(const i::Vector<const i::byte>& blob) const { + void MaybeWriteSnapshotFile(const i::Vector<const i::byte>& blob) const { + if (!fp_) return; + WriteFilePrefix(); WriteData(blob); WriteFileSuffix(); @@ -143,8 +146,9 @@ int main(int argc, char** argv) { // Print the usage if an error occurs when parsing the command line // flags or if the help flag is set. int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true); - if (result > 0 || (argc != 2 && argc != 3) || i::FLAG_help) { - ::printf("Usage: %s [flag] ... outfile\n", argv[0]); + if (result > 0 || (argc != 1 && argc != 2) || i::FLAG_help) { + ::printf("Usage: %s --startup_src=... --startup_blob=... [extras]\n", + argv[0]); i::FlagList::PrintHelp(); return !i::FLAG_help; } @@ -156,9 +160,10 @@ int main(int argc, char** argv) { v8::V8::Initialize(); { - SnapshotWriter writer(argv[1]); + SnapshotWriter writer; + if (i::FLAG_startup_src) writer.SetSnapshotFile(i::FLAG_startup_src); if (i::FLAG_startup_blob) writer.SetStartupBlobFile(i::FLAG_startup_blob); - char* extra_code = GetExtraCode(argc == 3 ? argv[2] : NULL); + char* extra_code = GetExtraCode(argc == 2 ? argv[1] : NULL); StartupData blob = v8::V8::CreateSnapshotDataBlob(extra_code); CHECK(blob.data); writer.WriteSnapshot(blob); diff --git a/chromium/v8/src/snapshot/natives-common.cc b/chromium/v8/src/snapshot/natives-common.cc new file mode 100644 index 00000000000..d027ec9dc79 --- /dev/null +++ b/chromium/v8/src/snapshot/natives-common.cc @@ -0,0 +1,64 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// The common functionality when building with internal or external natives. + +#include "src/heap/heap.h" +#include "src/objects-inl.h" +#include "src/snapshot/natives.h" + +namespace v8 { +namespace internal { + +template <> +FixedArray* NativesCollection<CORE>::GetSourceCache(Heap* heap) { + return heap->natives_source_cache(); +} + + +template <> +FixedArray* NativesCollection<EXPERIMENTAL>::GetSourceCache(Heap* heap) { + return heap->experimental_natives_source_cache(); +} + + +template <> +FixedArray* NativesCollection<EXTRAS>::GetSourceCache(Heap* heap) { + return heap->extra_natives_source_cache(); +} + + +template <> +FixedArray* NativesCollection<EXPERIMENTAL_EXTRAS>::GetSourceCache(Heap* heap) { + return heap->experimental_extra_natives_source_cache(); +} + + +template <> +FixedArray* NativesCollection<CODE_STUB>::GetSourceCache(Heap* heap) { + return heap->code_stub_natives_source_cache(); +} + + +template <NativeType type> +void NativesCollection<type>::UpdateSourceCache(Heap* heap) { + for (int i = 0; i < GetBuiltinsCount(); i++) { + Object* source = GetSourceCache(heap)->get(i); + if (!source->IsUndefined()) { + ExternalOneByteString::cast(source)->update_data_cache(); + } + } +} + + +// Explicit template instantiations. +template void NativesCollection<CORE>::UpdateSourceCache(Heap* heap); +template void NativesCollection<CODE_STUB>::UpdateSourceCache(Heap* heap); +template void NativesCollection<EXPERIMENTAL>::UpdateSourceCache(Heap* heap); +template void NativesCollection<EXTRAS>::UpdateSourceCache(Heap* heap); +template void NativesCollection<EXPERIMENTAL_EXTRAS>::UpdateSourceCache( + Heap* heap); + +} // namespace internal +} // namespace v8 diff --git a/chromium/v8/src/snapshot/natives-external.cc b/chromium/v8/src/snapshot/natives-external.cc index 3649c2a69ff..7e5e6c7ba04 100644 --- a/chromium/v8/src/snapshot/natives-external.cc +++ b/chromium/v8/src/snapshot/natives-external.cc @@ -157,9 +157,12 @@ void ReadNatives() { if (natives_blob_ && NativesHolder<CORE>::empty()) { SnapshotByteSource bytes(natives_blob_->data, natives_blob_->raw_size); NativesHolder<CORE>::set(NativesStore::MakeFromScriptsSource(&bytes)); + NativesHolder<CODE_STUB>::set(NativesStore::MakeFromScriptsSource(&bytes)); NativesHolder<EXPERIMENTAL>::set( NativesStore::MakeFromScriptsSource(&bytes)); NativesHolder<EXTRAS>::set(NativesStore::MakeFromScriptsSource(&bytes)); + NativesHolder<EXPERIMENTAL_EXTRAS>::set( + NativesStore::MakeFromScriptsSource(&bytes)); DCHECK(!bytes.HasMore()); } } @@ -185,8 +188,10 @@ void SetNativesFromFile(StartupData* natives_blob) { */ void DisposeNatives() { NativesHolder<CORE>::Dispose(); + NativesHolder<CODE_STUB>::Dispose(); NativesHolder<EXPERIMENTAL>::Dispose(); NativesHolder<EXTRAS>::Dispose(); + NativesHolder<EXPERIMENTAL_EXTRAS>::Dispose(); } @@ -227,10 +232,20 @@ Vector<const char> NativesCollection<type>::GetScriptsSource() { } -// The compiler can't 'see' all uses of the static methods and hence -// my choice to elide them. This we'll explicitly instantiate these. -template class NativesCollection<CORE>; -template class NativesCollection<EXPERIMENTAL>; -template class NativesCollection<EXTRAS>; +// Explicit template instantiations. +#define INSTANTIATE_TEMPLATES(T) \ + template int NativesCollection<T>::GetBuiltinsCount(); \ + template int NativesCollection<T>::GetDebuggerCount(); \ + template int NativesCollection<T>::GetIndex(const char* name); \ + template Vector<const char> NativesCollection<T>::GetScriptSource(int i); \ + template Vector<const char> NativesCollection<T>::GetScriptName(int i); \ + template Vector<const char> NativesCollection<T>::GetScriptsSource(); +INSTANTIATE_TEMPLATES(CORE) +INSTANTIATE_TEMPLATES(CODE_STUB) +INSTANTIATE_TEMPLATES(EXPERIMENTAL) +INSTANTIATE_TEMPLATES(EXTRAS) +INSTANTIATE_TEMPLATES(EXPERIMENTAL_EXTRAS) +#undef INSTANTIATE_TEMPLATES + } // namespace internal } // namespace v8 diff --git a/chromium/v8/src/snapshot/natives.h b/chromium/v8/src/snapshot/natives.h index 149f9ec2bed..c923a0f353b 100644 --- a/chromium/v8/src/snapshot/natives.h +++ b/chromium/v8/src/snapshot/natives.h @@ -5,6 +5,7 @@ #ifndef V8_SNAPSHOT_NATIVES_H_ #define V8_SNAPSHOT_NATIVES_H_ +#include "src/objects.h" #include "src/vector.h" namespace v8 { class StartupData; } // Forward declaration. @@ -12,11 +13,21 @@ namespace v8 { class StartupData; } // Forward declaration. namespace v8 { namespace internal { -enum NativeType { CORE, EXPERIMENTAL, EXTRAS, D8, TEST }; +enum NativeType { + CORE, + CODE_STUB, + EXPERIMENTAL, + EXTRAS, + EXPERIMENTAL_EXTRAS, + D8, + TEST +}; template <NativeType type> class NativesCollection { public: + // The following methods are implemented in js2c-generated code: + // Number of built-in scripts. static int GetBuiltinsCount(); // Number of debugger implementation scripts. @@ -30,11 +41,19 @@ class NativesCollection { static Vector<const char> GetScriptSource(int index); static Vector<const char> GetScriptName(int index); static Vector<const char> GetScriptsSource(); + + // The following methods are implemented in natives-common.cc: + + static FixedArray* GetSourceCache(Heap* heap); + static void UpdateSourceCache(Heap* heap); }; typedef NativesCollection<CORE> Natives; +typedef NativesCollection<CODE_STUB> CodeStubNatives; typedef NativesCollection<EXPERIMENTAL> ExperimentalNatives; typedef NativesCollection<EXTRAS> ExtraNatives; +typedef NativesCollection<EXPERIMENTAL_EXTRAS> ExperimentalExtraNatives; + #ifdef V8_USE_EXTERNAL_STARTUP_DATA // Used for reading the natives at runtime. Implementation in natives-empty.cc diff --git a/chromium/v8/src/snapshot/serialize.cc b/chromium/v8/src/snapshot/serialize.cc index 7588fbcf90f..297b31cbe5f 100644 --- a/chromium/v8/src/snapshot/serialize.cc +++ b/chromium/v8/src/snapshot/serialize.cc @@ -2,14 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/v8.h" +#include "src/snapshot/serialize.h" #include "src/accessors.h" #include "src/api.h" #include "src/base/platform/platform.h" #include "src/bootstrapper.h" #include "src/code-stubs.h" -#include "src/cpu-profiler.h" #include "src/deoptimizer.h" #include "src/execution.h" #include "src/global-handles.h" @@ -17,11 +16,12 @@ #include "src/ic/stub-cache.h" #include "src/objects.h" #include "src/parser.h" +#include "src/profiler/cpu-profiler.h" #include "src/runtime/runtime.h" #include "src/snapshot/natives.h" -#include "src/snapshot/serialize.h" #include "src/snapshot/snapshot.h" #include "src/snapshot/snapshot-source-sink.h" +#include "src/v8.h" #include "src/v8threads.h" #include "src/version.h" @@ -60,7 +60,6 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) { "Heap::NewSpaceAllocationLimitAddress()"); Add(ExternalReference::new_space_allocation_top_address(isolate).address(), "Heap::NewSpaceAllocationTopAddress()"); - Add(ExternalReference::debug_break(isolate).address(), "Debug::Break()"); Add(ExternalReference::debug_step_in_fp_address(isolate).address(), "Debug::step_in_fp_addr()"); Add(ExternalReference::mod_two_doubles_operation(isolate).address(), @@ -122,8 +121,6 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) { "InvokeFunctionCallback"); Add(ExternalReference::invoke_accessor_getter_callback(isolate).address(), "InvokeAccessorGetterCallback"); - Add(ExternalReference::flush_icache_function(isolate).address(), - "CpuFeatures::FlushICache"); Add(ExternalReference::log_enter_external_function(isolate).address(), "Logger::EnterExternal"); Add(ExternalReference::log_leave_external_function(isolate).address(), @@ -132,6 +129,8 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) { "double_constants.minus_one_half"); Add(ExternalReference::stress_deopt_count(isolate).address(), "Isolate::stress_deopt_count_address()"); + Add(ExternalReference::vector_store_virtual_register(isolate).address(), + "Isolate::vector_store_virtual_register()"); // Debug addresses Add(ExternalReference::debug_after_break_target_address(isolate).address(), @@ -221,20 +220,6 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) { Add(ref.address(), runtime_functions[i].name); } - static const RefTableEntry inline_caches[] = { -#define IC_ENTRY(name) \ - { IC::k##name, "IC::" #name } \ - , - IC_UTIL_LIST(IC_ENTRY) -#undef IC_ENTRY - }; - - for (unsigned i = 0; i < arraysize(inline_caches); ++i) { - ExternalReference ref( - IC_Utility(static_cast<IC::UtilityId>(inline_caches[i].id)), isolate); - Add(ref.address(), runtime_functions[i].name); - } - // Stat counters struct StatsRefTableEntry { StatsCounter* (Counters::*counter)(); @@ -369,10 +354,9 @@ RootIndexMap::RootIndexMap(Isolate* isolate) { map_ = isolate->root_index_map(); if (map_ != NULL) return; map_ = new HashMap(HashMap::PointersMatch); - Object** root_array = isolate->heap()->roots_array_start(); for (uint32_t i = 0; i < Heap::kStrongRootListLength; i++) { Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(i); - Object* root = root_array[root_index]; + Object* root = isolate->heap()->root(root_index); // Omit root entries that can be written after initialization. They must // not be referenced through the root list in the snapshot. if (root->IsHeapObject() && @@ -515,19 +499,23 @@ void Deserializer::DecodeReservation( } -void Deserializer::FlushICacheForNewCodeObjects() { - if (!deserializing_user_code_) { - // The entire isolate is newly deserialized. Simply flush all code pages. - PageIterator it(isolate_->heap()->code_space()); - while (it.has_next()) { - Page* p = it.next(); - CpuFeatures::FlushICache(p->area_start(), - p->area_end() - p->area_start()); - } +void Deserializer::FlushICacheForNewIsolate() { + DCHECK(!deserializing_user_code_); + // The entire isolate is newly deserialized. Simply flush all code pages. + PageIterator it(isolate_->heap()->code_space()); + while (it.has_next()) { + Page* p = it.next(); + Assembler::FlushICache(isolate_, p->area_start(), + p->area_end() - p->area_start()); } +} + + +void Deserializer::FlushICacheForNewCodeObjects() { + DCHECK(deserializing_user_code_); for (Code* code : new_code_objects_) { - CpuFeatures::FlushICache(code->instruction_start(), - code->instruction_size()); + Assembler::FlushICache(isolate_, code->instruction_start(), + code->instruction_size()); } } @@ -572,10 +560,11 @@ void Deserializer::Deserialize(Isolate* isolate) { isolate_->heap()->RepairFreeListsAfterDeserialization(); isolate_->heap()->IterateWeakRoots(this, VISIT_ALL); DeserializeDeferredObjects(); + FlushICacheForNewIsolate(); } isolate_->heap()->set_native_contexts_list( - isolate_->heap()->undefined_value()); + isolate_->heap()->code_stub_context()); // The allocation site list is build during root iteration, but if no sites // were encountered then it needs to be initialized to undefined. @@ -585,14 +574,9 @@ void Deserializer::Deserialize(Isolate* isolate) { } // Update data pointers to the external strings containing natives sources. - for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { - Object* source = isolate_->heap()->natives_source_cache()->get(i); - if (!source->IsUndefined()) { - ExternalOneByteString::cast(source)->update_data_cache(); - } - } - - FlushICacheForNewCodeObjects(); + Natives::UpdateSourceCache(isolate_->heap()); + ExtraNatives::UpdateSourceCache(isolate_->heap()); + CodeStubNatives::UpdateSourceCache(isolate_->heap()); // Issue code events for newly deserialized code objects. LOG_CODE_EVENT(isolate_, LogCodeObjects()); @@ -649,9 +633,10 @@ MaybeHandle<SharedFunctionInfo> Deserializer::DeserializeCode( Object* root; VisitPointer(&root); DeserializeDeferredObjects(); + FlushICacheForNewCodeObjects(); result = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(root)); } - CommitNewInternalizedStrings(isolate); + CommitPostProcessedObjects(isolate); return scope.CloseAndEscape(result); } } @@ -744,8 +729,7 @@ HeapObject* Deserializer::PostProcessNewObject(HeapObject* obj, int space) { } } } else if (obj->IsScript()) { - // Assign a new script id to avoid collision. - Script::cast(obj)->set_id(isolate_->heap()->NextScriptId()); + new_scripts_.Add(handle(Script::cast(obj))); } else { DCHECK(CanBeDeferred(obj)); } @@ -778,7 +762,7 @@ HeapObject* Deserializer::PostProcessNewObject(HeapObject* obj, int space) { } -void Deserializer::CommitNewInternalizedStrings(Isolate* isolate) { +void Deserializer::CommitPostProcessedObjects(Isolate* isolate) { StringTable::EnsureCapacityForDeserialization( isolate, new_internalized_strings_.length()); for (Handle<String> string : new_internalized_strings_) { @@ -786,6 +770,16 @@ void Deserializer::CommitNewInternalizedStrings(Isolate* isolate) { DCHECK_NULL(StringTable::LookupKeyIfExists(isolate, &key)); StringTable::LookupKey(isolate, &key); } + + Heap* heap = isolate->heap(); + Factory* factory = isolate->factory(); + for (Handle<Script> script : new_scripts_) { + // Assign a new script id to avoid collision. + script->set_id(isolate_->heap()->NextScriptId()); + // Add script to list. + Handle<Object> list = WeakFixedArray::Add(factory->script_list(), script); + heap->SetRootScriptList(*list); + } } @@ -907,6 +901,17 @@ Address Deserializer::Allocate(int space_index, int size) { } +Object** Deserializer::CopyInNativesSource(Vector<const char> source_vector, + Object** current) { + DCHECK(!isolate_->heap()->deserialization_complete()); + NativesExternalStringResource* resource = new NativesExternalStringResource( + source_vector.start(), source_vector.length()); + Object* resource_obj = reinterpret_cast<Object*>(resource); + UnalignedCopy(current++, &resource_obj); + return current; +} + + bool Deserializer::ReadData(Object** current, Object** limit, int source_space, Address current_object_address) { Isolate* const isolate = isolate_; @@ -950,8 +955,9 @@ bool Deserializer::ReadData(Object** current, Object** limit, int source_space, emit_write_barrier = (space_number == NEW_SPACE); \ new_object = GetBackReferencedObject(data & kSpaceMask); \ } else if (where == kRootArray) { \ - int root_id = source_.GetInt(); \ - new_object = isolate->heap()->roots_array_start()[root_id]; \ + int id = source_.GetInt(); \ + Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(id); \ + new_object = isolate->heap()->root(root_index); \ emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ } else if (where == kPartialSnapshotCache) { \ int cache_index = source_.GetInt(); \ @@ -1173,17 +1179,20 @@ bool Deserializer::ReadData(Object** current, Object** limit, int source_space, CHECK(false); break; - case kNativesStringResource: { - DCHECK(!isolate_->heap()->deserialization_complete()); - int index = source_.Get(); - Vector<const char> source_vector = Natives::GetScriptSource(index); - NativesExternalStringResource* resource = - new NativesExternalStringResource(source_vector.start(), - source_vector.length()); - Object* resource_obj = reinterpret_cast<Object*>(resource); - UnalignedCopy(current++, &resource_obj); + case kNativesStringResource: + current = CopyInNativesSource(Natives::GetScriptSource(source_.Get()), + current); + break; + + case kExtraNativesStringResource: + current = CopyInNativesSource( + ExtraNatives::GetScriptSource(source_.Get()), current); + break; + + case kCodeStubNativesStringResource: + current = CopyInNativesSource( + CodeStubNatives::GetScriptSource(source_.Get()), current); break; - } // Deserialize raw data of variable length. case kVariableRawData: { @@ -1222,8 +1231,9 @@ bool Deserializer::ReadData(Object** current, Object** limit, int source_space, SIXTEEN_CASES(kRootArrayConstants) SIXTEEN_CASES(kRootArrayConstants + 16) { - int root_id = data & kRootArrayConstantsMask; - Object* object = isolate->heap()->roots_array_start()[root_id]; + int id = data & kRootArrayConstantsMask; + Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(id); + Object* object = isolate->heap()->root(root_index); DCHECK(!isolate->heap()->InNewSpace(object)); UnalignedCopy(current++, &object); break; @@ -1368,6 +1378,66 @@ void Serializer::OutputStatistics(const char* name) { } +class Serializer::ObjectSerializer : public ObjectVisitor { + public: + ObjectSerializer(Serializer* serializer, Object* o, SnapshotByteSink* sink, + HowToCode how_to_code, WhereToPoint where_to_point) + : serializer_(serializer), + object_(HeapObject::cast(o)), + sink_(sink), + reference_representation_(how_to_code + where_to_point), + bytes_processed_so_far_(0), + is_code_object_(o->IsCode()), + code_has_been_output_(false) {} + void Serialize(); + void SerializeDeferred(); + void VisitPointers(Object** start, Object** end); + void VisitEmbeddedPointer(RelocInfo* target); + void VisitExternalReference(Address* p); + void VisitExternalReference(RelocInfo* rinfo); + void VisitInternalReference(RelocInfo* rinfo); + void VisitCodeTarget(RelocInfo* target); + void VisitCodeEntry(Address entry_address); + void VisitCell(RelocInfo* rinfo); + void VisitRuntimeEntry(RelocInfo* reloc); + // Used for seralizing the external strings that hold the natives source. + void VisitExternalOneByteString( + v8::String::ExternalOneByteStringResource** resource); + // We can't serialize a heap with external two byte strings. + void VisitExternalTwoByteString( + v8::String::ExternalStringResource** resource) { + UNREACHABLE(); + } + + private: + void SerializePrologue(AllocationSpace space, int size, Map* map); + + bool SerializeExternalNativeSourceString( + int builtin_count, + v8::String::ExternalOneByteStringResource** resource_pointer, + FixedArray* source_cache, int resource_index); + + enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn }; + // This function outputs or skips the raw data between the last pointer and + // up to the current position. It optionally can just return the number of + // bytes to skip instead of performing a skip instruction, in case the skip + // can be merged into the next instruction. + int OutputRawData(Address up_to, ReturnSkip return_skip = kIgnoringReturn); + // External strings are serialized in a way to resemble sequential strings. + void SerializeExternalString(); + + Address PrepareCode(); + + Serializer* serializer_; + HeapObject* object_; + SnapshotByteSink* sink_; + int reference_representation_; + int bytes_processed_so_far_; + bool is_code_object_; + bool code_has_been_output_; +}; + + void Serializer::SerializeDeferredObjects() { while (deferred_objects_.length() > 0) { HeapObject* obj = deferred_objects_.RemoveLast(); @@ -1419,6 +1489,17 @@ void PartialSerializer::Serialize(Object** o) { Context* context = Context::cast(*o); global_object_ = context->global_object(); back_reference_map()->AddGlobalProxy(context->global_proxy()); + // The bootstrap snapshot has a code-stub context. When serializing the + // partial snapshot, it is chained into the weak context list on the isolate + // and it's next context pointer may point to the code-stub context. Clear + // it before serializing, it will get re-added to the context list + // explicitly when it's loaded. + if (context->IsNativeContext()) { + context->set(Context::NEXT_CONTEXT_LINK, + isolate_->heap()->undefined_value()); + DCHECK(!context->global_object()->IsUndefined()); + DCHECK(!context->builtins()->IsUndefined()); + } } VisitPointer(o); SerializeDeferredObjects(); @@ -1518,6 +1599,11 @@ void SerializerDeserializer::Iterate(Isolate* isolate, } +bool SerializerDeserializer::CanBeDeferred(HeapObject* o) { + return !o->IsString() && !o->IsScript(); +} + + int PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) { Isolate* isolate = this->isolate(); List<Object*>* cache = isolate->partial_snapshot_cache(); @@ -1538,6 +1624,19 @@ int PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) { } +bool PartialSerializer::ShouldBeInThePartialSnapshotCache(HeapObject* o) { + // Scripts should be referred only through shared function infos. We can't + // allow them to be part of the partial snapshot because they contain a + // unique ID, and deserializing several partial snapshots containing script + // would cause dupes. + DCHECK(!o->IsScript()); + return o->IsName() || o->IsSharedFunctionInfo() || o->IsHeapNumber() || + o->IsCode() || o->IsScopeInfo() || o->IsExecutableAccessorInfo() || + o->map() == + startup_serializer_->isolate()->heap()->fixed_cow_array_map(); +} + + #ifdef DEBUG bool Serializer::BackReferenceIsAlreadyAllocated(BackReference reference) { DCHECK(reference.is_valid()); @@ -1621,9 +1720,23 @@ bool Serializer::SerializeKnownObject(HeapObject* obj, HowToCode how_to_code, } +StartupSerializer::StartupSerializer(Isolate* isolate, SnapshotByteSink* sink) + : Serializer(isolate, sink), root_index_wave_front_(0) { + // Clear the cache of objects used by the partial snapshot. After the + // strong roots have been serialized we can create a partial snapshot + // which will repopulate the cache with objects needed by that partial + // snapshot. + isolate->partial_snapshot_cache()->Clear(); + InitializeCodeAddressMap(); +} + + void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, WhereToPoint where_to_point, int skip) { - DCHECK(!obj->IsJSFunction()); + // Make sure that all functions are derived from the code-stub context + DCHECK(!obj->IsJSFunction() || + JSFunction::cast(obj)->GetCreationContext() == + isolate()->heap()->code_stub_context()); int root_index = root_index_map_.Lookup(obj); // We can only encode roots as such if it has already been serialized. @@ -1908,38 +2021,10 @@ void Serializer::ObjectSerializer::Serialize() { // We don't expect fillers. DCHECK(!object_->IsFiller()); - if (object_->IsPrototypeInfo()) { - Object* prototype_users = PrototypeInfo::cast(object_)->prototype_users(); - if (prototype_users->IsWeakFixedArray()) { - WeakFixedArray* array = WeakFixedArray::cast(prototype_users); - array->Compact<JSObject::PrototypeRegistryCompactionCallback>(); - } - } - // Compaction of a prototype users list can require the registered users - // to update their remembered slots. That doesn't work if those users - // have already been serialized themselves. So if this object is a - // registered user, compact its prototype's user list now. - if (object_->IsMap()) { - Map* map = Map::cast(object_); - if (map->is_prototype_map() && map->prototype_info()->IsPrototypeInfo() && - PrototypeInfo::cast(map->prototype_info())->registry_slot() != - PrototypeInfo::UNREGISTERED) { - JSObject* proto = JSObject::cast(map->prototype()); - PrototypeInfo* info = PrototypeInfo::cast(proto->map()->prototype_info()); - WeakFixedArray* array = WeakFixedArray::cast(info->prototype_users()); - array->Compact<JSObject::PrototypeRegistryCompactionCallback>(); - } - } - if (object_->IsScript()) { // Clear cached line ends. Object* undefined = serializer_->isolate()->heap()->undefined_value(); Script::cast(object_)->set_line_ends(undefined); - Object* shared_list = Script::cast(object_)->shared_function_infos(); - if (shared_list->IsWeakFixedArray()) { - WeakFixedArray::cast(shared_list) - ->Compact<WeakFixedArray::NullCallback>(); - } } if (object_->IsExternalString()) { @@ -2144,25 +2229,50 @@ void Serializer::ObjectSerializer::VisitCell(RelocInfo* rinfo) { } -void Serializer::ObjectSerializer::VisitExternalOneByteString( - v8::String::ExternalOneByteStringResource** resource_pointer) { - Address references_start = reinterpret_cast<Address>(resource_pointer); - OutputRawData(references_start); - for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { - Object* source = - serializer_->isolate()->heap()->natives_source_cache()->get(i); +bool Serializer::ObjectSerializer::SerializeExternalNativeSourceString( + int builtin_count, + v8::String::ExternalOneByteStringResource** resource_pointer, + FixedArray* source_cache, int resource_index) { + for (int i = 0; i < builtin_count; i++) { + Object* source = source_cache->get(i); if (!source->IsUndefined()) { ExternalOneByteString* string = ExternalOneByteString::cast(source); typedef v8::String::ExternalOneByteStringResource Resource; const Resource* resource = string->resource(); if (resource == *resource_pointer) { - sink_->Put(kNativesStringResource, "NativesStringResource"); + sink_->Put(resource_index, "NativesStringResource"); sink_->PutSection(i, "NativesStringResourceEnd"); bytes_processed_so_far_ += sizeof(resource); - return; + return true; } } } + return false; +} + + +void Serializer::ObjectSerializer::VisitExternalOneByteString( + v8::String::ExternalOneByteStringResource** resource_pointer) { + Address references_start = reinterpret_cast<Address>(resource_pointer); + OutputRawData(references_start); + if (SerializeExternalNativeSourceString( + Natives::GetBuiltinsCount(), resource_pointer, + Natives::GetSourceCache(serializer_->isolate()->heap()), + kNativesStringResource)) { + return; + } + if (SerializeExternalNativeSourceString( + ExtraNatives::GetBuiltinsCount(), resource_pointer, + ExtraNatives::GetSourceCache(serializer_->isolate()->heap()), + kExtraNativesStringResource)) { + return; + } + if (SerializeExternalNativeSourceString( + CodeStubNatives::GetBuiltinsCount(), resource_pointer, + CodeStubNatives::GetSourceCache(serializer_->isolate()->heap()), + kCodeStubNativesStringResource)) { + return; + } // One of the strings in the natives cache should match the resource. We // don't expect any other kinds of external strings here. UNREACHABLE(); @@ -2371,6 +2481,8 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, SerializeGeneric(code_object, how_to_code, where_to_point); } return; + case Code::WASM_FUNCTION: + UNREACHABLE(); } UNREACHABLE(); } @@ -2428,8 +2540,7 @@ void CodeSerializer::SerializeCodeStub(uint32_t stub_key, HowToCode how_to_code, if (FLAG_trace_serializer) { PrintF(" Encoding code stub %s as %d\n", - CodeStub::MajorName(CodeStub::MajorKeyFromKey(stub_key), false), - index); + CodeStub::MajorName(CodeStub::MajorKeyFromKey(stub_key)), index); } sink_->Put(kAttachedReference + how_to_code + where_to_point, "CodeStub"); @@ -2494,7 +2605,7 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( HandleScope scope(isolate); - SmartPointer<SerializedCodeData> scd( + base::SmartPointer<SerializedCodeData> scd( SerializedCodeData::FromCachedData(isolate, cached_data, *source)); if (scd.is_empty()) { if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n"); @@ -2522,7 +2633,6 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n"); return MaybeHandle<SharedFunctionInfo>(); } - deserializer.FlushICacheForNewCodeObjects(); if (FLAG_profile_deserialization) { double ms = timer.Elapsed().InMillisecondsF(); @@ -2715,6 +2825,11 @@ SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck( } +uint32_t SerializedCodeData::SourceHash(String* source) const { + return source->length(); +} + + // Return ScriptData object and relinquish ownership over it to the caller. ScriptData* SerializedCodeData::GetScriptData() { DCHECK(owns_data_); diff --git a/chromium/v8/src/snapshot/serialize.h b/chromium/v8/src/snapshot/serialize.h index 001d7753922..2863ede5034 100644 --- a/chromium/v8/src/snapshot/serialize.h +++ b/chromium/v8/src/snapshot/serialize.h @@ -6,13 +6,14 @@ #define V8_SNAPSHOT_SERIALIZE_H_ #include "src/hashmap.h" -#include "src/heap-profiler.h" -#include "src/isolate.h" +#include "src/heap/heap.h" +#include "src/objects.h" #include "src/snapshot/snapshot-source-sink.h" namespace v8 { namespace internal { +class Isolate; class ScriptData; static const int kDeoptTableSerializeEntryCount = 64; @@ -156,6 +157,8 @@ class BackReference { ChunkOffsetBits::encode(index)); } + static BackReference DummyReference() { return BackReference(kDummyValue); } + static BackReference Reference(AllocationSpace space, uint32_t chunk_index, uint32_t chunk_offset) { DCHECK(IsAligned(chunk_offset, kObjectAlignment)); @@ -201,6 +204,7 @@ class BackReference { static const uint32_t kInvalidValue = 0xFFFFFFFF; static const uint32_t kSourceValue = 0xFFFFFFFE; static const uint32_t kGlobalProxyValue = 0xFFFFFFFD; + static const uint32_t kDummyValue = 0xFFFFFFFC; static const int kChunkOffsetSize = kPageSizeBits - kObjectAlignmentBits; static const int kChunkIndexSize = 32 - kChunkOffsetSize - kSpaceTagSize; @@ -306,9 +310,7 @@ class SerializerDeserializer: public ObjectVisitor { static const int kNumberOfSpaces = LAST_SPACE + 1; protected: - static bool CanBeDeferred(HeapObject* o) { - return !o->IsString() && !o->IsScript(); - } + static bool CanBeDeferred(HeapObject* o); // ---------- byte code range 0x00..0x7f ---------- // Byte codes in this range represent Where, HowToCode and WhereToPoint. @@ -381,23 +383,29 @@ class SerializerDeserializer: public ObjectVisitor { static const int kNextChunk = 0x3e; // Deferring object content. static const int kDeferred = 0x3f; + // Used for the source code of the natives, which is in the executable, but + // is referred to from external strings in the snapshot. + static const int kNativesStringResource = 0x5d; + // Used for the source code for compiled stubs, which is in the executable, + // but is referred to from external strings in the snapshot. + static const int kCodeStubNativesStringResource = 0x5e; + // Used for the source code for V8 extras, which is in the executable, + // but is referred to from external strings in the snapshot. + static const int kExtraNativesStringResource = 0x5f; // A tag emitted at strategic points in the snapshot to delineate sections. // If the deserializer does not find these at the expected moments then it // is an indication that the snapshot and the VM do not fit together. // Examine the build process for architecture, version or configuration // mismatches. static const int kSynchronize = 0x17; - // Used for the source code of the natives, which is in the executable, but - // is referred to from external strings in the snapshot. - static const int kNativesStringResource = 0x37; + // Repeats of variable length. + static const int kVariableRepeat = 0x37; // Raw data of variable length. static const int kVariableRawData = 0x57; - // Repeats of variable length. - static const int kVariableRepeat = 0x77; // Alignment prefixes 0x7d..0x7f static const int kAlignmentPrefix = 0x7d; - // 0x5d..0x5f unused + // 0x77 unused // ---------- byte code range 0x80..0xff ---------- // First 32 root array items. @@ -539,8 +547,6 @@ class Deserializer: public SerializerDeserializer { // Deserialize a shared function info. Fail gracefully. MaybeHandle<SharedFunctionInfo> DeserializeCode(Isolate* isolate); - void FlushICacheForNewCodeObjects(); - // Pass a vector of externally-provided objects referenced by the snapshot. // The ownership to its backing store is handed over as well. void SetAttachedObjects(Vector<Handle<Object> > attached_objects) { @@ -568,7 +574,10 @@ class Deserializer: public SerializerDeserializer { void DeserializeDeferredObjects(); - void CommitNewInternalizedStrings(Isolate* isolate); + void FlushICacheForNewIsolate(); + void FlushICacheForNewCodeObjects(); + + void CommitPostProcessedObjects(Isolate* isolate); // Fills in some heap data in an area from start to end (non-inclusive). The // space id is used for the write barrier. The object_address is the address @@ -587,6 +596,9 @@ class Deserializer: public SerializerDeserializer { // snapshot by chunk index and offset. HeapObject* GetBackReferencedObject(int space); + Object** CopyInNativesSource(Vector<const char> source_vector, + Object** current); + // Cached current isolate. Isolate* isolate_; @@ -609,6 +621,7 @@ class Deserializer: public SerializerDeserializer { List<HeapObject*> deserialized_large_objects_; List<Code*> new_code_objects_; List<Handle<String> > new_internalized_strings_; + List<Handle<Script> > new_scripts_; bool deserializing_user_code_; @@ -641,60 +654,7 @@ class Serializer : public SerializerDeserializer { #endif // OBJECT_PRINT protected: - class ObjectSerializer : public ObjectVisitor { - public: - ObjectSerializer(Serializer* serializer, Object* o, SnapshotByteSink* sink, - HowToCode how_to_code, WhereToPoint where_to_point) - : serializer_(serializer), - object_(HeapObject::cast(o)), - sink_(sink), - reference_representation_(how_to_code + where_to_point), - bytes_processed_so_far_(0), - is_code_object_(o->IsCode()), - code_has_been_output_(false) {} - void Serialize(); - void SerializeDeferred(); - void VisitPointers(Object** start, Object** end); - void VisitEmbeddedPointer(RelocInfo* target); - void VisitExternalReference(Address* p); - void VisitExternalReference(RelocInfo* rinfo); - void VisitInternalReference(RelocInfo* rinfo); - void VisitCodeTarget(RelocInfo* target); - void VisitCodeEntry(Address entry_address); - void VisitCell(RelocInfo* rinfo); - void VisitRuntimeEntry(RelocInfo* reloc); - // Used for seralizing the external strings that hold the natives source. - void VisitExternalOneByteString( - v8::String::ExternalOneByteStringResource** resource); - // We can't serialize a heap with external two byte strings. - void VisitExternalTwoByteString( - v8::String::ExternalStringResource** resource) { - UNREACHABLE(); - } - - private: - void SerializePrologue(AllocationSpace space, int size, Map* map); - - enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn }; - // This function outputs or skips the raw data between the last pointer and - // up to the current position. It optionally can just return the number of - // bytes to skip instead of performing a skip instruction, in case the skip - // can be merged into the next instruction. - int OutputRawData(Address up_to, ReturnSkip return_skip = kIgnoringReturn); - // External strings are serialized in a way to resemble sequential strings. - void SerializeExternalString(); - - Address PrepareCode(); - - Serializer* serializer_; - HeapObject* object_; - SnapshotByteSink* sink_; - int reference_representation_; - int bytes_processed_so_far_; - bool is_code_object_; - bool code_has_been_output_; - }; - + class ObjectSerializer; class RecursionScope { public: explicit RecursionScope(Serializer* serializer) : serializer_(serializer) { @@ -833,17 +793,7 @@ class PartialSerializer : public Serializer { private: int PartialSnapshotCacheIndex(HeapObject* o); - bool ShouldBeInThePartialSnapshotCache(HeapObject* o) { - // Scripts should be referred only through shared function infos. We can't - // allow them to be part of the partial snapshot because they contain a - // unique ID, and deserializing several partial snapshots containing script - // would cause dupes. - DCHECK(!o->IsScript()); - return o->IsName() || o->IsSharedFunctionInfo() || o->IsHeapNumber() || - o->IsCode() || o->IsScopeInfo() || o->IsExecutableAccessorInfo() || - o->map() == - startup_serializer_->isolate()->heap()->fixed_cow_array_map(); - } + bool ShouldBeInThePartialSnapshotCache(HeapObject* o); void SerializeOutdatedContextsAsFixedArray(); @@ -857,16 +807,7 @@ class PartialSerializer : public Serializer { class StartupSerializer : public Serializer { public: - StartupSerializer(Isolate* isolate, SnapshotByteSink* sink) - : Serializer(isolate, sink), root_index_wave_front_(0) { - // Clear the cache of objects used by the partial snapshot. After the - // strong roots have been serialized we can create a partial snapshot - // which will repopulate the cache with objects needed by that partial - // snapshot. - isolate->partial_snapshot_cache()->Clear(); - InitializeCodeAddressMap(); - } - + StartupSerializer(Isolate* isolate, SnapshotByteSink* sink); ~StartupSerializer() { OutputStatistics("StartupSerializer"); } // The StartupSerializer has to serialize the root array, which is slightly @@ -1013,7 +954,7 @@ class SerializedCodeData : public SerializedData { SanityCheckResult SanityCheck(Isolate* isolate, String* source) const; - uint32_t SourceHash(String* source) const { return source->length(); } + uint32_t SourceHash(String* source) const; // The data header consists of uint32_t-sized entries: // [0] magic number and external reference count diff --git a/chromium/v8/src/snapshot/snapshot-common.cc b/chromium/v8/src/snapshot/snapshot-common.cc index ab8a88486ea..0b7e11d1ec4 100644 --- a/chromium/v8/src/snapshot/snapshot-common.cc +++ b/chromium/v8/src/snapshot/snapshot-common.cc @@ -4,12 +4,11 @@ // The common functionality when building with or without snapshots. -#include "src/v8.h" +#include "src/snapshot/snapshot.h" #include "src/api.h" #include "src/base/platform/platform.h" -#include "src/full-codegen.h" -#include "src/snapshot/snapshot.h" +#include "src/full-codegen/full-codegen.h" namespace v8 { namespace internal { @@ -22,6 +21,13 @@ bool Snapshot::SnapshotIsValid(v8::StartupData* snapshot_blob) { #endif // DEBUG +bool Snapshot::HaveASnapshotToStartFrom(Isolate* isolate) { + // Do not use snapshots if the isolate is used to create snapshots. + return isolate->snapshot_blob() != NULL && + isolate->snapshot_blob()->data != NULL; +} + + bool Snapshot::EmbedsScript(Isolate* isolate) { if (!isolate->snapshot_available()) return false; return ExtractMetadata(isolate->snapshot_blob()).embeds_script(); @@ -137,7 +143,7 @@ void CalculateFirstPageSizes(bool is_default_snapshot, 2 * context_reservations[context_index].chunk_size()) + Page::kObjectStartOffset; // Add a small allowance to the code space for small scripts. - if (space == CODE_SPACE) required += 64 * KB; + if (space == CODE_SPACE) required += 32 * KB; } else { // We expect the vanilla snapshot to only require on page per space. DCHECK(!is_default_snapshot); diff --git a/chromium/v8/src/snapshot/snapshot-empty.cc b/chromium/v8/src/snapshot/snapshot-empty.cc index 464d3a800a3..35cb6c38f5e 100644 --- a/chromium/v8/src/snapshot/snapshot-empty.cc +++ b/chromium/v8/src/snapshot/snapshot-empty.cc @@ -4,8 +4,6 @@ // Used for building without snapshots. -#include "src/v8.h" - #include "src/snapshot/snapshot.h" namespace v8 { diff --git a/chromium/v8/src/snapshot/snapshot.h b/chromium/v8/src/snapshot/snapshot.h index 7f89213f16c..1379644fd85 100644 --- a/chromium/v8/src/snapshot/snapshot.h +++ b/chromium/v8/src/snapshot/snapshot.h @@ -2,15 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/isolate.h" -#include "src/snapshot/serialize.h" - #ifndef V8_SNAPSHOT_SNAPSHOT_H_ #define V8_SNAPSHOT_SNAPSHOT_H_ +#include "src/snapshot/serialize.h" + namespace v8 { namespace internal { +// Forward declarations. +class Isolate; +class PartialSerializer; +class StartupSerializer; + class Snapshot : public AllStatic { public: class Metadata { @@ -36,11 +40,7 @@ class Snapshot : public AllStatic { Isolate* isolate, Handle<JSGlobalProxy> global_proxy, Handle<FixedArray>* outdated_contexts_out); - static bool HaveASnapshotToStartFrom(Isolate* isolate) { - // Do not use snapshots if the isolate is used to create snapshots. - return isolate->snapshot_blob() != NULL && - isolate->snapshot_blob()->data != NULL; - } + static bool HaveASnapshotToStartFrom(Isolate* isolate); static bool EmbedsScript(Isolate* isolate); |