diff options
author | Michaël Zasso <targos@protonmail.com> | 2019-08-01 08:38:30 +0200 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2019-08-01 12:53:56 +0200 |
commit | 2dcc3665abf57c3607cebffdeeca062f5894885d (patch) | |
tree | 4f560748132edcfb4c22d6f967a7e80d23d7ea2c /deps/v8/src/snapshot | |
parent | 1ee47d550c6de132f06110aa13eceb7551d643b3 (diff) | |
download | android-node-v8-2dcc3665abf57c3607cebffdeeca062f5894885d.tar.gz android-node-v8-2dcc3665abf57c3607cebffdeeca062f5894885d.tar.bz2 android-node-v8-2dcc3665abf57c3607cebffdeeca062f5894885d.zip |
deps: update V8 to 7.6.303.28
PR-URL: https://github.com/nodejs/node/pull/28016
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Refael Ackermann (רפאל פלחי) <refack@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Diffstat (limited to 'deps/v8/src/snapshot')
48 files changed, 2482 insertions, 1862 deletions
diff --git a/deps/v8/src/snapshot/code-serializer.cc b/deps/v8/src/snapshot/code-serializer.cc index da60ea189d..b4e75a6c20 100644 --- a/deps/v8/src/snapshot/code-serializer.cc +++ b/deps/v8/src/snapshot/code-serializer.cc @@ -4,17 +4,17 @@ #include "src/snapshot/code-serializer.h" -#include "src/counters.h" +#include "src/codegen/macro-assembler.h" #include "src/debug/debug.h" #include "src/heap/heap-inl.h" -#include "src/log.h" -#include "src/macro-assembler.h" -#include "src/objects-inl.h" +#include "src/logging/counters.h" +#include "src/logging/log.h" +#include "src/objects/objects-inl.h" #include "src/objects/slots.h" +#include "src/objects/visitors.h" #include "src/snapshot/object-deserializer.h" #include "src/snapshot/snapshot.h" -#include "src/version.h" -#include "src/visitors.h" +#include "src/utils/version.h" namespace v8 { namespace internal { @@ -50,15 +50,13 @@ ScriptCompiler::CachedData* CodeSerializer::Serialize( Handle<Script> script(Script::cast(info->script()), isolate); if (FLAG_trace_serializer) { PrintF("[Serializing from"); - script->name()->ShortPrint(); + script->name().ShortPrint(); PrintF("]\n"); } // TODO(7110): Enable serialization of Asm modules once the AsmWasmData is // context independent. if (script->ContainsAsmModule()) return nullptr; - isolate->heap()->read_only_space()->ClearStringPaddingIfNeeded(); - // Serialize code object. Handle<String> source(String::cast(script->source()), isolate); CodeSerializer cs(isolate, SerializedCodeData::SourceHash( @@ -104,7 +102,7 @@ bool CodeSerializer::SerializeReadOnlyObject(HeapObject obj) { // For objects in RO_SPACE, never serialize the object, but instead create a // back reference that encodes the page number as the chunk_index and the // offset within the page as the chunk_offset. - Address address = obj->address(); + Address address = obj.address(); Page* page = Page::FromAddress(address); uint32_t chunk_index = 0; for (Page* p : *read_only_space) { @@ -114,7 +112,7 @@ bool CodeSerializer::SerializeReadOnlyObject(HeapObject obj) { uint32_t chunk_offset = static_cast<uint32_t>(page->Offset(address)); SerializerReference back_reference = SerializerReference::BackReference(RO_SPACE, chunk_index, chunk_offset); - reference_map()->Add(reinterpret_cast<void*>(obj->ptr()), back_reference); + reference_map()->Add(reinterpret_cast<void*>(obj.ptr()), back_reference); CHECK(SerializeBackReference(obj)); return true; } @@ -128,60 +126,60 @@ void CodeSerializer::SerializeObject(HeapObject obj) { if (SerializeReadOnlyObject(obj)) return; - CHECK(!obj->IsCode()); + CHECK(!obj.IsCode()); ReadOnlyRoots roots(isolate()); if (ElideObject(obj)) { return SerializeObject(roots.undefined_value()); } - if (obj->IsScript()) { + if (obj.IsScript()) { Script script_obj = Script::cast(obj); - DCHECK_NE(script_obj->compilation_type(), Script::COMPILATION_TYPE_EVAL); + DCHECK_NE(script_obj.compilation_type(), Script::COMPILATION_TYPE_EVAL); // We want to differentiate between undefined and uninitialized_symbol for // context_data for now. It is hack to allow debugging for scripts that are // included as a part of custom snapshot. (see debug::Script::IsEmbedded()) - Object context_data = script_obj->context_data(); + Object context_data = script_obj.context_data(); if (context_data != roots.undefined_value() && context_data != roots.uninitialized_symbol()) { - script_obj->set_context_data(roots.undefined_value()); + script_obj.set_context_data(roots.undefined_value()); } // We don't want to serialize host options to avoid serializing unnecessary // object graph. - FixedArray host_options = script_obj->host_defined_options(); - script_obj->set_host_defined_options(roots.empty_fixed_array()); + FixedArray host_options = script_obj.host_defined_options(); + script_obj.set_host_defined_options(roots.empty_fixed_array()); SerializeGeneric(obj); - script_obj->set_host_defined_options(host_options); - script_obj->set_context_data(context_data); + script_obj.set_host_defined_options(host_options); + script_obj.set_context_data(context_data); return; } - if (obj->IsSharedFunctionInfo()) { + if (obj.IsSharedFunctionInfo()) { SharedFunctionInfo sfi = SharedFunctionInfo::cast(obj); // TODO(7110): Enable serializing of Asm modules once the AsmWasmData // is context independent. - DCHECK(!sfi->IsApiFunction() && !sfi->HasAsmWasmData()); + DCHECK(!sfi.IsApiFunction() && !sfi.HasAsmWasmData()); DebugInfo debug_info; BytecodeArray debug_bytecode_array; - if (sfi->HasDebugInfo()) { + if (sfi.HasDebugInfo()) { // Clear debug info. - debug_info = sfi->GetDebugInfo(); - if (debug_info->HasInstrumentedBytecodeArray()) { - debug_bytecode_array = debug_info->DebugBytecodeArray(); - sfi->SetDebugBytecodeArray(debug_info->OriginalBytecodeArray()); + debug_info = sfi.GetDebugInfo(); + if (debug_info.HasInstrumentedBytecodeArray()) { + debug_bytecode_array = debug_info.DebugBytecodeArray(); + sfi.SetDebugBytecodeArray(debug_info.OriginalBytecodeArray()); } - sfi->set_script_or_debug_info(debug_info->script()); + sfi.set_script_or_debug_info(debug_info.script()); } - DCHECK(!sfi->HasDebugInfo()); + DCHECK(!sfi.HasDebugInfo()); SerializeGeneric(obj); // Restore debug info if (!debug_info.is_null()) { - sfi->set_script_or_debug_info(debug_info); + sfi.set_script_or_debug_info(debug_info); if (!debug_bytecode_array.is_null()) { - sfi->SetDebugBytecodeArray(debug_bytecode_array); + sfi.SetDebugBytecodeArray(debug_bytecode_array); } } return; @@ -194,24 +192,24 @@ void CodeSerializer::SerializeObject(HeapObject obj) { // --interpreted-frames-native-stack is on. See v8:9122 for more context #ifndef V8_TARGET_ARCH_ARM if (V8_UNLIKELY(FLAG_interpreted_frames_native_stack) && - obj->IsInterpreterData()) { - obj = InterpreterData::cast(obj)->bytecode_array(); + obj.IsInterpreterData()) { + obj = InterpreterData::cast(obj).bytecode_array(); } #endif // V8_TARGET_ARCH_ARM - if (obj->IsBytecodeArray()) { + if (obj.IsBytecodeArray()) { // Clear the stack frame cache if present - BytecodeArray::cast(obj)->ClearFrameCacheFromSourcePositionTable(); + BytecodeArray::cast(obj).ClearFrameCacheFromSourcePositionTable(); } // Past this point we should not see any (context-specific) maps anymore. - CHECK(!obj->IsMap()); + CHECK(!obj.IsMap()); // There should be no references to the global object embedded. - CHECK(!obj->IsJSGlobalProxy() && !obj->IsJSGlobalObject()); + CHECK(!obj.IsJSGlobalProxy() && !obj.IsJSGlobalObject()); // Embedded FixedArrays that need rehashing must support rehashing. - CHECK_IMPLIES(obj->NeedsRehashing(), obj->CanBeRehashed()); + CHECK_IMPLIES(obj.NeedsRehashing(), obj.CanBeRehashed()); // We expect no instantiated function objects or contexts. - CHECK(!obj->IsJSFunction() && !obj->IsContext()); + CHECK(!obj.IsJSFunction() && !obj.IsContext()); SerializeGeneric(obj); } @@ -233,13 +231,13 @@ void CreateInterpreterDataForDeserializedCode(Isolate* isolate, Script script = Script::cast(sfi->script()); Handle<Script> script_handle(script, isolate); String name = ReadOnlyRoots(isolate).empty_string(); - if (script->name()->IsString()) name = String::cast(script->name()); + if (script.name().IsString()) name = String::cast(script.name()); Handle<String> name_handle(name, isolate); SharedFunctionInfo::ScriptIterator iter(isolate, script); for (SharedFunctionInfo info = iter.Next(); !info.is_null(); info = iter.Next()) { - if (!info->HasBytecodeArray()) continue; + if (!info.HasBytecodeArray()) continue; Handle<Code> code = isolate->factory()->CopyCode(Handle<Code>::cast( isolate->factory()->interpreter_entry_trampoline_for_profiling())); @@ -247,15 +245,15 @@ void CreateInterpreterDataForDeserializedCode(Isolate* isolate, Handle<InterpreterData>::cast(isolate->factory()->NewStruct( INTERPRETER_DATA_TYPE, AllocationType::kOld)); - interpreter_data->set_bytecode_array(info->GetBytecodeArray()); + interpreter_data->set_bytecode_array(info.GetBytecodeArray()); interpreter_data->set_interpreter_trampoline(*code); - info->set_interpreter_data(*interpreter_data); + info.set_interpreter_data(*interpreter_data); if (!log_code_creation) continue; Handle<AbstractCode> abstract_code = Handle<AbstractCode>::cast(code); - int line_num = script->GetLineNumber(info->StartPosition()) + 1; - int column_num = script->GetColumnNumber(info->StartPosition()) + 1; + int line_num = script.GetLineNumber(info.StartPosition()) + 1; + int column_num = script.GetColumnNumber(info.StartPosition()) + 1; PROFILE(isolate, CodeCreateEvent(CodeEventListener::INTERPRETED_FUNCTION_TAG, *abstract_code, info, *name_handle, line_num, @@ -320,6 +318,7 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( ? String::cast(script->name()) : ReadOnlyRoots(isolate).empty_string(), isolate); + if (FLAG_log_function_events) { LOG(isolate, FunctionEvent("deserialize", script->id(), @@ -328,15 +327,16 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( } if (log_code_creation) { Script::InitLineEnds(script); + DisallowHeapAllocation no_gc; SharedFunctionInfo::ScriptIterator iter(isolate, *script); for (i::SharedFunctionInfo info = iter.Next(); !info.is_null(); info = iter.Next()) { - if (info->is_compiled()) { - int line_num = script->GetLineNumber(info->StartPosition()) + 1; - int column_num = script->GetColumnNumber(info->StartPosition()) + 1; + if (info.is_compiled()) { + int line_num = script->GetLineNumber(info.StartPosition()) + 1; + int column_num = script->GetColumnNumber(info.StartPosition()) + 1; PROFILE(isolate, CodeCreateEvent(CodeEventListener::SCRIPT_TAG, - info->abstract_code(), info, *name, + info.abstract_code(), info, *name, line_num, column_num)); } } diff --git a/deps/v8/src/snapshot/deserializer-allocator.cc b/deps/v8/src/snapshot/deserializer-allocator.cc index 7862865d43..4fb600d1dd 100644 --- a/deps/v8/src/snapshot/deserializer-allocator.cc +++ b/deps/v8/src/snapshot/deserializer-allocator.cc @@ -29,7 +29,7 @@ Address DeserializerAllocator::AllocateRaw(AllocationSpace space, int size) { AllocationResult result = lo_space->AllocateRaw(size); HeapObject obj = result.ToObjectChecked(); deserialized_large_objects_.push_back(obj); - return obj->address(); + return obj.address(); } else if (space == MAP_SPACE) { DCHECK_EQ(Map::kSize, size); return allocated_maps_[next_map_index_++]; @@ -44,7 +44,10 @@ Address DeserializerAllocator::AllocateRaw(AllocationSpace space, int size) { int chunk_index = current_chunk_[space]; DCHECK_LE(high_water_[space], reservation[chunk_index].end); #endif - if (space == CODE_SPACE) SkipList::Update(address, size); + if (space == CODE_SPACE) + MemoryChunk::FromAddress(address) + ->GetCodeObjectRegistry() + ->RegisterNewlyAllocatedCodeObject(address); return address; } } @@ -60,11 +63,11 @@ Address DeserializerAllocator::Allocate(AllocationSpace space, int size) { // If one of the following assertions fails, then we are deserializing an // aligned object when the filler maps have not been deserialized yet. // We require filler maps as padding to align the object. - DCHECK(ReadOnlyRoots(heap_).free_space_map()->IsMap()); - DCHECK(ReadOnlyRoots(heap_).one_pointer_filler_map()->IsMap()); - DCHECK(ReadOnlyRoots(heap_).two_pointer_filler_map()->IsMap()); + DCHECK(ReadOnlyRoots(heap_).free_space_map().IsMap()); + DCHECK(ReadOnlyRoots(heap_).one_pointer_filler_map().IsMap()); + DCHECK(ReadOnlyRoots(heap_).two_pointer_filler_map().IsMap()); obj = heap_->AlignWithFiller(obj, size, reserved, next_alignment_); - address = obj->address(); + address = obj.address(); next_alignment_ = kWordAligned; return address; } else { @@ -103,7 +106,7 @@ HeapObject DeserializerAllocator::GetObject(AllocationSpace space, if (next_alignment_ != kWordAligned) { int padding = Heap::GetFillToAlign(address, next_alignment_); next_alignment_ = kWordAligned; - DCHECK(padding == 0 || HeapObject::FromAddress(address)->IsFiller()); + DCHECK(padding == 0 || HeapObject::FromAddress(address).IsFiller()); address += padding; } return HeapObject::FromAddress(address); diff --git a/deps/v8/src/snapshot/deserializer-allocator.h b/deps/v8/src/snapshot/deserializer-allocator.h index 56bd4d1b0e..27cacc79d5 100644 --- a/deps/v8/src/snapshot/deserializer-allocator.h +++ b/deps/v8/src/snapshot/deserializer-allocator.h @@ -5,7 +5,7 @@ #ifndef V8_SNAPSHOT_DESERIALIZER_ALLOCATOR_H_ #define V8_SNAPSHOT_DESERIALIZER_ALLOCATOR_H_ -#include "src/globals.h" +#include "src/common/globals.h" #include "src/heap/heap.h" #include "src/objects/heap-object.h" #include "src/snapshot/serializer-common.h" diff --git a/deps/v8/src/snapshot/deserializer.cc b/deps/v8/src/snapshot/deserializer.cc index 3759c53c21..1fd590db26 100644 --- a/deps/v8/src/snapshot/deserializer.cc +++ b/deps/v8/src/snapshot/deserializer.cc @@ -4,24 +4,24 @@ #include "src/snapshot/deserializer.h" -#include "src/assembler-inl.h" +#include "src/codegen/assembler-inl.h" +#include "src/execution/isolate.h" #include "src/heap/heap-inl.h" #include "src/heap/heap-write-barrier-inl.h" #include "src/heap/read-only-heap.h" #include "src/interpreter/interpreter.h" -#include "src/isolate.h" -#include "src/log.h" -#include "src/objects-body-descriptors-inl.h" +#include "src/logging/log.h" #include "src/objects/api-callbacks.h" #include "src/objects/cell-inl.h" #include "src/objects/hash-table.h" #include "src/objects/js-array-buffer-inl.h" #include "src/objects/js-array-inl.h" #include "src/objects/maybe-object.h" +#include "src/objects/objects-body-descriptors-inl.h" #include "src/objects/slots.h" #include "src/objects/smi.h" #include "src/objects/string.h" -#include "src/roots.h" +#include "src/roots/roots.h" #include "src/snapshot/natives.h" #include "src/snapshot/snapshot.h" #include "src/tracing/trace-event.h" @@ -71,7 +71,7 @@ void Deserializer::Initialize(Isolate* isolate) { void Deserializer::Rehash() { DCHECK(can_rehash() || deserializing_user_code()); for (HeapObject item : to_rehash_) { - item->RehashBasedOnMap(ReadOnlyRoots(isolate_)); + item.RehashBasedOnMap(ReadOnlyRoots(isolate_)); } } @@ -117,7 +117,7 @@ void Deserializer::DeserializeDeferredObjects() { DCHECK_EQ(code - space, kNewObject); HeapObject object = GetBackReferencedObject(space); int size = source_.GetInt() << kTaggedSizeLog2; - Address obj_address = object->address(); + Address obj_address = object.address(); // Object's map is already initialized, now read the rest. MaybeObjectSlot start(obj_address + kTaggedSize); MaybeObjectSlot end(obj_address + size); @@ -154,28 +154,26 @@ void Deserializer::LogNewMapEvents() { void Deserializer::LogScriptEvents(Script script) { DisallowHeapAllocation no_gc; LOG(isolate_, - ScriptEvent(Logger::ScriptEventType::kDeserialize, script->id())); + ScriptEvent(Logger::ScriptEventType::kDeserialize, script.id())); LOG(isolate_, ScriptDetails(script)); TRACE_EVENT_OBJECT_CREATED_WITH_ID( TRACE_DISABLED_BY_DEFAULT("v8.compile"), "Script", - TRACE_ID_WITH_SCOPE("v8::internal::Script", script->id())); + TRACE_ID_WITH_SCOPE("v8::internal::Script", script.id())); TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( TRACE_DISABLED_BY_DEFAULT("v8.compile"), "Script", - TRACE_ID_WITH_SCOPE("v8::internal::Script", script->id()), - script->ToTracedValue()); + TRACE_ID_WITH_SCOPE("v8::internal::Script", script.id()), + script.ToTracedValue()); } StringTableInsertionKey::StringTableInsertionKey(String string) - : StringTableKey(ComputeHashField(string)), string_(string) { - DCHECK(string->IsInternalizedString()); + : StringTableKey(ComputeHashField(string), string.length()), + string_(string) { + DCHECK(string.IsInternalizedString()); } -bool StringTableInsertionKey::IsMatch(Object string) { - // We know that all entries in a hash table had their hash keys created. - // Use that knowledge to have fast failure. - if (Hash() != String::cast(string)->Hash()) return false; - // We want to compare the content of two internalized strings here. - return string_->SlowEquals(String::cast(string)); +bool StringTableInsertionKey::IsMatch(String string) { + // We want to compare the content of two strings here. + return string_.SlowEquals(string); } Handle<String> StringTableInsertionKey::AsHandle(Isolate* isolate) { @@ -184,44 +182,58 @@ Handle<String> StringTableInsertionKey::AsHandle(Isolate* isolate) { uint32_t StringTableInsertionKey::ComputeHashField(String string) { // Make sure hash_field() is computed. - string->Hash(); - return string->hash_field(); + string.Hash(); + return string.hash_field(); } +namespace { + +String ForwardStringIfExists(Isolate* isolate, StringTableInsertionKey* key) { + StringTable table = isolate->heap()->string_table(); + int entry = table.FindEntry(isolate, key); + if (entry == kNotFound) return String(); + + String canonical = String::cast(table.KeyAt(entry)); + DCHECK_NE(canonical, key->string()); + key->string().MakeThin(isolate, canonical); + return canonical; +} + +} // namespace + HeapObject Deserializer::PostProcessNewObject(HeapObject obj, int space) { if ((FLAG_rehash_snapshot && can_rehash_) || deserializing_user_code()) { - if (obj->IsString()) { + if (obj.IsString()) { // Uninitialize hash field as we need to recompute the hash. String string = String::cast(obj); - string->set_hash_field(String::kEmptyHashField); + string.set_hash_field(String::kEmptyHashField); // Rehash strings before read-only space is sealed. Strings outside // read-only space are rehashed lazily. (e.g. when rehashing dictionaries) if (space == RO_SPACE) { to_rehash_.push_back(obj); } - } else if (obj->NeedsRehashing()) { + } else if (obj.NeedsRehashing()) { to_rehash_.push_back(obj); } } if (deserializing_user_code()) { - if (obj->IsString()) { + if (obj.IsString()) { String string = String::cast(obj); - if (string->IsInternalizedString()) { + if (string.IsInternalizedString()) { // Canonicalize the internalized string. If it already exists in the // string table, set it to forward to the existing one. StringTableInsertionKey key(string); - String canonical = - StringTable::ForwardStringIfExists(isolate_, &key, string); + String canonical = ForwardStringIfExists(isolate_, &key); if (!canonical.is_null()) return canonical; new_internalized_strings_.push_back(handle(string, isolate_)); return string; } - } else if (obj->IsScript()) { + } else if (obj.IsScript()) { new_scripts_.push_back(handle(Script::cast(obj), isolate_)); - } else if (obj->IsAllocationSite()) { + } else if (obj.IsAllocationSite()) { // We should link new allocation sites, but we can't do this immediately // because |AllocationSite::HasWeakNext()| internally accesses // |Heap::roots_| that may not have been initialized yet. So defer this to @@ -231,93 +243,86 @@ HeapObject Deserializer::PostProcessNewObject(HeapObject obj, int space) { DCHECK(CanBeDeferred(obj)); } } - if (obj->IsScript()) { + if (obj.IsScript()) { LogScriptEvents(Script::cast(obj)); - } else if (obj->IsCode()) { + } else if (obj.IsCode()) { // We flush all code pages after deserializing the startup snapshot. // Hence we only remember each individual code object when deserializing // user code. if (deserializing_user_code() || space == LO_SPACE) { new_code_objects_.push_back(Code::cast(obj)); } - } else if (FLAG_trace_maps && obj->IsMap()) { + } else if (FLAG_trace_maps && obj.IsMap()) { // Keep track of all seen Maps to log them later since they might be only // partially initialized at this point. new_maps_.push_back(Map::cast(obj)); - } else if (obj->IsAccessorInfo()) { + } else if (obj.IsAccessorInfo()) { #ifdef USE_SIMULATOR accessor_infos_.push_back(AccessorInfo::cast(obj)); #endif - } else if (obj->IsCallHandlerInfo()) { + } else if (obj.IsCallHandlerInfo()) { #ifdef USE_SIMULATOR call_handler_infos_.push_back(CallHandlerInfo::cast(obj)); #endif - } else if (obj->IsExternalString()) { - if (obj->map() == ReadOnlyRoots(isolate_).native_source_string_map()) { + } else if (obj.IsExternalString()) { + if (obj.map() == ReadOnlyRoots(isolate_).native_source_string_map()) { ExternalOneByteString string = ExternalOneByteString::cast(obj); - DCHECK(string->is_uncached()); - string->SetResource( + DCHECK(string.is_uncached()); + string.SetResource( isolate_, NativesExternalStringResource::DecodeForDeserialization( - string->resource())); + string.resource())); } else { ExternalString string = ExternalString::cast(obj); - uint32_t index = string->resource_as_uint32(); + uint32_t index = string.resource_as_uint32(); Address address = static_cast<Address>(isolate_->api_external_references()[index]); - string->set_address_as_resource(address); + string.set_address_as_resource(address); isolate_->heap()->UpdateExternalString(string, 0, - string->ExternalPayloadSize()); + string.ExternalPayloadSize()); } isolate_->heap()->RegisterExternalString(String::cast(obj)); - } else if (obj->IsJSTypedArray()) { + } else if (obj.IsJSDataView()) { + JSDataView data_view = JSDataView::cast(obj); + JSArrayBuffer buffer = JSArrayBuffer::cast(data_view.buffer()); + data_view.set_data_pointer( + reinterpret_cast<uint8_t*>(buffer.backing_store()) + + data_view.byte_offset()); + } else if (obj.IsJSTypedArray()) { JSTypedArray typed_array = JSTypedArray::cast(obj); - CHECK_LE(typed_array->byte_offset(), Smi::kMaxValue); - int32_t byte_offset = static_cast<int32_t>(typed_array->byte_offset()); - if (byte_offset > 0) { - FixedTypedArrayBase elements = - FixedTypedArrayBase::cast(typed_array->elements()); - // Must be off-heap layout. - DCHECK(!typed_array->is_on_heap()); - - void* pointer_with_offset = reinterpret_cast<void*>( - reinterpret_cast<intptr_t>(elements->external_pointer()) + - byte_offset); - elements->set_external_pointer(pointer_with_offset); + // Only fixup for the off-heap case. + if (!typed_array.is_on_heap()) { + Smi store_index( + reinterpret_cast<Address>(typed_array.external_pointer())); + byte* backing_store = off_heap_backing_stores_[store_index.value()] + + typed_array.byte_offset(); + typed_array.set_external_pointer(backing_store); } - } else if (obj->IsJSArrayBuffer()) { + } else if (obj.IsJSArrayBuffer()) { JSArrayBuffer buffer = JSArrayBuffer::cast(obj); // Only fixup for the off-heap case. - if (buffer->backing_store() != nullptr) { - Smi store_index(reinterpret_cast<Address>(buffer->backing_store())); - void* backing_store = off_heap_backing_stores_[store_index->value()]; + if (buffer.backing_store() != nullptr) { + Smi store_index(reinterpret_cast<Address>(buffer.backing_store())); + void* backing_store = off_heap_backing_stores_[store_index.value()]; - buffer->set_backing_store(backing_store); + buffer.set_backing_store(backing_store); isolate_->heap()->RegisterNewArrayBuffer(buffer); } - } else if (obj->IsFixedTypedArrayBase()) { - FixedTypedArrayBase fta = FixedTypedArrayBase::cast(obj); - // Only fixup for the off-heap case. - if (fta->base_pointer() == Smi::kZero) { - Smi store_index(reinterpret_cast<Address>(fta->external_pointer())); - void* backing_store = off_heap_backing_stores_[store_index->value()]; - fta->set_external_pointer(backing_store); - } - } else if (obj->IsBytecodeArray()) { + } else if (obj.IsBytecodeArray()) { // TODO(mythria): Remove these once we store the default values for these // fields in the serializer. BytecodeArray bytecode_array = BytecodeArray::cast(obj); - bytecode_array->set_osr_loop_nesting_level(0); + bytecode_array.set_osr_loop_nesting_level(0); } #ifdef DEBUG - if (obj->IsDescriptorArray()) { + if (obj.IsDescriptorArray()) { DescriptorArray descriptor_array = DescriptorArray::cast(obj); - DCHECK_EQ(0, descriptor_array->raw_number_of_marked_descriptors()); + DCHECK_EQ(0, descriptor_array.raw_number_of_marked_descriptors()); } #endif // Check alignment. - DCHECK_EQ(0, Heap::GetFillToAlign(obj->address(), - HeapObject::RequiredAlignment(obj->map()))); + DCHECK_EQ(0, Heap::GetFillToAlign(obj.address(), + HeapObject::RequiredAlignment(obj.map()))); return obj; } @@ -356,12 +361,12 @@ HeapObject Deserializer::GetBackReferencedObject(int space) { } } - if (deserializing_user_code() && obj->IsThinString()) { - obj = ThinString::cast(obj)->actual(); + if (deserializing_user_code() && obj.IsThinString()) { + obj = ThinString::cast(obj).actual(); } hot_objects_.Add(obj); - DCHECK(!HasWeakHeapObjectTag(obj->ptr())); + DCHECK(!HasWeakHeapObjectTag(obj)); return obj; } @@ -393,7 +398,7 @@ HeapObject Deserializer::ReadObject(int space_number) { } #ifdef DEBUG - if (obj->IsCode()) { + if (obj.IsCode()) { DCHECK(space_number == CODE_SPACE || space_number == CODE_LO_SPACE); } else { DCHECK(space_number != CODE_SPACE && space_number != CODE_LO_SPACE); @@ -424,7 +429,7 @@ void Deserializer::ReadCodeObjectBody(int space_number, void Deserializer::VisitCodeTarget(Code host, RelocInfo* rinfo) { HeapObject object = ReadObject(); - rinfo->set_target_address(Code::cast(object)->raw_instruction_start()); + rinfo->set_target_address(Code::cast(object).raw_instruction_start()); } void Deserializer::VisitEmbeddedPointer(Code host, RelocInfo* rinfo) { @@ -460,8 +465,8 @@ void Deserializer::VisitInternalReference(Code host, RelocInfo* rinfo) { // Internal reference target is encoded as an offset from code entry. int target_offset = source_.GetInt(); DCHECK_LT(static_cast<unsigned>(target_offset), - static_cast<unsigned>(host->raw_instruction_size())); - Address target = host->entry() + target_offset; + static_cast<unsigned>(host.raw_instruction_size())); + Address target = host.entry() + target_offset; Assembler::deserialization_set_target_internal_reference_at( rinfo->pc(), target, rinfo->rmode()); } @@ -619,7 +624,7 @@ bool Deserializer::ReadData(TSlot current, TSlot limit, int source_space, HeapObject obj = HeapObject::FromAddress(current_object_address); // If the deferred object is a map, its instance type may be used // during deserialization. Initialize it with a temporary value. - if (obj->IsMap()) Map::cast(obj)->set_instance_type(FILLER_TYPE); + if (obj.IsMap()) Map::cast(obj).set_instance_type(FILLER_TYPE); current = limit; return false; } @@ -814,7 +819,7 @@ TSlot Deserializer::ReadDataCase(Isolate* isolate, TSlot current, } else if (bytecode == kReadOnlyObjectCache) { int cache_index = source_.GetInt(); heap_object = HeapObject::cast( - isolate->heap()->read_only_heap()->read_only_object_cache()->at( + isolate->heap()->read_only_heap()->cached_read_only_object( cache_index)); DCHECK(!Heap::InYoungGeneration(heap_object)); emit_write_barrier = false; diff --git a/deps/v8/src/snapshot/deserializer.h b/deps/v8/src/snapshot/deserializer.h index 86536ca81c..6e3f497d38 100644 --- a/deps/v8/src/snapshot/deserializer.h +++ b/deps/v8/src/snapshot/deserializer.h @@ -186,14 +186,16 @@ class V8_EXPORT_PRIVATE Deserializer : public SerializerDeserializer { }; // Used to insert a deserialized internalized string into the string table. -class StringTableInsertionKey : public StringTableKey { +class StringTableInsertionKey final : public StringTableKey { public: explicit StringTableInsertionKey(String string); - bool IsMatch(Object string) override; + bool IsMatch(String string) override; V8_WARN_UNUSED_RESULT Handle<String> AsHandle(Isolate* isolate) override; + String string() const { return string_; } + private: uint32_t ComputeHashField(String string); diff --git a/deps/v8/src/snapshot/embedded-file-writer.cc b/deps/v8/src/snapshot/embedded-file-writer.cc deleted file mode 100644 index 3ead35bd9a..0000000000 --- a/deps/v8/src/snapshot/embedded-file-writer.cc +++ /dev/null @@ -1,843 +0,0 @@ -// Copyright 2018 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. - -#include "src/snapshot/embedded-file-writer.h" - -#include <algorithm> -#include <cinttypes> - -#include "src/objects/code-inl.h" - -namespace v8 { -namespace internal { - -// V8_CC_MSVC is true for both MSVC and clang on windows. clang can handle -// __asm__-style inline assembly but MSVC cannot, and thus we need a more -// precise compiler detection that can distinguish between the two. clang on -// windows sets both __clang__ and _MSC_VER, MSVC sets only _MSC_VER. -#if defined(_MSC_VER) && !defined(__clang__) -#define V8_COMPILER_IS_MSVC -#endif - -// MSVC uses MASM for x86 and x64, while it has a ARMASM for ARM32 and -// ARMASM64 for ARM64. Since ARMASM and ARMASM64 accept a slightly tweaked -// version of ARM assembly language, they are referred to together in Visual -// Studio project files as MARMASM. -// -// ARM assembly language docs: -// http://infocenter.arm.com/help/topic/com.arm.doc.dui0802b/index.html -// Microsoft ARM assembler and assembly language docs: -// https://docs.microsoft.com/en-us/cpp/assembler/arm/arm-assembler-reference -#if defined(V8_COMPILER_IS_MSVC) -#if defined(V8_TARGET_ARCH_ARM64) || defined(V8_TARGET_ARCH_ARM) -#define V8_ASSEMBLER_IS_MARMASM -#elif defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64) -#define V8_ASSEMBLER_IS_MASM -#else -#error Unknown Windows assembler target architecture. -#endif -#endif - -// Name mangling. -// Symbols are prefixed with an underscore on 32-bit architectures. -#if defined(V8_TARGET_OS_WIN) && !defined(V8_TARGET_ARCH_X64) && \ - !defined(V8_TARGET_ARCH_ARM64) -#define SYMBOL_PREFIX "_" -#else -#define SYMBOL_PREFIX "" -#endif - -// Platform-independent bits. -// ----------------------------------------------------------------------------- - -namespace { - -DataDirective PointerSizeDirective() { - if (kSystemPointerSize == 8) { - return kQuad; - } else { - CHECK_EQ(4, kSystemPointerSize); - return kLong; - } -} - -} // namespace - -const char* DirectiveAsString(DataDirective directive) { -#if defined(V8_TARGET_OS_WIN) && defined(V8_ASSEMBLER_IS_MASM) - switch (directive) { - case kByte: - return "BYTE"; - case kLong: - return "DWORD"; - case kQuad: - return "QWORD"; - default: - UNREACHABLE(); - } -#elif defined(V8_TARGET_OS_WIN) && defined(V8_ASSEMBLER_IS_MARMASM) - switch (directive) { - case kByte: - return "DCB"; - case kLong: - return "DCDU"; - case kQuad: - return "DCQU"; - default: - UNREACHABLE(); - } -#elif defined(V8_OS_AIX) - switch (directive) { - case kByte: - return ".byte"; - case kLong: - return ".long"; - case kQuad: - return ".llong"; - default: - UNREACHABLE(); - } -#else - switch (directive) { - case kByte: - return ".byte"; - case kLong: - return ".long"; - case kQuad: - return ".quad"; - case kOcta: - return ".octa"; - } - UNREACHABLE(); -#endif -} - -void EmbeddedFileWriter::PrepareBuiltinSourcePositionMap(Builtins* builtins) { - for (int i = 0; i < Builtins::builtin_count; i++) { - // Retrieve the SourcePositionTable and copy it. - Code code = builtins->builtin(i); - // Verify that the code object is still the "real code" and not a - // trampoline (which wouldn't have source positions). - DCHECK(!code->is_off_heap_trampoline()); - std::vector<unsigned char> data( - code->SourcePositionTable()->GetDataStartAddress(), - code->SourcePositionTable()->GetDataEndAddress()); - source_positions_[i] = data; - } -} - -#if defined(V8_OS_WIN_X64) -std::string EmbeddedFileWriter::BuiltinsUnwindInfoLabel() const { - char embedded_blob_data_symbol[kTemporaryStringLength]; - i::SNPrintF(i::Vector<char>(embedded_blob_data_symbol), - "%s_Builtins_UnwindInfo", embedded_variant_); - return embedded_blob_data_symbol; -} - -void EmbeddedFileWriter::SetBuiltinUnwindData( - int builtin_index, const win64_unwindinfo::BuiltinUnwindInfo& unwind_info) { - DCHECK_LT(builtin_index, Builtins::builtin_count); - unwind_infos_[builtin_index] = unwind_info; -} - -void EmbeddedFileWriter::WriteUnwindInfoEntry( - PlatformDependentEmbeddedFileWriter* w, uint64_t rva_start, - uint64_t rva_end) const { - w->DeclareRvaToSymbol(EmbeddedBlobDataSymbol().c_str(), rva_start); - w->DeclareRvaToSymbol(EmbeddedBlobDataSymbol().c_str(), rva_end); - w->DeclareRvaToSymbol(BuiltinsUnwindInfoLabel().c_str()); -} - -void EmbeddedFileWriter::WriteUnwindInfo(PlatformDependentEmbeddedFileWriter* w, - const i::EmbeddedData* blob) const { - // Emit an UNWIND_INFO (XDATA) struct, which contains the unwinding - // information that is used for all builtin functions. - DCHECK(win64_unwindinfo::CanEmitUnwindInfoForBuiltins()); - w->Comment("xdata for all the code in the embedded blob."); - w->DeclareExternalFunction(CRASH_HANDLER_FUNCTION_NAME_STRING); - - w->StartXdataSection(); - { - w->DeclareLabel(BuiltinsUnwindInfoLabel().c_str()); - std::vector<uint8_t> xdata = - win64_unwindinfo::GetUnwindInfoForBuiltinFunctions(); - WriteBinaryContentsAsInlineAssembly(w, xdata.data(), - static_cast<uint32_t>(xdata.size())); - w->Comment(" ExceptionHandler"); - w->DeclareRvaToSymbol(CRASH_HANDLER_FUNCTION_NAME_STRING); - } - w->EndXdataSection(); - w->Newline(); - - // Emit a RUNTIME_FUNCTION (PDATA) entry for each builtin function, as - // documented here: - // https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64. - w->Comment( - "pdata for all the code in the embedded blob (structs of type " - "RUNTIME_FUNCTION)."); - w->Comment(" BeginAddress"); - w->Comment(" EndAddress"); - w->Comment(" UnwindInfoAddress"); - w->StartPdataSection(); - { - Address prev_builtin_end_offset = 0; - for (int i = 0; i < Builtins::builtin_count; i++) { - // Some builtins are leaf functions from the point of view of Win64 stack - // walking: they do not move the stack pointer and do not require a PDATA - // entry because the return address can be retrieved from [rsp]. - if (!blob->ContainsBuiltin(i)) continue; - if (unwind_infos_[i].is_leaf_function()) continue; - - uint64_t builtin_start_offset = blob->InstructionStartOfBuiltin(i) - - reinterpret_cast<Address>(blob->data()); - uint32_t builtin_size = blob->InstructionSizeOfBuiltin(i); - - const std::vector<int>& xdata_desc = unwind_infos_[i].fp_offsets(); - if (xdata_desc.empty()) { - // Some builtins do not have any "push rbp - mov rbp, rsp" instructions - // to start a stack frame. We still emit a PDATA entry as if they had, - // relying on the fact that we can find the previous frame address from - // rbp in most cases. Note that since the function does not really start - // with a 'push rbp' we need to specify the start RVA in the PDATA entry - // a few bytes before the beginning of the function, if it does not - // overlap the end of the previous builtin. - WriteUnwindInfoEntry( - w, - std::max(prev_builtin_end_offset, - builtin_start_offset - win64_unwindinfo::kRbpPrefixLength), - builtin_start_offset + builtin_size); - } else { - // Some builtins have one or more "push rbp - mov rbp, rsp" sequences, - // but not necessarily at the beginning of the function. In this case - // we want to yield a PDATA entry for each block of instructions that - // emit an rbp frame. If the function does not start with 'push rbp' - // we also emit a PDATA entry for the initial block of code up to the - // first 'push rbp', like in the case above. - if (xdata_desc[0] > 0) { - WriteUnwindInfoEntry(w, - std::max(prev_builtin_end_offset, - builtin_start_offset - - win64_unwindinfo::kRbpPrefixLength), - builtin_start_offset + xdata_desc[0]); - } - - for (size_t j = 0; j < xdata_desc.size(); j++) { - int chunk_start = xdata_desc[j]; - int chunk_end = - (j < xdata_desc.size() - 1) ? xdata_desc[j + 1] : builtin_size; - WriteUnwindInfoEntry(w, builtin_start_offset + chunk_start, - builtin_start_offset + chunk_end); - } - } - - prev_builtin_end_offset = builtin_start_offset + builtin_size; - w->Newline(); - } - } - w->EndPdataSection(); - w->Newline(); -} -#endif - -// V8_OS_MACOSX -// Fuchsia target is explicitly excluded here for Mac hosts. This is to avoid -// generating uncompilable assembly files for the Fuchsia target. -// ----------------------------------------------------------------------------- - -#if defined(V8_OS_MACOSX) && !defined(V8_TARGET_OS_FUCHSIA) - -void PlatformDependentEmbeddedFileWriter::SectionText() { - fprintf(fp_, ".text\n"); -} - -void PlatformDependentEmbeddedFileWriter::SectionData() { - fprintf(fp_, ".data\n"); -} - -void PlatformDependentEmbeddedFileWriter::SectionRoData() { - fprintf(fp_, ".const_data\n"); -} - -void PlatformDependentEmbeddedFileWriter::DeclareUint32(const char* name, - uint32_t value) { - DeclareSymbolGlobal(name); - DeclareLabel(name); - IndentedDataDirective(kLong); - fprintf(fp_, "%d", value); - Newline(); -} - -void PlatformDependentEmbeddedFileWriter::DeclarePointerToSymbol( - const char* name, const char* target) { - DeclareSymbolGlobal(name); - DeclareLabel(name); - fprintf(fp_, " %s _%s\n", DirectiveAsString(PointerSizeDirective()), target); -} - -void PlatformDependentEmbeddedFileWriter::DeclareSymbolGlobal( - const char* name) { - // TODO(jgruber): Investigate switching to .globl. Using .private_extern - // prevents something along the compilation chain from messing with the - // embedded blob. Using .global here causes embedded blob hash verification - // failures at runtime. - fprintf(fp_, ".private_extern _%s\n", name); -} - -void PlatformDependentEmbeddedFileWriter::AlignToCodeAlignment() { - fprintf(fp_, ".balign 32\n"); -} - -void PlatformDependentEmbeddedFileWriter::AlignToDataAlignment() { - fprintf(fp_, ".balign 8\n"); -} - -void PlatformDependentEmbeddedFileWriter::Comment(const char* string) { - fprintf(fp_, "// %s\n", string); -} - -void PlatformDependentEmbeddedFileWriter::DeclareLabel(const char* name) { - fprintf(fp_, "_%s:\n", name); -} - -void PlatformDependentEmbeddedFileWriter::SourceInfo(int fileid, - const char* filename, - int line) { - fprintf(fp_, ".loc %d %d\n", fileid, line); -} - -void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin( - const char* name) { - DeclareLabel(name); - - // TODO(mvstanton): Investigate the proper incantations to mark the label as - // a function on OSX. -} - -void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) { -} - -int PlatformDependentEmbeddedFileWriter::HexLiteral(uint64_t value) { - return fprintf(fp_, "0x%" PRIx64, value); -} - -void PlatformDependentEmbeddedFileWriter::FilePrologue() {} - -void PlatformDependentEmbeddedFileWriter::DeclareExternalFilename( - int fileid, const char* filename) { - fprintf(fp_, ".file %d \"%s\"\n", fileid, filename); -} - -void PlatformDependentEmbeddedFileWriter::FileEpilogue() {} - -int PlatformDependentEmbeddedFileWriter::IndentedDataDirective( - DataDirective directive) { - return fprintf(fp_, " %s ", DirectiveAsString(directive)); -} - -// V8_OS_AIX -// ----------------------------------------------------------------------------- - -#elif defined(V8_OS_AIX) - -void PlatformDependentEmbeddedFileWriter::SectionText() { - fprintf(fp_, ".csect .text[PR]\n"); -} - -void PlatformDependentEmbeddedFileWriter::SectionData() { - fprintf(fp_, ".csect .data[RW]\n"); -} - -void PlatformDependentEmbeddedFileWriter::SectionRoData() { - fprintf(fp_, ".csect[RO]\n"); -} - -void PlatformDependentEmbeddedFileWriter::DeclareUint32(const char* name, - uint32_t value) { - DeclareSymbolGlobal(name); - fprintf(fp_, ".align 2\n"); - fprintf(fp_, "%s:\n", name); - IndentedDataDirective(kLong); - fprintf(fp_, "%d\n", value); - Newline(); -} - -void PlatformDependentEmbeddedFileWriter::DeclarePointerToSymbol( - const char* name, const char* target) { - AlignToCodeAlignment(); - DeclareLabel(name); - fprintf(fp_, " %s %s\n", DirectiveAsString(PointerSizeDirective()), target); - Newline(); -} - -void PlatformDependentEmbeddedFileWriter::DeclareSymbolGlobal( - const char* name) { - fprintf(fp_, ".globl %s\n", name); -} - -void PlatformDependentEmbeddedFileWriter::AlignToCodeAlignment() { - fprintf(fp_, ".align 5\n"); -} - -void PlatformDependentEmbeddedFileWriter::AlignToDataAlignment() { - fprintf(fp_, ".align 3\n"); -} - -void PlatformDependentEmbeddedFileWriter::Comment(const char* string) { - fprintf(fp_, "// %s\n", string); -} - -void PlatformDependentEmbeddedFileWriter::DeclareLabel(const char* name) { - DeclareSymbolGlobal(name); - fprintf(fp_, "%s:\n", name); -} - -void PlatformDependentEmbeddedFileWriter::SourceInfo(int fileid, - const char* filename, - int line) { - fprintf(fp_, ".xline %d, \"%s\"\n", line, filename); -} - -void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin( - const char* name) { - Newline(); - DeclareSymbolGlobal(name); - fprintf(fp_, ".csect %s[DS]\n", name); // function descriptor - fprintf(fp_, "%s:\n", name); - fprintf(fp_, ".llong .%s, 0, 0\n", name); - SectionText(); - fprintf(fp_, ".%s:\n", name); -} - -void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) { -} - -int PlatformDependentEmbeddedFileWriter::HexLiteral(uint64_t value) { - return fprintf(fp_, "0x%" PRIx64, value); -} - -void PlatformDependentEmbeddedFileWriter::FilePrologue() {} - -void PlatformDependentEmbeddedFileWriter::DeclareExternalFilename( - int fileid, const char* filename) { - // File name cannot be declared with an identifier on AIX. - // We use the SourceInfo method to emit debug info in - //.xline <line-number> <file-name> format. -} - -void PlatformDependentEmbeddedFileWriter::FileEpilogue() {} - -int PlatformDependentEmbeddedFileWriter::IndentedDataDirective( - DataDirective directive) { - return fprintf(fp_, " %s ", DirectiveAsString(directive)); -} - -// V8_TARGET_OS_WIN (MSVC) -// ----------------------------------------------------------------------------- - -#elif defined(V8_TARGET_OS_WIN) && defined(V8_ASSEMBLER_IS_MASM) - -// For MSVC builds we emit assembly in MASM syntax. -// See https://docs.microsoft.com/en-us/cpp/assembler/masm/directives-reference. - -void PlatformDependentEmbeddedFileWriter::SectionText() { - fprintf(fp_, ".CODE\n"); -} - -void PlatformDependentEmbeddedFileWriter::SectionData() { - fprintf(fp_, ".DATA\n"); -} - -void PlatformDependentEmbeddedFileWriter::SectionRoData() { - fprintf(fp_, ".CONST\n"); -} - -void PlatformDependentEmbeddedFileWriter::DeclareUint32(const char* name, - uint32_t value) { - DeclareSymbolGlobal(name); - fprintf(fp_, "%s%s %s %d\n", SYMBOL_PREFIX, name, DirectiveAsString(kLong), - value); -} - -void PlatformDependentEmbeddedFileWriter::DeclarePointerToSymbol( - const char* name, const char* target) { - DeclareSymbolGlobal(name); - fprintf(fp_, "%s%s %s %s%s\n", SYMBOL_PREFIX, name, - DirectiveAsString(PointerSizeDirective()), SYMBOL_PREFIX, target); -} - -#if defined(V8_OS_WIN_X64) - -void PlatformDependentEmbeddedFileWriter::StartPdataSection() { - fprintf(fp_, "OPTION DOTNAME\n"); - fprintf(fp_, ".pdata SEGMENT DWORD READ ''\n"); -} - -void PlatformDependentEmbeddedFileWriter::EndPdataSection() { - fprintf(fp_, ".pdata ENDS\n"); -} - -void PlatformDependentEmbeddedFileWriter::StartXdataSection() { - fprintf(fp_, "OPTION DOTNAME\n"); - fprintf(fp_, ".xdata SEGMENT DWORD READ ''\n"); -} - -void PlatformDependentEmbeddedFileWriter::EndXdataSection() { - fprintf(fp_, ".xdata ENDS\n"); -} - -void PlatformDependentEmbeddedFileWriter::DeclareExternalFunction( - const char* name) { - fprintf(fp_, "EXTERN %s : PROC\n", name); -} - -void PlatformDependentEmbeddedFileWriter::DeclareRvaToSymbol(const char* name, - uint64_t offset) { - if (offset > 0) { - fprintf(fp_, "DD IMAGEREL %s+%llu\n", name, offset); - } else { - fprintf(fp_, "DD IMAGEREL %s\n", name); - } -} - -#endif // defined(V8_OS_WIN_X64) - -void PlatformDependentEmbeddedFileWriter::DeclareSymbolGlobal( - const char* name) { - fprintf(fp_, "PUBLIC %s%s\n", SYMBOL_PREFIX, name); -} - -void PlatformDependentEmbeddedFileWriter::AlignToCodeAlignment() { - // Diverges from other platforms due to compile error - // 'invalid combination with segment alignment'. - fprintf(fp_, "ALIGN 4\n"); -} - -void PlatformDependentEmbeddedFileWriter::AlignToDataAlignment() { - fprintf(fp_, "ALIGN 4\n"); -} - -void PlatformDependentEmbeddedFileWriter::Comment(const char* string) { - fprintf(fp_, "; %s\n", string); -} - -void PlatformDependentEmbeddedFileWriter::DeclareLabel(const char* name) { - fprintf(fp_, "%s%s LABEL %s\n", SYMBOL_PREFIX, name, - DirectiveAsString(kByte)); -} - -void PlatformDependentEmbeddedFileWriter::SourceInfo(int fileid, - const char* filename, - int line) { - // TODO(mvstanton): output source information for MSVC. - // Its syntax is #line <line> "<filename>" -} - -void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin( - const char* name) { - fprintf(fp_, "%s%s PROC\n", SYMBOL_PREFIX, name); -} - -void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) { - fprintf(fp_, "%s%s ENDP\n", SYMBOL_PREFIX, name); -} - -int PlatformDependentEmbeddedFileWriter::HexLiteral(uint64_t value) { - return fprintf(fp_, "0%" PRIx64 "h", value); -} - -void PlatformDependentEmbeddedFileWriter::FilePrologue() { -#if !defined(V8_TARGET_ARCH_X64) - fprintf(fp_, ".MODEL FLAT\n"); -#endif -} - -void PlatformDependentEmbeddedFileWriter::DeclareExternalFilename( - int fileid, const char* filename) {} - -void PlatformDependentEmbeddedFileWriter::FileEpilogue() { - fprintf(fp_, "END\n"); -} - -int PlatformDependentEmbeddedFileWriter::IndentedDataDirective( - DataDirective directive) { - return fprintf(fp_, " %s ", DirectiveAsString(directive)); -} - -#undef V8_ASSEMBLER_IS_MASM - -#elif defined(V8_TARGET_OS_WIN) && defined(V8_ASSEMBLER_IS_MARMASM) - -// The the AARCH64 ABI requires instructions be 4-byte-aligned and Windows does -// not have a stricter alignment requirement (see the TEXTAREA macro of -// kxarm64.h in the Windows SDK), so code is 4-byte-aligned. -// The data fields in the emitted assembly tend to be accessed with 8-byte -// LDR instructions, so data is 8-byte-aligned. -// -// armasm64's warning A4228 states -// Alignment value exceeds AREA alignment; alignment not guaranteed -// To ensure that ALIGN directives are honored, their values are defined as -// equal to their corresponding AREA's ALIGN attributes. - -#define ARM64_DATA_ALIGNMENT_POWER (3) -#define ARM64_DATA_ALIGNMENT (1 << ARM64_DATA_ALIGNMENT_POWER) -#define ARM64_CODE_ALIGNMENT_POWER (2) -#define ARM64_CODE_ALIGNMENT (1 << ARM64_CODE_ALIGNMENT_POWER) - -void PlatformDependentEmbeddedFileWriter::SectionText() { - fprintf(fp_, " AREA |.text|, CODE, ALIGN=%d, READONLY\n", - ARM64_CODE_ALIGNMENT_POWER); -} - -void PlatformDependentEmbeddedFileWriter::SectionData() { - fprintf(fp_, " AREA |.data|, DATA, ALIGN=%d, READWRITE\n", - ARM64_DATA_ALIGNMENT_POWER); -} - -void PlatformDependentEmbeddedFileWriter::SectionRoData() { - fprintf(fp_, " AREA |.rodata|, DATA, ALIGN=%d, READONLY\n", - ARM64_DATA_ALIGNMENT_POWER); -} - -void PlatformDependentEmbeddedFileWriter::DeclareUint32(const char* name, - uint32_t value) { - DeclareSymbolGlobal(name); - fprintf(fp_, "%s%s %s %d\n", SYMBOL_PREFIX, name, DirectiveAsString(kLong), - value); -} - -void PlatformDependentEmbeddedFileWriter::DeclarePointerToSymbol( - const char* name, const char* target) { - DeclareSymbolGlobal(name); - fprintf(fp_, "%s%s %s %s%s\n", SYMBOL_PREFIX, name, - DirectiveAsString(PointerSizeDirective()), SYMBOL_PREFIX, target); -} - -void PlatformDependentEmbeddedFileWriter::DeclareSymbolGlobal( - const char* name) { - fprintf(fp_, " EXPORT %s%s\n", SYMBOL_PREFIX, name); -} - -void PlatformDependentEmbeddedFileWriter::AlignToCodeAlignment() { - fprintf(fp_, " ALIGN %d\n", ARM64_CODE_ALIGNMENT); -} - -void PlatformDependentEmbeddedFileWriter::AlignToDataAlignment() { - fprintf(fp_, " ALIGN %d\n", ARM64_DATA_ALIGNMENT); -} - -void PlatformDependentEmbeddedFileWriter::Comment(const char* string) { - fprintf(fp_, "; %s\n", string); -} - -void PlatformDependentEmbeddedFileWriter::DeclareLabel(const char* name) { - fprintf(fp_, "%s%s\n", SYMBOL_PREFIX, name); -} - -void PlatformDependentEmbeddedFileWriter::SourceInfo(int fileid, - const char* filename, - int line) { - // TODO(mvstanton): output source information for MSVC. - // Its syntax is #line <line> "<filename>" -} - -void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin( - const char* name) { - fprintf(fp_, "%s%s FUNCTION\n", SYMBOL_PREFIX, name); -} - -void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) { - fprintf(fp_, " ENDFUNC\n"); -} - -int PlatformDependentEmbeddedFileWriter::HexLiteral(uint64_t value) { - return fprintf(fp_, "0x%" PRIx64, value); -} - -void PlatformDependentEmbeddedFileWriter::FilePrologue() {} - -void PlatformDependentEmbeddedFileWriter::DeclareExternalFilename( - int fileid, const char* filename) {} - -void PlatformDependentEmbeddedFileWriter::FileEpilogue() { - fprintf(fp_, " END\n"); -} - -int PlatformDependentEmbeddedFileWriter::IndentedDataDirective( - DataDirective directive) { - return fprintf(fp_, " %s ", DirectiveAsString(directive)); -} - -#undef V8_ASSEMBLER_IS_MARMASM -#undef ARM64_DATA_ALIGNMENT_POWER -#undef ARM64_DATA_ALIGNMENT -#undef ARM64_CODE_ALIGNMENT_POWER -#undef ARM64_CODE_ALIGNMENT - -// Everything but AIX, Windows with MSVC, or OSX. -// ----------------------------------------------------------------------------- - -#else - -void PlatformDependentEmbeddedFileWriter::SectionText() { -#ifdef OS_CHROMEOS - fprintf(fp_, ".section .text.hot.embedded\n"); -#else - fprintf(fp_, ".section .text\n"); -#endif -} - -void PlatformDependentEmbeddedFileWriter::SectionData() { - fprintf(fp_, ".section .data\n"); -} - -void PlatformDependentEmbeddedFileWriter::SectionRoData() { - if (i::FLAG_target_os == std::string("win")) - fprintf(fp_, ".section .rdata\n"); - else - fprintf(fp_, ".section .rodata\n"); -} - -void PlatformDependentEmbeddedFileWriter::DeclareUint32(const char* name, - uint32_t value) { - DeclareSymbolGlobal(name); - DeclareLabel(name); - IndentedDataDirective(kLong); - fprintf(fp_, "%d", value); - Newline(); -} - -void PlatformDependentEmbeddedFileWriter::DeclarePointerToSymbol( - const char* name, const char* target) { - DeclareSymbolGlobal(name); - DeclareLabel(name); - fprintf(fp_, " %s %s%s\n", DirectiveAsString(PointerSizeDirective()), - SYMBOL_PREFIX, target); -} - -#if defined(V8_OS_WIN_X64) - -void PlatformDependentEmbeddedFileWriter::StartPdataSection() { - fprintf(fp_, ".section .pdata\n"); -} - -void PlatformDependentEmbeddedFileWriter::EndPdataSection() {} - -void PlatformDependentEmbeddedFileWriter::StartXdataSection() { - fprintf(fp_, ".section .xdata\n"); -} - -void PlatformDependentEmbeddedFileWriter::EndXdataSection() {} - -void PlatformDependentEmbeddedFileWriter::DeclareExternalFunction( - const char* name) {} - -void PlatformDependentEmbeddedFileWriter::DeclareRvaToSymbol(const char* name, - uint64_t offset) { - if (offset > 0) { - fprintf(fp_, ".rva %s + %llu\n", name, offset); - } else { - fprintf(fp_, ".rva %s\n", name); - } -} - -#endif // defined(V8_OS_WIN_X64) - -void PlatformDependentEmbeddedFileWriter::DeclareSymbolGlobal( - const char* name) { - fprintf(fp_, ".global %s%s\n", SYMBOL_PREFIX, name); -} - -void PlatformDependentEmbeddedFileWriter::AlignToCodeAlignment() { - fprintf(fp_, ".balign 32\n"); -} - -void PlatformDependentEmbeddedFileWriter::AlignToDataAlignment() { - // On Windows ARM64, s390, PPC and possibly more platforms, aligned load - // instructions are used to retrieve v8_Default_embedded_blob_ and/or - // v8_Default_embedded_blob_size_. The generated instructions require the - // load target to be aligned at 8 bytes (2^3). - fprintf(fp_, ".balign 8\n"); -} - -void PlatformDependentEmbeddedFileWriter::Comment(const char* string) { - fprintf(fp_, "// %s\n", string); -} - -void PlatformDependentEmbeddedFileWriter::DeclareLabel(const char* name) { - fprintf(fp_, "%s%s:\n", SYMBOL_PREFIX, name); -} - -void PlatformDependentEmbeddedFileWriter::SourceInfo(int fileid, - const char* filename, - int line) { - fprintf(fp_, ".loc %d %d\n", fileid, line); -} - -void PlatformDependentEmbeddedFileWriter::DeclareFunctionBegin( - const char* name) { - DeclareLabel(name); - - if (i::FLAG_target_os == std::string("win")) { -#if defined(V8_TARGET_ARCH_ARM64) - // Windows ARM64 assembly is in GAS syntax, but ".type" is invalid directive - // in PE/COFF for Windows. -#else - // The directives for inserting debugging information on Windows come - // from the PE (Portable Executable) and COFF (Common Object File Format) - // standards. Documented here: - // https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format - // - // .scl 2 means StorageClass external. - // .type 32 means Type Representation Function. - fprintf(fp_, ".def %s%s; .scl 2; .type 32; .endef;\n", SYMBOL_PREFIX, name); -#endif - } else { -#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_ARM64) - // ELF format binaries on ARM use ".type <function name>, %function" - // to create a DWARF subprogram entry. - fprintf(fp_, ".type %s, %%function\n", name); -#else - // Other ELF Format binaries use ".type <function name>, @function" - // to create a DWARF subprogram entry. - fprintf(fp_, ".type %s, @function\n", name); -#endif - } -} - -void PlatformDependentEmbeddedFileWriter::DeclareFunctionEnd(const char* name) { -} - -int PlatformDependentEmbeddedFileWriter::HexLiteral(uint64_t value) { - return fprintf(fp_, "0x%" PRIx64, value); -} - -void PlatformDependentEmbeddedFileWriter::FilePrologue() {} - -void PlatformDependentEmbeddedFileWriter::DeclareExternalFilename( - int fileid, const char* filename) { - // Replace any Windows style paths (backslashes) with forward - // slashes. - std::string fixed_filename(filename); - for (auto& c : fixed_filename) { - if (c == '\\') { - c = '/'; - } - } - fprintf(fp_, ".file %d \"%s\"\n", fileid, fixed_filename.c_str()); -} - -void PlatformDependentEmbeddedFileWriter::FileEpilogue() {} - -int PlatformDependentEmbeddedFileWriter::IndentedDataDirective( - DataDirective directive) { - return fprintf(fp_, " %s ", DirectiveAsString(directive)); -} - -#endif - -#undef SYMBOL_PREFIX -#undef V8_COMPILER_IS_MSVC - -} // namespace internal -} // namespace v8 diff --git a/deps/v8/src/snapshot/embedded-file-writer.h b/deps/v8/src/snapshot/embedded-file-writer.h deleted file mode 100644 index 0f4978cfd8..0000000000 --- a/deps/v8/src/snapshot/embedded-file-writer.h +++ /dev/null @@ -1,483 +0,0 @@ -// Copyright 2018 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. - -#ifndef V8_SNAPSHOT_EMBEDDED_FILE_WRITER_H_ -#define V8_SNAPSHOT_EMBEDDED_FILE_WRITER_H_ - -#include <cstdio> -#include <cstring> - -#include "src/globals.h" -#include "src/snapshot/snapshot.h" -#include "src/source-position-table.h" - -#if defined(V8_OS_WIN_X64) -#include "src/unwinding-info-win64.h" -#endif - -namespace v8 { -namespace internal { - -enum DataDirective { - kByte, - kLong, - kQuad, - kOcta, -}; - -static constexpr char kDefaultEmbeddedVariant[] = "Default"; - -// The platform-dependent logic for emitting assembly code for the generated -// embedded.S file. -class EmbeddedFileWriter; -class PlatformDependentEmbeddedFileWriter final { - public: - void SetFile(FILE* fp) { fp_ = fp; } - - void SectionText(); - void SectionData(); - void SectionRoData(); - - void AlignToCodeAlignment(); - void AlignToDataAlignment(); - - void DeclareUint32(const char* name, uint32_t value); - void DeclarePointerToSymbol(const char* name, const char* target); - -#if defined(V8_OS_WIN_X64) - void StartPdataSection(); - void EndPdataSection(); - void StartXdataSection(); - void EndXdataSection(); - void DeclareExternalFunction(const char* name); - - // Emits an RVA (address relative to the module load address) specified as an - // offset from a given symbol. - void DeclareRvaToSymbol(const char* name, uint64_t offset = 0); -#endif - - void DeclareLabel(const char* name); - - void SourceInfo(int fileid, const char* filename, int line); - void DeclareFunctionBegin(const char* name); - void DeclareFunctionEnd(const char* name); - - // Returns the number of printed characters. - int HexLiteral(uint64_t value); - - void Comment(const char* string); - void Newline() { fprintf(fp_, "\n"); } - - void FilePrologue(); - void DeclareExternalFilename(int fileid, const char* filename); - void FileEpilogue(); - - int IndentedDataDirective(DataDirective directive); - - FILE* fp() const { return fp_; } - - private: - void DeclareSymbolGlobal(const char* name); - - private: - FILE* fp_ = nullptr; -}; - -// When writing out compiled builtins to a file, we -// Detailed source-code information about builtins can only be obtained by -// registration on the isolate during compilation. -class EmbeddedFileWriterInterface { - public: - // We maintain a database of filenames to synthetic IDs. - virtual int LookupOrAddExternallyCompiledFilename(const char* filename) = 0; - virtual const char* GetExternallyCompiledFilename(int index) const = 0; - virtual int GetExternallyCompiledFilenameCount() const = 0; - - // The isolate will call the method below just prior to replacing the - // compiled builtin Code objects with trampolines. - virtual void PrepareBuiltinSourcePositionMap(Builtins* builtins) = 0; - -#if defined(V8_OS_WIN_X64) - virtual void SetBuiltinUnwindData( - int builtin_index, - const win64_unwindinfo::BuiltinUnwindInfo& unwinding_info) = 0; -#endif -}; - -// Generates the embedded.S file which is later compiled into the final v8 -// binary. Its contents are exported through two symbols: -// -// v8_<variant>_embedded_blob_ (intptr_t): -// a pointer to the start of the embedded blob. -// v8_<variant>_embedded_blob_size_ (uint32_t): -// size of the embedded blob in bytes. -// -// The variant is usually "Default" but can be modified in multisnapshot builds. -class EmbeddedFileWriter : public EmbeddedFileWriterInterface { - public: - int LookupOrAddExternallyCompiledFilename(const char* filename) override { - auto result = external_filenames_.find(filename); - if (result != external_filenames_.end()) { - return result->second; - } - int new_id = - ExternalFilenameIndexToId(static_cast<int>(external_filenames_.size())); - external_filenames_.insert(std::make_pair(filename, new_id)); - external_filenames_by_index_.push_back(filename); - DCHECK_EQ(external_filenames_by_index_.size(), external_filenames_.size()); - return new_id; - } - - const char* GetExternallyCompiledFilename(int fileid) const override { - size_t index = static_cast<size_t>(ExternalFilenameIdToIndex(fileid)); - DCHECK_GE(index, 0); - DCHECK_LT(index, external_filenames_by_index_.size()); - - return external_filenames_by_index_[index]; - } - - int GetExternallyCompiledFilenameCount() const override { - return static_cast<int>(external_filenames_.size()); - } - - void PrepareBuiltinSourcePositionMap(Builtins* builtins) override; - -#if defined(V8_OS_WIN_X64) - void SetBuiltinUnwindData( - int builtin_index, - const win64_unwindinfo::BuiltinUnwindInfo& unwinding_info) override; -#endif - - void SetEmbeddedFile(const char* embedded_src_path) { - embedded_src_path_ = embedded_src_path; - } - - void SetEmbeddedVariant(const char* embedded_variant) { - embedded_variant_ = embedded_variant; - } - - void WriteEmbedded(const i::EmbeddedData* blob) const { - MaybeWriteEmbeddedFile(blob); - } - - private: - void MaybeWriteEmbeddedFile(const i::EmbeddedData* blob) const { - if (embedded_src_path_ == nullptr) return; - - FILE* fp = GetFileDescriptorOrDie(embedded_src_path_); - - PlatformDependentEmbeddedFileWriter writer; - writer.SetFile(fp); - - WriteFilePrologue(&writer); - WriteExternalFilenames(&writer); - WriteMetadataSection(&writer, blob); - WriteInstructionStreams(&writer, blob); - WriteFileEpilogue(&writer, blob); - - fclose(fp); - } - - static FILE* GetFileDescriptorOrDie(const char* filename) { - FILE* fp = v8::base::OS::FOpen(filename, "wb"); - if (fp == nullptr) { - i::PrintF("Unable to open file \"%s\" for writing.\n", filename); - exit(1); - } - return fp; - } - - void WriteFilePrologue(PlatformDependentEmbeddedFileWriter* w) const { - w->Comment("Autogenerated file. Do not edit."); - w->Newline(); - w->FilePrologue(); - } - - void WriteExternalFilenames(PlatformDependentEmbeddedFileWriter* w) const { - w->Comment( - "Source positions in the embedded blob refer to filenames by id."); - w->Comment("Assembly directives here map the id to a filename."); - w->Newline(); - - // Write external filenames. - int size = static_cast<int>(external_filenames_by_index_.size()); - for (int i = 0; i < size; i++) { - w->DeclareExternalFilename(ExternalFilenameIndexToId(i), - external_filenames_by_index_[i]); - } - } - - // Fairly arbitrary but should fit all symbol names. - static constexpr int kTemporaryStringLength = 256; - - std::string EmbeddedBlobDataSymbol() const { - char embedded_blob_data_symbol[kTemporaryStringLength]; - i::SNPrintF(i::Vector<char>(embedded_blob_data_symbol), - "v8_%s_embedded_blob_data_", embedded_variant_); - return embedded_blob_data_symbol; - } - - void WriteMetadataSection(PlatformDependentEmbeddedFileWriter* w, - const i::EmbeddedData* blob) const { - w->Comment("The embedded blob starts here. Metadata comes first, followed"); - w->Comment("by builtin instruction streams."); - w->SectionText(); - w->AlignToCodeAlignment(); - w->DeclareLabel(EmbeddedBlobDataSymbol().c_str()); - - WriteBinaryContentsAsInlineAssembly(w, blob->data(), - i::EmbeddedData::RawDataOffset()); - } - - void WriteBuiltin(PlatformDependentEmbeddedFileWriter* w, - const i::EmbeddedData* blob, const int builtin_id) const { - const bool is_default_variant = - std::strcmp(embedded_variant_, kDefaultEmbeddedVariant) == 0; - - char builtin_symbol[kTemporaryStringLength]; - if (is_default_variant) { - // Create nicer symbol names for the default mode. - i::SNPrintF(i::Vector<char>(builtin_symbol), "Builtins_%s", - i::Builtins::name(builtin_id)); - } else { - i::SNPrintF(i::Vector<char>(builtin_symbol), "%s_Builtins_%s", - embedded_variant_, i::Builtins::name(builtin_id)); - } - - // Labels created here will show up in backtraces. We check in - // Isolate::SetEmbeddedBlob that the blob layout remains unchanged, i.e. - // that labels do not insert bytes into the middle of the blob byte - // stream. - w->DeclareFunctionBegin(builtin_symbol); - const std::vector<byte>& current_positions = source_positions_[builtin_id]; - - // The code below interleaves bytes of assembly code for the builtin - // function with source positions at the appropriate offsets. - Vector<const byte> vpos(current_positions.data(), current_positions.size()); - v8::internal::SourcePositionTableIterator positions( - vpos, SourcePositionTableIterator::kExternalOnly); - - const uint8_t* data = reinterpret_cast<const uint8_t*>( - blob->InstructionStartOfBuiltin(builtin_id)); - uint32_t size = blob->PaddedInstructionSizeOfBuiltin(builtin_id); - uint32_t i = 0; - uint32_t next_offset = static_cast<uint32_t>( - positions.done() ? size : positions.code_offset()); - while (i < size) { - if (i == next_offset) { - // Write source directive. - w->SourceInfo(positions.source_position().ExternalFileId(), - GetExternallyCompiledFilename( - positions.source_position().ExternalFileId()), - positions.source_position().ExternalLine()); - positions.Advance(); - next_offset = static_cast<uint32_t>( - positions.done() ? size : positions.code_offset()); - } - CHECK_GE(next_offset, i); - WriteBinaryContentsAsInlineAssembly(w, data + i, next_offset - i); - i = next_offset; - } - - w->DeclareFunctionEnd(builtin_symbol); - } - - void WriteInstructionStreams(PlatformDependentEmbeddedFileWriter* w, - const i::EmbeddedData* blob) const { - for (int i = 0; i < i::Builtins::builtin_count; i++) { - if (!blob->ContainsBuiltin(i)) continue; - - WriteBuiltin(w, blob, i); - } - w->Newline(); - } - - void WriteFileEpilogue(PlatformDependentEmbeddedFileWriter* w, - const i::EmbeddedData* blob) const { - { - char embedded_blob_symbol[kTemporaryStringLength]; - i::SNPrintF(i::Vector<char>(embedded_blob_symbol), "v8_%s_embedded_blob_", - embedded_variant_); - - w->Comment("Pointer to the beginning of the embedded blob."); - w->SectionData(); - w->AlignToDataAlignment(); - w->DeclarePointerToSymbol(embedded_blob_symbol, - EmbeddedBlobDataSymbol().c_str()); - w->Newline(); - } - - { - char embedded_blob_size_symbol[kTemporaryStringLength]; - i::SNPrintF(i::Vector<char>(embedded_blob_size_symbol), - "v8_%s_embedded_blob_size_", embedded_variant_); - - w->Comment("The size of the embedded blob in bytes."); - w->SectionRoData(); - w->AlignToDataAlignment(); - w->DeclareUint32(embedded_blob_size_symbol, blob->size()); - w->Newline(); - } - -#if defined(V8_OS_WIN_X64) - if (win64_unwindinfo::CanEmitUnwindInfoForBuiltins()) { - WriteUnwindInfo(w, blob); - } -#endif - - w->FileEpilogue(); - } - -#if defined(V8_OS_WIN_X64) - std::string BuiltinsUnwindInfoLabel() const; - void WriteUnwindInfo(PlatformDependentEmbeddedFileWriter* w, - const i::EmbeddedData* blob) const; - void WriteUnwindInfoEntry(PlatformDependentEmbeddedFileWriter* w, - uint64_t rva_start, uint64_t rva_end) const; -#endif - -#if defined(_MSC_VER) && !defined(__clang__) -#define V8_COMPILER_IS_MSVC -#endif - -#if defined(V8_COMPILER_IS_MSVC) - // Windows MASM doesn't have an .octa directive, use QWORDs instead. - // Note: MASM *really* does not like large data streams. It takes over 5 - // minutes to assemble the ~350K lines of embedded.S produced when using - // BYTE directives in a debug build. QWORD produces roughly 120KLOC and - // reduces assembly time to ~40 seconds. Still terrible, but much better - // than before. See also: https://crbug.com/v8/8475. - static constexpr DataDirective kByteChunkDirective = kQuad; - static constexpr int kByteChunkSize = 8; - - static int WriteByteChunk(PlatformDependentEmbeddedFileWriter* w, - int current_line_length, const uint8_t* data) { - const uint64_t* quad_ptr = reinterpret_cast<const uint64_t*>(data); - return current_line_length + w->HexLiteral(*quad_ptr); - } - -#elif defined(V8_OS_AIX) - // PPC uses a fixed 4 byte instruction set, using .long - // to prevent any unnecessary padding. - static constexpr DataDirective kByteChunkDirective = kLong; - static constexpr int kByteChunkSize = 4; - - static int WriteByteChunk(PlatformDependentEmbeddedFileWriter* w, - int current_line_length, const uint8_t* data) { - const uint32_t* long_ptr = reinterpret_cast<const uint32_t*>(data); - return current_line_length + w->HexLiteral(*long_ptr); - } - -#else // defined(V8_COMPILER_IS_MSVC) || defined(V8_OS_AIX) - static constexpr DataDirective kByteChunkDirective = kOcta; - static constexpr int kByteChunkSize = 16; - - static int WriteByteChunk(PlatformDependentEmbeddedFileWriter* w, - int current_line_length, const uint8_t* data) { - const size_t size = kInt64Size; - - uint64_t part1, part2; - // Use memcpy for the reads since {data} is not guaranteed to be aligned. -#ifdef V8_TARGET_BIG_ENDIAN - memcpy(&part1, data, size); - memcpy(&part2, data + size, size); -#else - memcpy(&part1, data + size, size); - memcpy(&part2, data, size); -#endif // V8_TARGET_BIG_ENDIAN - - if (part1 != 0) { - current_line_length += - fprintf(w->fp(), "0x%" PRIx64 "%016" PRIx64, part1, part2); - } else { - current_line_length += fprintf(w->fp(), "0x%" PRIx64, part2); - } - return current_line_length; - } -#endif // defined(V8_COMPILER_IS_MSVC) || defined(V8_OS_AIX) -#undef V8_COMPILER_IS_MSVC - - static int WriteDirectiveOrSeparator(PlatformDependentEmbeddedFileWriter* w, - int current_line_length, - DataDirective directive) { - int printed_chars; - if (current_line_length == 0) { - printed_chars = w->IndentedDataDirective(directive); - DCHECK_LT(0, printed_chars); - } else { - printed_chars = fprintf(w->fp(), ","); - DCHECK_EQ(1, printed_chars); - } - return current_line_length + printed_chars; - } - - static int WriteLineEndIfNeeded(PlatformDependentEmbeddedFileWriter* w, - int current_line_length, int write_size) { - static const int kTextWidth = 100; - // Check if adding ',0xFF...FF\n"' would force a line wrap. This doesn't use - // the actual size of the string to be written to determine this so it's - // more conservative than strictly needed. - if (current_line_length + strlen(",0x") + write_size * 2 > kTextWidth) { - fprintf(w->fp(), "\n"); - return 0; - } else { - return current_line_length; - } - } - - static void WriteBinaryContentsAsInlineAssembly( - PlatformDependentEmbeddedFileWriter* w, const uint8_t* data, - uint32_t size) { - int current_line_length = 0; - uint32_t i = 0; - - // Begin by writing out byte chunks. - for (; i + kByteChunkSize < size; i += kByteChunkSize) { - current_line_length = WriteDirectiveOrSeparator(w, current_line_length, - kByteChunkDirective); - current_line_length = WriteByteChunk(w, current_line_length, data + i); - current_line_length = - WriteLineEndIfNeeded(w, current_line_length, kByteChunkSize); - } - if (current_line_length != 0) w->Newline(); - current_line_length = 0; - - // Write any trailing bytes one-by-one. - for (; i < size; i++) { - current_line_length = - WriteDirectiveOrSeparator(w, current_line_length, kByte); - current_line_length += w->HexLiteral(data[i]); - current_line_length = WriteLineEndIfNeeded(w, current_line_length, 1); - } - - if (current_line_length != 0) w->Newline(); - } - - static int ExternalFilenameIndexToId(int index) { - return kFirstExternalFilenameId + index; - } - - static int ExternalFilenameIdToIndex(int id) { - return id - kFirstExternalFilenameId; - } - - std::vector<byte> source_positions_[Builtins::builtin_count]; - -#if defined(V8_OS_WIN_X64) - win64_unwindinfo::BuiltinUnwindInfo unwind_infos_[Builtins::builtin_count]; -#endif - - // In assembly directives, filename ids need to begin with 1. - static const int kFirstExternalFilenameId = 1; - std::map<const char*, int> external_filenames_; - std::vector<const char*> external_filenames_by_index_; - - const char* embedded_src_path_ = nullptr; - const char* embedded_variant_ = kDefaultEmbeddedVariant; -}; - -} // namespace internal -} // namespace v8 - -#endif // V8_SNAPSHOT_EMBEDDED_FILE_WRITER_H_ diff --git a/deps/v8/src/snapshot/embedded-data.cc b/deps/v8/src/snapshot/embedded/embedded-data.cc index 0488c2f2c7..0474d3babe 100644 --- a/deps/v8/src/snapshot/embedded-data.cc +++ b/deps/v8/src/snapshot/embedded/embedded-data.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/snapshot/embedded-data.h" +#include "src/snapshot/embedded/embedded-data.h" -#include "src/assembler-inl.h" -#include "src/callable.h" -#include "src/objects-inl.h" +#include "src/codegen/assembler-inl.h" +#include "src/codegen/callable.h" +#include "src/objects/objects-inl.h" #include "src/snapshot/snapshot.h" namespace v8 { @@ -89,8 +89,8 @@ void InstructionStream::FreeOffHeapInstructionStream(uint8_t* data, namespace { bool BuiltinAliasesOffHeapTrampolineRegister(Isolate* isolate, Code code) { - DCHECK(Builtins::IsIsolateIndependent(code->builtin_index())); - switch (Builtins::KindOf(code->builtin_index())) { + DCHECK(Builtins::IsIsolateIndependent(code.builtin_index())); + switch (Builtins::KindOf(code.builtin_index())) { case Builtins::CPP: case Builtins::TFC: case Builtins::TFH: @@ -101,14 +101,13 @@ bool BuiltinAliasesOffHeapTrampolineRegister(Isolate* isolate, Code code) { // Bytecode handlers will only ever be used by the interpreter and so there // will never be a need to use trampolines with them. case Builtins::BCH: - case Builtins::API: case Builtins::ASM: // TODO(jgruber): Extend checks to remaining kinds. return false; } Callable callable = Builtins::CallableFor( - isolate, static_cast<Builtins::Name>(code->builtin_index())); + isolate, static_cast<Builtins::Name>(code.builtin_index())); CallInterfaceDescriptor descriptor = callable.descriptor(); if (descriptor.ContextRegister() == kOffHeapTrampolineRegister) { @@ -152,7 +151,7 @@ void FinalizeEmbeddedCodeTargets(Isolate* isolate, EmbeddedData* blob) { // Do not emit write-barrier for off-heap writes. off_heap_it.rinfo()->set_target_address( - blob->InstructionStartOfBuiltin(target->builtin_index()), + blob->InstructionStartOfBuiltin(target.builtin_index()), SKIP_WRITE_BARRIER); on_heap_it.next(); @@ -186,7 +185,7 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) { if (Builtins::IsIsolateIndependent(i)) { // Sanity-check that the given builtin is isolate-independent and does not // use the trampoline register in its calling convention. - if (!code->IsIsolateIndependent(isolate)) { + if (!code.IsIsolateIndependent(isolate)) { saw_unsafe_builtin = true; fprintf(stderr, "%s is not isolate-independent.\n", Builtins::name(i)); } @@ -206,7 +205,7 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) { Builtins::name(i)); } - uint32_t length = static_cast<uint32_t>(code->raw_instruction_size()); + uint32_t length = static_cast<uint32_t>(code.raw_instruction_size()); DCHECK_EQ(0, raw_data_size % kCodeAlignment); metadata[i].instructions_offset = raw_data_size; @@ -249,10 +248,10 @@ EmbeddedData EmbeddedData::FromIsolate(Isolate* isolate) { Code code = builtins->builtin(i); uint32_t offset = metadata[i].instructions_offset; uint8_t* dst = raw_data_start + offset; - DCHECK_LE(RawDataOffset() + offset + code->raw_instruction_size(), + DCHECK_LE(RawDataOffset() + offset + code.raw_instruction_size(), blob_size); - std::memcpy(dst, reinterpret_cast<uint8_t*>(code->raw_instruction_start()), - code->raw_instruction_size()); + std::memcpy(dst, reinterpret_cast<uint8_t*>(code.raw_instruction_start()), + code.raw_instruction_size()); } EmbeddedData d(blob, blob_size); @@ -290,6 +289,19 @@ uint32_t EmbeddedData::InstructionSizeOfBuiltin(int i) const { return metadata[i].instructions_length; } +Address EmbeddedData::InstructionStartOfBytecodeHandlers() const { + return InstructionStartOfBuiltin(Builtins::kFirstBytecodeHandler); +} + +Address EmbeddedData::InstructionEndOfBytecodeHandlers() const { + STATIC_ASSERT(Builtins::kFirstBytecodeHandler + kNumberOfBytecodeHandlers + + 2 * kNumberOfWideBytecodeHandlers == + Builtins::builtin_count); + int lastBytecodeHandler = Builtins::builtin_count - 1; + return InstructionStartOfBuiltin(lastBytecodeHandler) + + InstructionSizeOfBuiltin(lastBytecodeHandler); +} + size_t EmbeddedData::CreateEmbeddedBlobHash() const { STATIC_ASSERT(EmbeddedBlobHashOffset() == 0); STATIC_ASSERT(EmbeddedBlobHashSize() == kSizetSize); diff --git a/deps/v8/src/snapshot/embedded-data.h b/deps/v8/src/snapshot/embedded/embedded-data.h index 5c5653e2ca..58905668f2 100644 --- a/deps/v8/src/snapshot/embedded-data.h +++ b/deps/v8/src/snapshot/embedded/embedded-data.h @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef V8_SNAPSHOT_EMBEDDED_DATA_H_ -#define V8_SNAPSHOT_EMBEDDED_DATA_H_ +#ifndef V8_SNAPSHOT_EMBEDDED_EMBEDDED_DATA_H_ +#define V8_SNAPSHOT_EMBEDDED_EMBEDDED_DATA_H_ #include "src/base/macros.h" #include "src/builtins/builtins.h" -#include "src/globals.h" -#include "src/isolate.h" +#include "src/common/globals.h" +#include "src/execution/isolate.h" namespace v8 { namespace internal { @@ -57,6 +57,9 @@ class EmbeddedData final { Address InstructionStartOfBuiltin(int i) const; uint32_t InstructionSizeOfBuiltin(int i) const; + Address InstructionStartOfBytecodeHandlers() const; + Address InstructionEndOfBytecodeHandlers() const; + bool ContainsBuiltin(int i) const { return InstructionSizeOfBuiltin(i) > 0; } uint32_t AddressForHashing(Address addr) { @@ -140,4 +143,4 @@ class EmbeddedData final { } // namespace internal } // namespace v8 -#endif // V8_SNAPSHOT_EMBEDDED_DATA_H_ +#endif // V8_SNAPSHOT_EMBEDDED_EMBEDDED_DATA_H_ diff --git a/deps/v8/src/snapshot/embedded-empty.cc b/deps/v8/src/snapshot/embedded/embedded-empty.cc index 9ffb3458d3..9ffb3458d3 100644 --- a/deps/v8/src/snapshot/embedded-empty.cc +++ b/deps/v8/src/snapshot/embedded/embedded-empty.cc diff --git a/deps/v8/src/snapshot/embedded/embedded-file-writer.cc b/deps/v8/src/snapshot/embedded/embedded-file-writer.cc new file mode 100644 index 0000000000..4703ef4822 --- /dev/null +++ b/deps/v8/src/snapshot/embedded/embedded-file-writer.cc @@ -0,0 +1,214 @@ +// Copyright 2018 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. + +#include "src/snapshot/embedded/embedded-file-writer.h" + +#include <cinttypes> + +#include "src/codegen/source-position-table.h" +#include "src/objects/code-inl.h" + +namespace v8 { +namespace internal { + +void EmbeddedFileWriter::WriteBuiltin(PlatformEmbeddedFileWriterBase* w, + const i::EmbeddedData* blob, + const int builtin_id) const { + const bool is_default_variant = + std::strcmp(embedded_variant_, kDefaultEmbeddedVariant) == 0; + + i::EmbeddedVector<char, kTemporaryStringLength> builtin_symbol; + if (is_default_variant) { + // Create nicer symbol names for the default mode. + i::SNPrintF(builtin_symbol, "Builtins_%s", i::Builtins::name(builtin_id)); + } else { + i::SNPrintF(builtin_symbol, "%s_Builtins_%s", embedded_variant_, + i::Builtins::name(builtin_id)); + } + + // Labels created here will show up in backtraces. We check in + // Isolate::SetEmbeddedBlob that the blob layout remains unchanged, i.e. + // that labels do not insert bytes into the middle of the blob byte + // stream. + w->DeclareFunctionBegin(builtin_symbol.begin()); + const std::vector<byte>& current_positions = source_positions_[builtin_id]; + + // The code below interleaves bytes of assembly code for the builtin + // function with source positions at the appropriate offsets. + Vector<const byte> vpos(current_positions.data(), current_positions.size()); + v8::internal::SourcePositionTableIterator positions( + vpos, SourcePositionTableIterator::kExternalOnly); + + const uint8_t* data = reinterpret_cast<const uint8_t*>( + blob->InstructionStartOfBuiltin(builtin_id)); + uint32_t size = blob->PaddedInstructionSizeOfBuiltin(builtin_id); + uint32_t i = 0; + uint32_t next_offset = + static_cast<uint32_t>(positions.done() ? size : positions.code_offset()); + while (i < size) { + if (i == next_offset) { + // Write source directive. + w->SourceInfo(positions.source_position().ExternalFileId(), + GetExternallyCompiledFilename( + positions.source_position().ExternalFileId()), + positions.source_position().ExternalLine()); + positions.Advance(); + next_offset = static_cast<uint32_t>( + positions.done() ? size : positions.code_offset()); + } + CHECK_GE(next_offset, i); + WriteBinaryContentsAsInlineAssembly(w, data + i, next_offset - i); + i = next_offset; + } + + w->DeclareFunctionEnd(builtin_symbol.begin()); +} + +void EmbeddedFileWriter::WriteFileEpilogue(PlatformEmbeddedFileWriterBase* w, + const i::EmbeddedData* blob) const { + { + i::EmbeddedVector<char, kTemporaryStringLength> embedded_blob_symbol; + i::SNPrintF(embedded_blob_symbol, "v8_%s_embedded_blob_", + embedded_variant_); + + w->Comment("Pointer to the beginning of the embedded blob."); + w->SectionData(); + w->AlignToDataAlignment(); + w->DeclarePointerToSymbol(embedded_blob_symbol.begin(), + EmbeddedBlobDataSymbol().c_str()); + w->Newline(); + } + + { + i::EmbeddedVector<char, kTemporaryStringLength> embedded_blob_size_symbol; + i::SNPrintF(embedded_blob_size_symbol, "v8_%s_embedded_blob_size_", + embedded_variant_); + + w->Comment("The size of the embedded blob in bytes."); + w->SectionRoData(); + w->AlignToDataAlignment(); + w->DeclareUint32(embedded_blob_size_symbol.begin(), blob->size()); + w->Newline(); + } + +#if defined(V8_OS_WIN_X64) + { + i::EmbeddedVector<char, kTemporaryStringLength> unwind_info_symbol; + i::SNPrintF(unwind_info_symbol, "%s_Builtins_UnwindInfo", + embedded_variant_); + + w->MaybeEmitUnwindData(unwind_info_symbol.begin(), + EmbeddedBlobDataSymbol().c_str(), blob, + reinterpret_cast<const void*>(&unwind_infos_[0])); + } +#endif + + w->FileEpilogue(); +} + +namespace { + +int WriteDirectiveOrSeparator(PlatformEmbeddedFileWriterBase* w, + int current_line_length, + DataDirective directive) { + int printed_chars; + if (current_line_length == 0) { + printed_chars = w->IndentedDataDirective(directive); + DCHECK_LT(0, printed_chars); + } else { + printed_chars = fprintf(w->fp(), ","); + DCHECK_EQ(1, printed_chars); + } + return current_line_length + printed_chars; +} + +int WriteLineEndIfNeeded(PlatformEmbeddedFileWriterBase* w, + int current_line_length, int write_size) { + static const int kTextWidth = 100; + // Check if adding ',0xFF...FF\n"' would force a line wrap. This doesn't use + // the actual size of the string to be written to determine this so it's + // more conservative than strictly needed. + if (current_line_length + strlen(",0x") + write_size * 2 > kTextWidth) { + fprintf(w->fp(), "\n"); + return 0; + } else { + return current_line_length; + } +} + +} // namespace + +// static +void EmbeddedFileWriter::WriteBinaryContentsAsInlineAssembly( + PlatformEmbeddedFileWriterBase* w, const uint8_t* data, uint32_t size) { + int current_line_length = 0; + uint32_t i = 0; + + // Begin by writing out byte chunks. + const DataDirective directive = w->ByteChunkDataDirective(); + const int byte_chunk_size = DataDirectiveSize(directive); + for (; i + byte_chunk_size < size; i += byte_chunk_size) { + current_line_length = + WriteDirectiveOrSeparator(w, current_line_length, directive); + current_line_length += w->WriteByteChunk(data + i); + current_line_length = + WriteLineEndIfNeeded(w, current_line_length, byte_chunk_size); + } + if (current_line_length != 0) w->Newline(); + current_line_length = 0; + + // Write any trailing bytes one-by-one. + for (; i < size; i++) { + current_line_length = + WriteDirectiveOrSeparator(w, current_line_length, kByte); + current_line_length += w->HexLiteral(data[i]); + current_line_length = WriteLineEndIfNeeded(w, current_line_length, 1); + } + + if (current_line_length != 0) w->Newline(); +} + +int EmbeddedFileWriter::LookupOrAddExternallyCompiledFilename( + const char* filename) { + auto result = external_filenames_.find(filename); + if (result != external_filenames_.end()) { + return result->second; + } + int new_id = + ExternalFilenameIndexToId(static_cast<int>(external_filenames_.size())); + external_filenames_.insert(std::make_pair(filename, new_id)); + external_filenames_by_index_.push_back(filename); + DCHECK_EQ(external_filenames_by_index_.size(), external_filenames_.size()); + return new_id; +} + +const char* EmbeddedFileWriter::GetExternallyCompiledFilename( + int fileid) const { + size_t index = static_cast<size_t>(ExternalFilenameIdToIndex(fileid)); + DCHECK_GE(index, 0); + DCHECK_LT(index, external_filenames_by_index_.size()); + + return external_filenames_by_index_[index]; +} + +int EmbeddedFileWriter::GetExternallyCompiledFilenameCount() const { + return static_cast<int>(external_filenames_.size()); +} + +void EmbeddedFileWriter::PrepareBuiltinSourcePositionMap(Builtins* builtins) { + for (int i = 0; i < Builtins::builtin_count; i++) { + // Retrieve the SourcePositionTable and copy it. + Code code = builtins->builtin(i); + // Verify that the code object is still the "real code" and not a + // trampoline (which wouldn't have source positions). + DCHECK(!code.is_off_heap_trampoline()); + std::vector<unsigned char> data( + code.SourcePositionTable().GetDataStartAddress(), + code.SourcePositionTable().GetDataEndAddress()); + source_positions_[i] = data; + } +} + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/snapshot/embedded/embedded-file-writer.h b/deps/v8/src/snapshot/embedded/embedded-file-writer.h new file mode 100644 index 0000000000..c26465ae6a --- /dev/null +++ b/deps/v8/src/snapshot/embedded/embedded-file-writer.h @@ -0,0 +1,221 @@ +// Copyright 2018 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. + +#ifndef V8_SNAPSHOT_EMBEDDED_EMBEDDED_FILE_WRITER_H_ +#define V8_SNAPSHOT_EMBEDDED_EMBEDDED_FILE_WRITER_H_ + +#include <cinttypes> +#include <cstdio> +#include <cstring> + +#include "src/common/globals.h" +#include "src/snapshot/embedded/embedded-data.h" +#include "src/snapshot/embedded/platform-embedded-file-writer-base.h" + +#if defined(V8_OS_WIN_X64) +#include "src/diagnostics/unwinding-info-win64.h" +#endif + +namespace v8 { +namespace internal { + +static constexpr char kDefaultEmbeddedVariant[] = "Default"; + +// Detailed source-code information about builtins can only be obtained by +// registration on the isolate during compilation. +class EmbeddedFileWriterInterface { + public: + // We maintain a database of filenames to synthetic IDs. + virtual int LookupOrAddExternallyCompiledFilename(const char* filename) = 0; + virtual const char* GetExternallyCompiledFilename(int index) const = 0; + virtual int GetExternallyCompiledFilenameCount() const = 0; + + // The isolate will call the method below just prior to replacing the + // compiled builtin Code objects with trampolines. + virtual void PrepareBuiltinSourcePositionMap(Builtins* builtins) = 0; + +#if defined(V8_OS_WIN_X64) + virtual void SetBuiltinUnwindData( + int builtin_index, + const win64_unwindinfo::BuiltinUnwindInfo& unwinding_info) = 0; +#endif +}; + +// Generates the embedded.S file which is later compiled into the final v8 +// binary. Its contents are exported through two symbols: +// +// v8_<variant>_embedded_blob_ (intptr_t): +// a pointer to the start of the embedded blob. +// v8_<variant>_embedded_blob_size_ (uint32_t): +// size of the embedded blob in bytes. +// +// The variant is usually "Default" but can be modified in multisnapshot builds. +class EmbeddedFileWriter : public EmbeddedFileWriterInterface { + public: + int LookupOrAddExternallyCompiledFilename(const char* filename) override; + const char* GetExternallyCompiledFilename(int fileid) const override; + int GetExternallyCompiledFilenameCount() const override; + + void PrepareBuiltinSourcePositionMap(Builtins* builtins) override; + +#if defined(V8_OS_WIN_X64) + void SetBuiltinUnwindData( + int builtin_index, + const win64_unwindinfo::BuiltinUnwindInfo& unwinding_info) override { + DCHECK_LT(builtin_index, Builtins::builtin_count); + unwind_infos_[builtin_index] = unwinding_info; + } +#endif + + void SetEmbeddedFile(const char* embedded_src_path) { + embedded_src_path_ = embedded_src_path; + } + + void SetEmbeddedVariant(const char* embedded_variant) { + if (embedded_variant == nullptr) return; + embedded_variant_ = embedded_variant; + } + + void SetTargetArch(const char* target_arch) { target_arch_ = target_arch; } + + void SetTargetOs(const char* target_os) { target_os_ = target_os; } + + void WriteEmbedded(const i::EmbeddedData* blob) const { + MaybeWriteEmbeddedFile(blob); + } + + private: + void MaybeWriteEmbeddedFile(const i::EmbeddedData* blob) const { + if (embedded_src_path_ == nullptr) return; + + FILE* fp = GetFileDescriptorOrDie(embedded_src_path_); + + std::unique_ptr<PlatformEmbeddedFileWriterBase> writer = + NewPlatformEmbeddedFileWriter(target_arch_, target_os_); + writer->SetFile(fp); + + WriteFilePrologue(writer.get()); + WriteExternalFilenames(writer.get()); + WriteMetadataSection(writer.get(), blob); + WriteInstructionStreams(writer.get(), blob); + WriteFileEpilogue(writer.get(), blob); + + fclose(fp); + } + + static FILE* GetFileDescriptorOrDie(const char* filename) { + FILE* fp = v8::base::OS::FOpen(filename, "wb"); + if (fp == nullptr) { + i::PrintF("Unable to open file \"%s\" for writing.\n", filename); + exit(1); + } + return fp; + } + + void WriteFilePrologue(PlatformEmbeddedFileWriterBase* w) const { + w->Comment("Autogenerated file. Do not edit."); + w->Newline(); + w->FilePrologue(); + } + + void WriteExternalFilenames(PlatformEmbeddedFileWriterBase* w) const { + w->Comment( + "Source positions in the embedded blob refer to filenames by id."); + w->Comment("Assembly directives here map the id to a filename."); + w->Newline(); + + // Write external filenames. + int size = static_cast<int>(external_filenames_by_index_.size()); + for (int i = 0; i < size; i++) { + w->DeclareExternalFilename(ExternalFilenameIndexToId(i), + external_filenames_by_index_[i]); + } + } + + // Fairly arbitrary but should fit all symbol names. + static constexpr int kTemporaryStringLength = 256; + + std::string EmbeddedBlobDataSymbol() const { + i::EmbeddedVector<char, kTemporaryStringLength> embedded_blob_data_symbol; + i::SNPrintF(embedded_blob_data_symbol, "v8_%s_embedded_blob_data_", + embedded_variant_); + return std::string{embedded_blob_data_symbol.begin()}; + } + + void WriteMetadataSection(PlatformEmbeddedFileWriterBase* w, + const i::EmbeddedData* blob) const { + w->Comment("The embedded blob starts here. Metadata comes first, followed"); + w->Comment("by builtin instruction streams."); + w->SectionText(); + w->AlignToCodeAlignment(); + w->DeclareLabel(EmbeddedBlobDataSymbol().c_str()); + + WriteBinaryContentsAsInlineAssembly(w, blob->data(), + i::EmbeddedData::RawDataOffset()); + } + + void WriteBuiltin(PlatformEmbeddedFileWriterBase* w, + const i::EmbeddedData* blob, const int builtin_id) const; + + void WriteInstructionStreams(PlatformEmbeddedFileWriterBase* w, + const i::EmbeddedData* blob) const { + for (int i = 0; i < i::Builtins::builtin_count; i++) { + if (!blob->ContainsBuiltin(i)) continue; + + WriteBuiltin(w, blob, i); + } + w->Newline(); + } + + void WriteFileEpilogue(PlatformEmbeddedFileWriterBase* w, + const i::EmbeddedData* blob) const; + +#if defined(V8_OS_WIN_X64) + std::string BuiltinsUnwindInfoLabel() const; + void WriteUnwindInfo(PlatformEmbeddedFileWriterBase* w, + const i::EmbeddedData* blob) const; + void WriteUnwindInfoEntry(PlatformEmbeddedFileWriterBase* w, + uint64_t rva_start, uint64_t rva_end) const; +#endif + + static void WriteBinaryContentsAsInlineAssembly( + PlatformEmbeddedFileWriterBase* w, const uint8_t* data, uint32_t size); + + // In assembly directives, filename ids need to begin with 1. + static constexpr int kFirstExternalFilenameId = 1; + static int ExternalFilenameIndexToId(int index) { + return kFirstExternalFilenameId + index; + } + static int ExternalFilenameIdToIndex(int id) { + return id - kFirstExternalFilenameId; + } + + private: + std::vector<byte> source_positions_[Builtins::builtin_count]; + +#if defined(V8_OS_WIN_X64) + win64_unwindinfo::BuiltinUnwindInfo unwind_infos_[Builtins::builtin_count]; +#endif + + std::map<const char*, int> external_filenames_; + std::vector<const char*> external_filenames_by_index_; + + // The file to generate or nullptr. + const char* embedded_src_path_ = nullptr; + + // The variant is only used in multi-snapshot builds and otherwise set to + // "Default". + const char* embedded_variant_ = kDefaultEmbeddedVariant; + + // {target_arch} and {target_os} control the generated assembly format. Note + // these may differ from both host- and target-platforms specified through + // e.g. V8_OS_* and V8_TARGET_ARCH_* defines. + const char* target_arch_ = nullptr; + const char* target_os_ = nullptr; +}; + +} // namespace internal +} // namespace v8 + +#endif // V8_SNAPSHOT_EMBEDDED_EMBEDDED_FILE_WRITER_H_ diff --git a/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-aix.cc b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-aix.cc new file mode 100644 index 0000000000..3aef77e341 --- /dev/null +++ b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-aix.cc @@ -0,0 +1,132 @@ +// Copyright 2019 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. + +#include "src/snapshot/embedded/platform-embedded-file-writer-aix.h" + +namespace v8 { +namespace internal { + +#define SYMBOL_PREFIX "" + +namespace { + +const char* DirectiveAsString(DataDirective directive) { + switch (directive) { + case kByte: + return ".byte"; + case kLong: + return ".long"; + case kQuad: + return ".llong"; + default: + UNREACHABLE(); + } +} + +} // namespace + +void PlatformEmbeddedFileWriterAIX::SectionText() { + fprintf(fp_, ".csect .text[PR]\n"); +} + +void PlatformEmbeddedFileWriterAIX::SectionData() { + fprintf(fp_, ".csect .data[RW]\n"); +} + +void PlatformEmbeddedFileWriterAIX::SectionRoData() { + fprintf(fp_, ".csect[RO]\n"); +} + +void PlatformEmbeddedFileWriterAIX::DeclareUint32(const char* name, + uint32_t value) { + DeclareSymbolGlobal(name); + fprintf(fp_, ".align 2\n"); + fprintf(fp_, "%s:\n", name); + IndentedDataDirective(kLong); + fprintf(fp_, "%d\n", value); + Newline(); +} + +void PlatformEmbeddedFileWriterAIX::DeclarePointerToSymbol(const char* name, + const char* target) { + AlignToCodeAlignment(); + DeclareLabel(name); + fprintf(fp_, " %s %s\n", DirectiveAsString(PointerSizeDirective()), target); + Newline(); +} + +void PlatformEmbeddedFileWriterAIX::DeclareSymbolGlobal(const char* name) { + fprintf(fp_, ".globl %s\n", name); +} + +void PlatformEmbeddedFileWriterAIX::AlignToCodeAlignment() { + fprintf(fp_, ".align 5\n"); +} + +void PlatformEmbeddedFileWriterAIX::AlignToDataAlignment() { + fprintf(fp_, ".align 3\n"); +} + +void PlatformEmbeddedFileWriterAIX::Comment(const char* string) { + fprintf(fp_, "// %s\n", string); +} + +void PlatformEmbeddedFileWriterAIX::DeclareLabel(const char* name) { + DeclareSymbolGlobal(name); + fprintf(fp_, "%s:\n", name); +} + +void PlatformEmbeddedFileWriterAIX::SourceInfo(int fileid, const char* filename, + int line) { + fprintf(fp_, ".xline %d, \"%s\"\n", line, filename); +} + +void PlatformEmbeddedFileWriterAIX::DeclareFunctionBegin(const char* name) { + Newline(); + DeclareSymbolGlobal(name); + fprintf(fp_, ".csect %s[DS]\n", name); // function descriptor + fprintf(fp_, "%s:\n", name); + fprintf(fp_, ".llong .%s, 0, 0\n", name); + SectionText(); + fprintf(fp_, ".%s:\n", name); +} + +void PlatformEmbeddedFileWriterAIX::DeclareFunctionEnd(const char* name) {} + +int PlatformEmbeddedFileWriterAIX::HexLiteral(uint64_t value) { + return fprintf(fp_, "0x%" PRIx64, value); +} + +void PlatformEmbeddedFileWriterAIX::FilePrologue() {} + +void PlatformEmbeddedFileWriterAIX::DeclareExternalFilename( + int fileid, const char* filename) { + // File name cannot be declared with an identifier on AIX. + // We use the SourceInfo method to emit debug info in + //.xline <line-number> <file-name> format. +} + +void PlatformEmbeddedFileWriterAIX::FileEpilogue() {} + +int PlatformEmbeddedFileWriterAIX::IndentedDataDirective( + DataDirective directive) { + return fprintf(fp_, " %s ", DirectiveAsString(directive)); +} + +DataDirective PlatformEmbeddedFileWriterAIX::ByteChunkDataDirective() const { + // PPC uses a fixed 4 byte instruction set, using .long + // to prevent any unnecessary padding. + return kLong; +} + +int PlatformEmbeddedFileWriterAIX::WriteByteChunk(const uint8_t* data) { + DCHECK_EQ(ByteChunkDataDirective(), kLong); + const uint32_t* long_ptr = reinterpret_cast<const uint32_t*>(data); + return HexLiteral(*long_ptr); +} + +#undef SYMBOL_PREFIX + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-aix.h b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-aix.h new file mode 100644 index 0000000000..6119d50623 --- /dev/null +++ b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-aix.h @@ -0,0 +1,64 @@ +// Copyright 2019 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. + +#ifndef V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_AIX_H_ +#define V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_AIX_H_ + +#include "src/base/macros.h" +#include "src/snapshot/embedded/platform-embedded-file-writer-base.h" + +namespace v8 { +namespace internal { + +class PlatformEmbeddedFileWriterAIX : public PlatformEmbeddedFileWriterBase { + public: + PlatformEmbeddedFileWriterAIX(EmbeddedTargetArch target_arch, + EmbeddedTargetOs target_os) + : target_arch_(target_arch), target_os_(target_os) { + USE(target_arch_); + USE(target_os_); + DCHECK_EQ(target_os_, EmbeddedTargetOs::kAIX); + } + + void SectionText() override; + void SectionData() override; + void SectionRoData() override; + + void AlignToCodeAlignment() override; + void AlignToDataAlignment() override; + + void DeclareUint32(const char* name, uint32_t value) override; + void DeclarePointerToSymbol(const char* name, const char* target) override; + + void DeclareLabel(const char* name) override; + + void SourceInfo(int fileid, const char* filename, int line) override; + void DeclareFunctionBegin(const char* name) override; + void DeclareFunctionEnd(const char* name) override; + + int HexLiteral(uint64_t value) override; + + void Comment(const char* string) override; + + void FilePrologue() override; + void DeclareExternalFilename(int fileid, const char* filename) override; + void FileEpilogue() override; + + int IndentedDataDirective(DataDirective directive) override; + + DataDirective ByteChunkDataDirective() const override; + int WriteByteChunk(const uint8_t* data) override; + + private: + void DeclareSymbolGlobal(const char* name); + + private: + const EmbeddedTargetArch target_arch_; + const EmbeddedTargetOs target_os_; +}; + +} // namespace internal +} // namespace v8 + +#endif // V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_AIX_H_ diff --git a/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-base.cc b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-base.cc new file mode 100644 index 0000000000..a17f039fa2 --- /dev/null +++ b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-base.cc @@ -0,0 +1,156 @@ +// Copyright 2019 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. + +#include "src/snapshot/embedded/platform-embedded-file-writer-base.h" + +#include <string> + +#include "src/common/globals.h" +#include "src/snapshot/embedded/platform-embedded-file-writer-aix.h" +#include "src/snapshot/embedded/platform-embedded-file-writer-generic.h" +#include "src/snapshot/embedded/platform-embedded-file-writer-mac.h" +#include "src/snapshot/embedded/platform-embedded-file-writer-win.h" + +namespace v8 { +namespace internal { + +DataDirective PointerSizeDirective() { + if (kSystemPointerSize == 8) { + return kQuad; + } else { + CHECK_EQ(4, kSystemPointerSize); + return kLong; + } +} + +int DataDirectiveSize(DataDirective directive) { + switch (directive) { + case kByte: + return 1; + case kLong: + return 4; + case kQuad: + return 8; + case kOcta: + return 16; + } + UNREACHABLE(); +} + +int PlatformEmbeddedFileWriterBase::WriteByteChunk(const uint8_t* data) { + DCHECK_EQ(ByteChunkDataDirective(), kOcta); + + static constexpr size_t kSize = kInt64Size; + + uint64_t part1, part2; + // Use memcpy for the reads since {data} is not guaranteed to be aligned. +#ifdef V8_TARGET_BIG_ENDIAN + memcpy(&part1, data, kSize); + memcpy(&part2, data + kSize, kSize); +#else + memcpy(&part1, data + kSize, kSize); + memcpy(&part2, data, kSize); +#endif // V8_TARGET_BIG_ENDIAN + + if (part1 != 0) { + return fprintf(fp(), "0x%" PRIx64 "%016" PRIx64, part1, part2); + } else { + return fprintf(fp(), "0x%" PRIx64, part2); + } +} + +namespace { + +EmbeddedTargetArch DefaultEmbeddedTargetArch() { +#if defined(V8_TARGET_ARCH_ARM) + return EmbeddedTargetArch::kArm; +#elif defined(V8_TARGET_ARCH_ARM64) + return EmbeddedTargetArch::kArm64; +#elif defined(V8_TARGET_ARCH_IA32) + return EmbeddedTargetArch::kIA32; +#elif defined(V8_TARGET_ARCH_X64) + return EmbeddedTargetArch::kX64; +#else + return EmbeddedTargetArch::kGeneric; +#endif +} + +EmbeddedTargetArch ToEmbeddedTargetArch(const char* s) { + if (s == nullptr) { + return DefaultEmbeddedTargetArch(); + } + + std::string string(s); + if (string == "arm") { + return EmbeddedTargetArch::kArm; + } else if (string == "arm64") { + return EmbeddedTargetArch::kArm64; + } else if (string == "ia32") { + return EmbeddedTargetArch::kIA32; + } else if (string == "x64") { + return EmbeddedTargetArch::kX64; + } else { + return EmbeddedTargetArch::kGeneric; + } +} + +EmbeddedTargetOs DefaultEmbeddedTargetOs() { +#if defined(V8_OS_AIX) + return EmbeddedTargetOs::kAIX; +#elif defined(V8_OS_MACOSX) + return EmbeddedTargetOs::kMac; +#elif defined(V8_OS_WIN) + return EmbeddedTargetOs::kWin; +#else + return EmbeddedTargetOs::kGeneric; +#endif +} + +EmbeddedTargetOs ToEmbeddedTargetOs(const char* s) { + if (s == nullptr) { + return DefaultEmbeddedTargetOs(); + } + + std::string string(s); + if (string == "aix") { + return EmbeddedTargetOs::kAIX; + } else if (string == "chromeos") { + return EmbeddedTargetOs::kChromeOS; + } else if (string == "fuchsia") { + return EmbeddedTargetOs::kFuchsia; + } else if (string == "ios" || string == "mac") { + return EmbeddedTargetOs::kMac; + } else if (string == "win") { + return EmbeddedTargetOs::kWin; + } else { + return EmbeddedTargetOs::kGeneric; + } +} + +} // namespace + +std::unique_ptr<PlatformEmbeddedFileWriterBase> NewPlatformEmbeddedFileWriter( + const char* target_arch, const char* target_os) { + auto embedded_target_arch = ToEmbeddedTargetArch(target_arch); + auto embedded_target_os = ToEmbeddedTargetOs(target_os); + + if (embedded_target_os == EmbeddedTargetOs::kAIX) { + return base::make_unique<PlatformEmbeddedFileWriterAIX>( + embedded_target_arch, embedded_target_os); + } else if (embedded_target_os == EmbeddedTargetOs::kMac) { + return base::make_unique<PlatformEmbeddedFileWriterMac>( + embedded_target_arch, embedded_target_os); + } else if (embedded_target_os == EmbeddedTargetOs::kWin) { + return base::make_unique<PlatformEmbeddedFileWriterWin>( + embedded_target_arch, embedded_target_os); + } else { + return base::make_unique<PlatformEmbeddedFileWriterGeneric>( + embedded_target_arch, embedded_target_os); + } + + UNREACHABLE(); +} + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-base.h b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-base.h new file mode 100644 index 0000000000..0f1763ba24 --- /dev/null +++ b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-base.h @@ -0,0 +1,105 @@ +// Copyright 2019 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. + +#ifndef V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_BASE_H_ +#define V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_BASE_H_ + +#include <cinttypes> +#include <cstdio> // For FILE. +#include <memory> + +namespace v8 { +namespace internal { + +class EmbeddedData; + +enum DataDirective { + kByte, + kLong, + kQuad, + kOcta, +}; + +DataDirective PointerSizeDirective(); +int DataDirectiveSize(DataDirective directive); + +enum class EmbeddedTargetOs { + kAIX, + kChromeOS, + kFuchsia, + kMac, + kWin, + kGeneric, // Everything not covered above falls in here. +}; + +enum class EmbeddedTargetArch { + kArm, + kArm64, + kIA32, + kX64, + kGeneric, // Everything not covered above falls in here. +}; + +// The platform-dependent logic for emitting assembly code for the generated +// embedded.S file. +class PlatformEmbeddedFileWriterBase { + public: + virtual ~PlatformEmbeddedFileWriterBase() = default; + + void SetFile(FILE* fp) { fp_ = fp; } + FILE* fp() const { return fp_; } + + virtual void SectionText() = 0; + virtual void SectionData() = 0; + virtual void SectionRoData() = 0; + + virtual void AlignToCodeAlignment() = 0; + virtual void AlignToDataAlignment() = 0; + + virtual void DeclareUint32(const char* name, uint32_t value) = 0; + virtual void DeclarePointerToSymbol(const char* name, const char* target) = 0; + + virtual void DeclareLabel(const char* name) = 0; + + virtual void SourceInfo(int fileid, const char* filename, int line) = 0; + virtual void DeclareFunctionBegin(const char* name) = 0; + virtual void DeclareFunctionEnd(const char* name) = 0; + + // Returns the number of printed characters. + virtual int HexLiteral(uint64_t value) = 0; + + virtual void Comment(const char* string) = 0; + virtual void Newline() { fprintf(fp_, "\n"); } + + virtual void FilePrologue() = 0; + virtual void DeclareExternalFilename(int fileid, const char* filename) = 0; + virtual void FileEpilogue() = 0; + + virtual int IndentedDataDirective(DataDirective directive) = 0; + + virtual DataDirective ByteChunkDataDirective() const { return kOcta; } + virtual int WriteByteChunk(const uint8_t* data); + + // This awkward interface works around the fact that unwind data emission + // is both high-level and platform-dependent. The former implies it should + // live in EmbeddedFileWriter, but code there should be platform-independent. + // + // Emits unwinding data on x64 Windows, and does nothing otherwise. + virtual void MaybeEmitUnwindData(const char* unwind_info_symbol, + const char* embedded_blob_data_symbol, + const EmbeddedData* blob, + const void* unwind_infos) {} + + protected: + FILE* fp_ = nullptr; +}; + +// The factory function. Returns the appropriate platform-specific instance. +std::unique_ptr<PlatformEmbeddedFileWriterBase> NewPlatformEmbeddedFileWriter( + const char* target_arch, const char* target_os); + +} // namespace internal +} // namespace v8 + +#endif // V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_BASE_H_ diff --git a/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-generic.cc b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-generic.cc new file mode 100644 index 0000000000..4cee1ac131 --- /dev/null +++ b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-generic.cc @@ -0,0 +1,140 @@ +// Copyright 2019 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. + +#include "src/snapshot/embedded/platform-embedded-file-writer-generic.h" + +#include <algorithm> +#include <cinttypes> + +#include "src/common/globals.h" + +namespace v8 { +namespace internal { + +#define SYMBOL_PREFIX "" + +namespace { + +const char* DirectiveAsString(DataDirective directive) { + switch (directive) { + case kByte: + return ".byte"; + case kLong: + return ".long"; + case kQuad: + return ".quad"; + case kOcta: + return ".octa"; + } + UNREACHABLE(); +} + +} // namespace + +void PlatformEmbeddedFileWriterGeneric::SectionText() { + if (target_os_ == EmbeddedTargetOs::kChromeOS) { + fprintf(fp_, ".section .text.hot.embedded\n"); + } else { + fprintf(fp_, ".section .text\n"); + } +} + +void PlatformEmbeddedFileWriterGeneric::SectionData() { + fprintf(fp_, ".section .data\n"); +} + +void PlatformEmbeddedFileWriterGeneric::SectionRoData() { + fprintf(fp_, ".section .rodata\n"); +} + +void PlatformEmbeddedFileWriterGeneric::DeclareUint32(const char* name, + uint32_t value) { + DeclareSymbolGlobal(name); + DeclareLabel(name); + IndentedDataDirective(kLong); + fprintf(fp_, "%d", value); + Newline(); +} + +void PlatformEmbeddedFileWriterGeneric::DeclarePointerToSymbol( + const char* name, const char* target) { + DeclareSymbolGlobal(name); + DeclareLabel(name); + fprintf(fp_, " %s %s%s\n", DirectiveAsString(PointerSizeDirective()), + SYMBOL_PREFIX, target); +} + +void PlatformEmbeddedFileWriterGeneric::DeclareSymbolGlobal(const char* name) { + fprintf(fp_, ".global %s%s\n", SYMBOL_PREFIX, name); +} + +void PlatformEmbeddedFileWriterGeneric::AlignToCodeAlignment() { + fprintf(fp_, ".balign 32\n"); +} + +void PlatformEmbeddedFileWriterGeneric::AlignToDataAlignment() { + // On Windows ARM64, s390, PPC and possibly more platforms, aligned load + // instructions are used to retrieve v8_Default_embedded_blob_ and/or + // v8_Default_embedded_blob_size_. The generated instructions require the + // load target to be aligned at 8 bytes (2^3). + fprintf(fp_, ".balign 8\n"); +} + +void PlatformEmbeddedFileWriterGeneric::Comment(const char* string) { + fprintf(fp_, "// %s\n", string); +} + +void PlatformEmbeddedFileWriterGeneric::DeclareLabel(const char* name) { + fprintf(fp_, "%s%s:\n", SYMBOL_PREFIX, name); +} + +void PlatformEmbeddedFileWriterGeneric::SourceInfo(int fileid, + const char* filename, + int line) { + fprintf(fp_, ".loc %d %d\n", fileid, line); +} + +void PlatformEmbeddedFileWriterGeneric::DeclareFunctionBegin(const char* name) { + DeclareLabel(name); + + if (target_arch_ == EmbeddedTargetArch::kArm || + target_arch_ == EmbeddedTargetArch::kArm64) { + // ELF format binaries on ARM use ".type <function name>, %function" + // to create a DWARF subprogram entry. + fprintf(fp_, ".type %s, %%function\n", name); + } else { + // Other ELF Format binaries use ".type <function name>, @function" + // to create a DWARF subprogram entry. + fprintf(fp_, ".type %s, @function\n", name); + } +} + +void PlatformEmbeddedFileWriterGeneric::DeclareFunctionEnd(const char* name) {} + +int PlatformEmbeddedFileWriterGeneric::HexLiteral(uint64_t value) { + return fprintf(fp_, "0x%" PRIx64, value); +} + +void PlatformEmbeddedFileWriterGeneric::FilePrologue() {} + +void PlatformEmbeddedFileWriterGeneric::DeclareExternalFilename( + int fileid, const char* filename) { + // Replace any Windows style paths (backslashes) with forward + // slashes. + std::string fixed_filename(filename); + std::replace(fixed_filename.begin(), fixed_filename.end(), '\\', '/'); + fprintf(fp_, ".file %d \"%s\"\n", fileid, fixed_filename.c_str()); +} + +void PlatformEmbeddedFileWriterGeneric::FileEpilogue() {} + +int PlatformEmbeddedFileWriterGeneric::IndentedDataDirective( + DataDirective directive) { + return fprintf(fp_, " %s ", DirectiveAsString(directive)); +} + +#undef SYMBOL_PREFIX + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-generic.h b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-generic.h new file mode 100644 index 0000000000..0c76e7df88 --- /dev/null +++ b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-generic.h @@ -0,0 +1,63 @@ +// Copyright 2019 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. + +#ifndef V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_GENERIC_H_ +#define V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_GENERIC_H_ + +#include "src/base/macros.h" +#include "src/common/globals.h" // For V8_OS_WIN_X64 +#include "src/snapshot/embedded/platform-embedded-file-writer-base.h" + +namespace v8 { +namespace internal { + +class PlatformEmbeddedFileWriterGeneric + : public PlatformEmbeddedFileWriterBase { + public: + PlatformEmbeddedFileWriterGeneric(EmbeddedTargetArch target_arch, + EmbeddedTargetOs target_os) + : target_arch_(target_arch), target_os_(target_os) { + DCHECK(target_os_ == EmbeddedTargetOs::kChromeOS || + target_os_ == EmbeddedTargetOs::kFuchsia || + target_os_ == EmbeddedTargetOs::kGeneric); + } + + void SectionText() override; + void SectionData() override; + void SectionRoData() override; + + void AlignToCodeAlignment() override; + void AlignToDataAlignment() override; + + void DeclareUint32(const char* name, uint32_t value) override; + void DeclarePointerToSymbol(const char* name, const char* target) override; + + void DeclareLabel(const char* name) override; + + void SourceInfo(int fileid, const char* filename, int line) override; + void DeclareFunctionBegin(const char* name) override; + void DeclareFunctionEnd(const char* name) override; + + int HexLiteral(uint64_t value) override; + + void Comment(const char* string) override; + + void FilePrologue() override; + void DeclareExternalFilename(int fileid, const char* filename) override; + void FileEpilogue() override; + + int IndentedDataDirective(DataDirective directive) override; + + private: + void DeclareSymbolGlobal(const char* name); + + private: + const EmbeddedTargetArch target_arch_; + const EmbeddedTargetOs target_os_; +}; + +} // namespace internal +} // namespace v8 + +#endif // V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_GENERIC_H_ diff --git a/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-mac.cc b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-mac.cc new file mode 100644 index 0000000000..4be3c7ac6b --- /dev/null +++ b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-mac.cc @@ -0,0 +1,109 @@ +// Copyright 2019 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. + +#include "src/snapshot/embedded/platform-embedded-file-writer-mac.h" + +namespace v8 { +namespace internal { + +namespace { + +const char* DirectiveAsString(DataDirective directive) { + switch (directive) { + case kByte: + return ".byte"; + case kLong: + return ".long"; + case kQuad: + return ".quad"; + case kOcta: + return ".octa"; + } + UNREACHABLE(); +} + +} // namespace + +void PlatformEmbeddedFileWriterMac::SectionText() { fprintf(fp_, ".text\n"); } + +void PlatformEmbeddedFileWriterMac::SectionData() { fprintf(fp_, ".data\n"); } + +void PlatformEmbeddedFileWriterMac::SectionRoData() { + fprintf(fp_, ".const_data\n"); +} + +void PlatformEmbeddedFileWriterMac::DeclareUint32(const char* name, + uint32_t value) { + DeclareSymbolGlobal(name); + DeclareLabel(name); + IndentedDataDirective(kLong); + fprintf(fp_, "%d", value); + Newline(); +} + +void PlatformEmbeddedFileWriterMac::DeclarePointerToSymbol(const char* name, + const char* target) { + DeclareSymbolGlobal(name); + DeclareLabel(name); + fprintf(fp_, " %s _%s\n", DirectiveAsString(PointerSizeDirective()), target); +} + +void PlatformEmbeddedFileWriterMac::DeclareSymbolGlobal(const char* name) { + // TODO(jgruber): Investigate switching to .globl. Using .private_extern + // prevents something along the compilation chain from messing with the + // embedded blob. Using .global here causes embedded blob hash verification + // failures at runtime. + fprintf(fp_, ".private_extern _%s\n", name); +} + +void PlatformEmbeddedFileWriterMac::AlignToCodeAlignment() { + fprintf(fp_, ".balign 32\n"); +} + +void PlatformEmbeddedFileWriterMac::AlignToDataAlignment() { + fprintf(fp_, ".balign 8\n"); +} + +void PlatformEmbeddedFileWriterMac::Comment(const char* string) { + fprintf(fp_, "// %s\n", string); +} + +void PlatformEmbeddedFileWriterMac::DeclareLabel(const char* name) { + fprintf(fp_, "_%s:\n", name); +} + +void PlatformEmbeddedFileWriterMac::SourceInfo(int fileid, const char* filename, + int line) { + fprintf(fp_, ".loc %d %d\n", fileid, line); +} + +void PlatformEmbeddedFileWriterMac::DeclareFunctionBegin(const char* name) { + DeclareLabel(name); + + // TODO(mvstanton): Investigate the proper incantations to mark the label as + // a function on OSX. +} + +void PlatformEmbeddedFileWriterMac::DeclareFunctionEnd(const char* name) {} + +int PlatformEmbeddedFileWriterMac::HexLiteral(uint64_t value) { + return fprintf(fp_, "0x%" PRIx64, value); +} + +void PlatformEmbeddedFileWriterMac::FilePrologue() {} + +void PlatformEmbeddedFileWriterMac::DeclareExternalFilename( + int fileid, const char* filename) { + fprintf(fp_, ".file %d \"%s\"\n", fileid, filename); +} + +void PlatformEmbeddedFileWriterMac::FileEpilogue() {} + +int PlatformEmbeddedFileWriterMac::IndentedDataDirective( + DataDirective directive) { + return fprintf(fp_, " %s ", DirectiveAsString(directive)); +} + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-mac.h b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-mac.h new file mode 100644 index 0000000000..4f2cd3d6ae --- /dev/null +++ b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-mac.h @@ -0,0 +1,61 @@ +// Copyright 2019 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. + +#ifndef V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_MAC_H_ +#define V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_MAC_H_ + +#include "src/base/macros.h" +#include "src/snapshot/embedded/platform-embedded-file-writer-base.h" + +namespace v8 { +namespace internal { + +class PlatformEmbeddedFileWriterMac : public PlatformEmbeddedFileWriterBase { + public: + PlatformEmbeddedFileWriterMac(EmbeddedTargetArch target_arch, + EmbeddedTargetOs target_os) + : target_arch_(target_arch), target_os_(target_os) { + USE(target_arch_); + USE(target_os_); + DCHECK_EQ(target_os_, EmbeddedTargetOs::kMac); + } + + void SectionText() override; + void SectionData() override; + void SectionRoData() override; + + void AlignToCodeAlignment() override; + void AlignToDataAlignment() override; + + void DeclareUint32(const char* name, uint32_t value) override; + void DeclarePointerToSymbol(const char* name, const char* target) override; + + void DeclareLabel(const char* name) override; + + void SourceInfo(int fileid, const char* filename, int line) override; + void DeclareFunctionBegin(const char* name) override; + void DeclareFunctionEnd(const char* name) override; + + int HexLiteral(uint64_t value) override; + + void Comment(const char* string) override; + + void FilePrologue() override; + void DeclareExternalFilename(int fileid, const char* filename) override; + void FileEpilogue() override; + + int IndentedDataDirective(DataDirective directive) override; + + private: + void DeclareSymbolGlobal(const char* name); + + private: + const EmbeddedTargetArch target_arch_; + const EmbeddedTargetOs target_os_; +}; + +} // namespace internal +} // namespace v8 + +#endif // V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_MAC_H_ diff --git a/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-win.cc b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-win.cc new file mode 100644 index 0000000000..69457e11a5 --- /dev/null +++ b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-win.cc @@ -0,0 +1,615 @@ +// Copyright 2019 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. + +#include "src/snapshot/embedded/platform-embedded-file-writer-win.h" + +#include <algorithm> + +#include "src/common/globals.h" // For V8_OS_WIN_X64. + +#if defined(V8_OS_WIN_X64) +#include "src/builtins/builtins.h" +#include "src/diagnostics/unwinding-info-win64.h" +#include "src/snapshot/embedded/embedded-data.h" +#endif + +namespace v8 { +namespace internal { + +// V8_CC_MSVC is true for both MSVC and clang on windows. clang can handle +// __asm__-style inline assembly but MSVC cannot, and thus we need a more +// precise compiler detection that can distinguish between the two. clang on +// windows sets both __clang__ and _MSC_VER, MSVC sets only _MSC_VER. +#if defined(_MSC_VER) && !defined(__clang__) +#define V8_COMPILER_IS_MSVC +#endif + +// MSVC uses MASM for x86 and x64, while it has a ARMASM for ARM32 and +// ARMASM64 for ARM64. Since ARMASM and ARMASM64 accept a slightly tweaked +// version of ARM assembly language, they are referred to together in Visual +// Studio project files as MARMASM. +// +// ARM assembly language docs: +// http://infocenter.arm.com/help/topic/com.arm.doc.dui0802b/index.html +// Microsoft ARM assembler and assembly language docs: +// https://docs.microsoft.com/en-us/cpp/assembler/arm/arm-assembler-reference +#if defined(V8_COMPILER_IS_MSVC) +#if defined(V8_TARGET_ARCH_ARM64) || defined(V8_TARGET_ARCH_ARM) +#define V8_ASSEMBLER_IS_MARMASM +#elif defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64) +#define V8_ASSEMBLER_IS_MASM +#else +#error Unknown Windows assembler target architecture. +#endif +#endif + +// Name mangling. +// Symbols are prefixed with an underscore on 32-bit architectures. +#if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_ARM64) +#define SYMBOL_PREFIX "_" +#else +#define SYMBOL_PREFIX "" +#endif + +// Notes: +// +// Cross-bitness builds are unsupported. It's thus safe to detect bitness +// through compile-time defines. +// +// Cross-compiler builds (e.g. with mixed use of clang / MSVC) are likewise +// unsupported and hence the compiler can also be detected through compile-time +// defines. + +namespace { + +const char* DirectiveAsString(DataDirective directive) { +#if defined(V8_ASSEMBLER_IS_MASM) + switch (directive) { + case kByte: + return "BYTE"; + case kLong: + return "DWORD"; + case kQuad: + return "QWORD"; + default: + UNREACHABLE(); + } +#elif defined(V8_ASSEMBLER_IS_MARMASM) + switch (directive) { + case kByte: + return "DCB"; + case kLong: + return "DCDU"; + case kQuad: + return "DCQU"; + default: + UNREACHABLE(); + } +#else + switch (directive) { + case kByte: + return ".byte"; + case kLong: + return ".long"; + case kQuad: + return ".quad"; + case kOcta: + return ".octa"; + } + UNREACHABLE(); +#endif +} + +#if defined(V8_OS_WIN_X64) + +void WriteUnwindInfoEntry(PlatformEmbeddedFileWriterWin* w, + const char* unwind_info_symbol, + const char* embedded_blob_data_symbol, + uint64_t rva_start, uint64_t rva_end) { + w->DeclareRvaToSymbol(embedded_blob_data_symbol, rva_start); + w->DeclareRvaToSymbol(embedded_blob_data_symbol, rva_end); + w->DeclareRvaToSymbol(unwind_info_symbol); +} + +void EmitUnwindData(PlatformEmbeddedFileWriterWin* w, + const char* unwind_info_symbol, + const char* embedded_blob_data_symbol, + const EmbeddedData* blob, + const win64_unwindinfo::BuiltinUnwindInfo* unwind_infos) { + // Emit an UNWIND_INFO (XDATA) struct, which contains the unwinding + // information that is used for all builtin functions. + DCHECK(win64_unwindinfo::CanEmitUnwindInfoForBuiltins()); + w->Comment("xdata for all the code in the embedded blob."); + w->DeclareExternalFunction(CRASH_HANDLER_FUNCTION_NAME_STRING); + + w->StartXdataSection(); + { + w->DeclareLabel(unwind_info_symbol); + + std::vector<uint8_t> xdata = + win64_unwindinfo::GetUnwindInfoForBuiltinFunctions(); + DCHECK(!xdata.empty()); + + w->IndentedDataDirective(kByte); + for (size_t i = 0; i < xdata.size(); i++) { + if (i > 0) fprintf(w->fp(), ","); + w->HexLiteral(xdata[i]); + } + w->Newline(); + + w->Comment(" ExceptionHandler"); + w->DeclareRvaToSymbol(CRASH_HANDLER_FUNCTION_NAME_STRING); + } + w->EndXdataSection(); + w->Newline(); + + // Emit a RUNTIME_FUNCTION (PDATA) entry for each builtin function, as + // documented here: + // https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64. + w->Comment( + "pdata for all the code in the embedded blob (structs of type " + "RUNTIME_FUNCTION)."); + w->Comment(" BeginAddress"); + w->Comment(" EndAddress"); + w->Comment(" UnwindInfoAddress"); + w->StartPdataSection(); + { + Address prev_builtin_end_offset = 0; + for (int i = 0; i < Builtins::builtin_count; i++) { + // Some builtins are leaf functions from the point of view of Win64 stack + // walking: they do not move the stack pointer and do not require a PDATA + // entry because the return address can be retrieved from [rsp]. + if (!blob->ContainsBuiltin(i)) continue; + if (unwind_infos[i].is_leaf_function()) continue; + + uint64_t builtin_start_offset = blob->InstructionStartOfBuiltin(i) - + reinterpret_cast<Address>(blob->data()); + uint32_t builtin_size = blob->InstructionSizeOfBuiltin(i); + + const std::vector<int>& xdata_desc = unwind_infos[i].fp_offsets(); + if (xdata_desc.empty()) { + // Some builtins do not have any "push rbp - mov rbp, rsp" instructions + // to start a stack frame. We still emit a PDATA entry as if they had, + // relying on the fact that we can find the previous frame address from + // rbp in most cases. Note that since the function does not really start + // with a 'push rbp' we need to specify the start RVA in the PDATA entry + // a few bytes before the beginning of the function, if it does not + // overlap the end of the previous builtin. + WriteUnwindInfoEntry( + w, unwind_info_symbol, embedded_blob_data_symbol, + std::max(prev_builtin_end_offset, + builtin_start_offset - win64_unwindinfo::kRbpPrefixLength), + builtin_start_offset + builtin_size); + } else { + // Some builtins have one or more "push rbp - mov rbp, rsp" sequences, + // but not necessarily at the beginning of the function. In this case + // we want to yield a PDATA entry for each block of instructions that + // emit an rbp frame. If the function does not start with 'push rbp' + // we also emit a PDATA entry for the initial block of code up to the + // first 'push rbp', like in the case above. + if (xdata_desc[0] > 0) { + WriteUnwindInfoEntry(w, unwind_info_symbol, embedded_blob_data_symbol, + std::max(prev_builtin_end_offset, + builtin_start_offset - + win64_unwindinfo::kRbpPrefixLength), + builtin_start_offset + xdata_desc[0]); + } + + for (size_t j = 0; j < xdata_desc.size(); j++) { + int chunk_start = xdata_desc[j]; + int chunk_end = + (j < xdata_desc.size() - 1) ? xdata_desc[j + 1] : builtin_size; + WriteUnwindInfoEntry(w, unwind_info_symbol, embedded_blob_data_symbol, + builtin_start_offset + chunk_start, + builtin_start_offset + chunk_end); + } + } + + prev_builtin_end_offset = builtin_start_offset + builtin_size; + w->Newline(); + } + } + w->EndPdataSection(); + w->Newline(); +} +#endif // defined(V8_OS_WIN_X64) + +} // namespace + +void PlatformEmbeddedFileWriterWin::MaybeEmitUnwindData( + const char* unwind_info_symbol, const char* embedded_blob_data_symbol, + const EmbeddedData* blob, const void* unwind_infos) { +#if defined(V8_OS_WIN_X64) + if (win64_unwindinfo::CanEmitUnwindInfoForBuiltins()) { + EmitUnwindData(this, unwind_info_symbol, embedded_blob_data_symbol, blob, + reinterpret_cast<const win64_unwindinfo::BuiltinUnwindInfo*>( + unwind_infos)); + } +#endif // defined(V8_OS_WIN_X64) +} + +// Windows, MSVC, not arm/arm64. +// ----------------------------------------------------------------------------- + +#if defined(V8_ASSEMBLER_IS_MASM) + +// For MSVC builds we emit assembly in MASM syntax. +// See https://docs.microsoft.com/en-us/cpp/assembler/masm/directives-reference. + +void PlatformEmbeddedFileWriterWin::SectionText() { fprintf(fp_, ".CODE\n"); } + +void PlatformEmbeddedFileWriterWin::SectionData() { fprintf(fp_, ".DATA\n"); } + +void PlatformEmbeddedFileWriterWin::SectionRoData() { + fprintf(fp_, ".CONST\n"); +} + +void PlatformEmbeddedFileWriterWin::DeclareUint32(const char* name, + uint32_t value) { + DeclareSymbolGlobal(name); + fprintf(fp_, "%s%s %s %d\n", SYMBOL_PREFIX, name, DirectiveAsString(kLong), + value); +} + +void PlatformEmbeddedFileWriterWin::DeclarePointerToSymbol(const char* name, + const char* target) { + DeclareSymbolGlobal(name); + fprintf(fp_, "%s%s %s %s%s\n", SYMBOL_PREFIX, name, + DirectiveAsString(PointerSizeDirective()), SYMBOL_PREFIX, target); +} + +void PlatformEmbeddedFileWriterWin::StartPdataSection() { + fprintf(fp_, "OPTION DOTNAME\n"); + fprintf(fp_, ".pdata SEGMENT DWORD READ ''\n"); +} + +void PlatformEmbeddedFileWriterWin::EndPdataSection() { + fprintf(fp_, ".pdata ENDS\n"); +} + +void PlatformEmbeddedFileWriterWin::StartXdataSection() { + fprintf(fp_, "OPTION DOTNAME\n"); + fprintf(fp_, ".xdata SEGMENT DWORD READ ''\n"); +} + +void PlatformEmbeddedFileWriterWin::EndXdataSection() { + fprintf(fp_, ".xdata ENDS\n"); +} + +void PlatformEmbeddedFileWriterWin::DeclareExternalFunction(const char* name) { + fprintf(fp_, "EXTERN %s : PROC\n", name); +} + +void PlatformEmbeddedFileWriterWin::DeclareRvaToSymbol(const char* name, + uint64_t offset) { + if (offset > 0) { + fprintf(fp_, "DD IMAGEREL %s+%llu\n", name, offset); + } else { + fprintf(fp_, "DD IMAGEREL %s\n", name); + } +} + +void PlatformEmbeddedFileWriterWin::DeclareSymbolGlobal(const char* name) { + fprintf(fp_, "PUBLIC %s%s\n", SYMBOL_PREFIX, name); +} + +void PlatformEmbeddedFileWriterWin::AlignToCodeAlignment() { + // Diverges from other platforms due to compile error + // 'invalid combination with segment alignment'. + fprintf(fp_, "ALIGN 4\n"); +} + +void PlatformEmbeddedFileWriterWin::AlignToDataAlignment() { + fprintf(fp_, "ALIGN 4\n"); +} + +void PlatformEmbeddedFileWriterWin::Comment(const char* string) { + fprintf(fp_, "; %s\n", string); +} + +void PlatformEmbeddedFileWriterWin::DeclareLabel(const char* name) { + fprintf(fp_, "%s%s LABEL %s\n", SYMBOL_PREFIX, name, + DirectiveAsString(kByte)); +} + +void PlatformEmbeddedFileWriterWin::SourceInfo(int fileid, const char* filename, + int line) { + // TODO(mvstanton): output source information for MSVC. + // Its syntax is #line <line> "<filename>" +} + +void PlatformEmbeddedFileWriterWin::DeclareFunctionBegin(const char* name) { + fprintf(fp_, "%s%s PROC\n", SYMBOL_PREFIX, name); +} + +void PlatformEmbeddedFileWriterWin::DeclareFunctionEnd(const char* name) { + fprintf(fp_, "%s%s ENDP\n", SYMBOL_PREFIX, name); +} + +int PlatformEmbeddedFileWriterWin::HexLiteral(uint64_t value) { + return fprintf(fp_, "0%" PRIx64 "h", value); +} + +void PlatformEmbeddedFileWriterWin::FilePrologue() { + if (target_arch_ != EmbeddedTargetArch::kX64) { + fprintf(fp_, ".MODEL FLAT\n"); + } +} + +void PlatformEmbeddedFileWriterWin::DeclareExternalFilename( + int fileid, const char* filename) {} + +void PlatformEmbeddedFileWriterWin::FileEpilogue() { fprintf(fp_, "END\n"); } + +int PlatformEmbeddedFileWriterWin::IndentedDataDirective( + DataDirective directive) { + return fprintf(fp_, " %s ", DirectiveAsString(directive)); +} + +// Windows, MSVC, arm/arm64. +// ----------------------------------------------------------------------------- + +#elif defined(V8_ASSEMBLER_IS_MARMASM) + +// The AARCH64 ABI requires instructions be 4-byte-aligned and Windows does +// not have a stricter alignment requirement (see the TEXTAREA macro of +// kxarm64.h in the Windows SDK), so code is 4-byte-aligned. +// The data fields in the emitted assembly tend to be accessed with 8-byte +// LDR instructions, so data is 8-byte-aligned. +// +// armasm64's warning A4228 states +// Alignment value exceeds AREA alignment; alignment not guaranteed +// To ensure that ALIGN directives are honored, their values are defined as +// equal to their corresponding AREA's ALIGN attributes. + +#define ARM64_DATA_ALIGNMENT_POWER (3) +#define ARM64_DATA_ALIGNMENT (1 << ARM64_DATA_ALIGNMENT_POWER) +#define ARM64_CODE_ALIGNMENT_POWER (2) +#define ARM64_CODE_ALIGNMENT (1 << ARM64_CODE_ALIGNMENT_POWER) + +void PlatformEmbeddedFileWriterWin::SectionText() { + fprintf(fp_, " AREA |.text|, CODE, ALIGN=%d, READONLY\n", + ARM64_CODE_ALIGNMENT_POWER); +} + +void PlatformEmbeddedFileWriterWin::SectionData() { + fprintf(fp_, " AREA |.data|, DATA, ALIGN=%d, READWRITE\n", + ARM64_DATA_ALIGNMENT_POWER); +} + +void PlatformEmbeddedFileWriterWin::SectionRoData() { + fprintf(fp_, " AREA |.rodata|, DATA, ALIGN=%d, READONLY\n", + ARM64_DATA_ALIGNMENT_POWER); +} + +void PlatformEmbeddedFileWriterWin::DeclareUint32(const char* name, + uint32_t value) { + DeclareSymbolGlobal(name); + fprintf(fp_, "%s%s %s %d\n", SYMBOL_PREFIX, name, DirectiveAsString(kLong), + value); +} + +void PlatformEmbeddedFileWriterWin::DeclarePointerToSymbol(const char* name, + const char* target) { + DeclareSymbolGlobal(name); + fprintf(fp_, "%s%s %s %s%s\n", SYMBOL_PREFIX, name, + DirectiveAsString(PointerSizeDirective()), SYMBOL_PREFIX, target); +} + +void PlatformEmbeddedFileWriterWin::DeclareSymbolGlobal(const char* name) { + fprintf(fp_, " EXPORT %s%s\n", SYMBOL_PREFIX, name); +} + +void PlatformEmbeddedFileWriterWin::AlignToCodeAlignment() { + fprintf(fp_, " ALIGN %d\n", ARM64_CODE_ALIGNMENT); +} + +void PlatformEmbeddedFileWriterWin::AlignToDataAlignment() { + fprintf(fp_, " ALIGN %d\n", ARM64_DATA_ALIGNMENT); +} + +void PlatformEmbeddedFileWriterWin::Comment(const char* string) { + fprintf(fp_, "; %s\n", string); +} + +void PlatformEmbeddedFileWriterWin::DeclareLabel(const char* name) { + fprintf(fp_, "%s%s\n", SYMBOL_PREFIX, name); +} + +void PlatformEmbeddedFileWriterWin::SourceInfo(int fileid, const char* filename, + int line) { + // TODO(mvstanton): output source information for MSVC. + // Its syntax is #line <line> "<filename>" +} + +void PlatformEmbeddedFileWriterWin::DeclareFunctionBegin(const char* name) { + fprintf(fp_, "%s%s FUNCTION\n", SYMBOL_PREFIX, name); +} + +void PlatformEmbeddedFileWriterWin::DeclareFunctionEnd(const char* name) { + fprintf(fp_, " ENDFUNC\n"); +} + +int PlatformEmbeddedFileWriterWin::HexLiteral(uint64_t value) { + return fprintf(fp_, "0x%" PRIx64, value); +} + +void PlatformEmbeddedFileWriterWin::FilePrologue() {} + +void PlatformEmbeddedFileWriterWin::DeclareExternalFilename( + int fileid, const char* filename) {} + +void PlatformEmbeddedFileWriterWin::FileEpilogue() { fprintf(fp_, " END\n"); } + +int PlatformEmbeddedFileWriterWin::IndentedDataDirective( + DataDirective directive) { + return fprintf(fp_, " %s ", DirectiveAsString(directive)); +} + +#undef ARM64_DATA_ALIGNMENT_POWER +#undef ARM64_DATA_ALIGNMENT +#undef ARM64_CODE_ALIGNMENT_POWER +#undef ARM64_CODE_ALIGNMENT + +// All Windows builds without MSVC. +// ----------------------------------------------------------------------------- + +#else + +void PlatformEmbeddedFileWriterWin::SectionText() { + fprintf(fp_, ".section .text\n"); +} + +void PlatformEmbeddedFileWriterWin::SectionData() { + fprintf(fp_, ".section .data\n"); +} + +void PlatformEmbeddedFileWriterWin::SectionRoData() { + fprintf(fp_, ".section .rdata\n"); +} + +void PlatformEmbeddedFileWriterWin::DeclareUint32(const char* name, + uint32_t value) { + DeclareSymbolGlobal(name); + DeclareLabel(name); + IndentedDataDirective(kLong); + fprintf(fp_, "%d", value); + Newline(); +} + +void PlatformEmbeddedFileWriterWin::DeclarePointerToSymbol(const char* name, + const char* target) { + DeclareSymbolGlobal(name); + DeclareLabel(name); + fprintf(fp_, " %s %s%s\n", DirectiveAsString(PointerSizeDirective()), + SYMBOL_PREFIX, target); +} + +void PlatformEmbeddedFileWriterWin::StartPdataSection() { + fprintf(fp_, ".section .pdata\n"); +} + +void PlatformEmbeddedFileWriterWin::EndPdataSection() {} + +void PlatformEmbeddedFileWriterWin::StartXdataSection() { + fprintf(fp_, ".section .xdata\n"); +} + +void PlatformEmbeddedFileWriterWin::EndXdataSection() {} + +void PlatformEmbeddedFileWriterWin::DeclareExternalFunction(const char* name) {} + +void PlatformEmbeddedFileWriterWin::DeclareRvaToSymbol(const char* name, + uint64_t offset) { + if (offset > 0) { + fprintf(fp_, ".rva %s + %" PRIu64 "\n", name, offset); + } else { + fprintf(fp_, ".rva %s\n", name); + } +} + +void PlatformEmbeddedFileWriterWin::DeclareSymbolGlobal(const char* name) { + fprintf(fp_, ".global %s%s\n", SYMBOL_PREFIX, name); +} + +void PlatformEmbeddedFileWriterWin::AlignToCodeAlignment() { + fprintf(fp_, ".balign 32\n"); +} + +void PlatformEmbeddedFileWriterWin::AlignToDataAlignment() { + // On Windows ARM64, s390, PPC and possibly more platforms, aligned load + // instructions are used to retrieve v8_Default_embedded_blob_ and/or + // v8_Default_embedded_blob_size_. The generated instructions require the + // load target to be aligned at 8 bytes (2^3). + fprintf(fp_, ".balign 8\n"); +} + +void PlatformEmbeddedFileWriterWin::Comment(const char* string) { + fprintf(fp_, "// %s\n", string); +} + +void PlatformEmbeddedFileWriterWin::DeclareLabel(const char* name) { + fprintf(fp_, "%s%s:\n", SYMBOL_PREFIX, name); +} + +void PlatformEmbeddedFileWriterWin::SourceInfo(int fileid, const char* filename, + int line) { + fprintf(fp_, ".loc %d %d\n", fileid, line); +} + +void PlatformEmbeddedFileWriterWin::DeclareFunctionBegin(const char* name) { + DeclareLabel(name); + + if (target_arch_ == EmbeddedTargetArch::kArm64) { + // Windows ARM64 assembly is in GAS syntax, but ".type" is invalid directive + // in PE/COFF for Windows. + } else { + // The directives for inserting debugging information on Windows come + // from the PE (Portable Executable) and COFF (Common Object File Format) + // standards. Documented here: + // https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format + // + // .scl 2 means StorageClass external. + // .type 32 means Type Representation Function. + fprintf(fp_, ".def %s%s; .scl 2; .type 32; .endef;\n", SYMBOL_PREFIX, name); + } +} + +void PlatformEmbeddedFileWriterWin::DeclareFunctionEnd(const char* name) {} + +int PlatformEmbeddedFileWriterWin::HexLiteral(uint64_t value) { + return fprintf(fp_, "0x%" PRIx64, value); +} + +void PlatformEmbeddedFileWriterWin::FilePrologue() {} + +void PlatformEmbeddedFileWriterWin::DeclareExternalFilename( + int fileid, const char* filename) { + // Replace any Windows style paths (backslashes) with forward + // slashes. + std::string fixed_filename(filename); + std::replace(fixed_filename.begin(), fixed_filename.end(), '\\', '/'); + fprintf(fp_, ".file %d \"%s\"\n", fileid, fixed_filename.c_str()); +} + +void PlatformEmbeddedFileWriterWin::FileEpilogue() {} + +int PlatformEmbeddedFileWriterWin::IndentedDataDirective( + DataDirective directive) { + return fprintf(fp_, " %s ", DirectiveAsString(directive)); +} + +#endif + +DataDirective PlatformEmbeddedFileWriterWin::ByteChunkDataDirective() const { +#if defined(V8_COMPILER_IS_MSVC) + // Windows MASM doesn't have an .octa directive, use QWORDs instead. + // Note: MASM *really* does not like large data streams. It takes over 5 + // minutes to assemble the ~350K lines of embedded.S produced when using + // BYTE directives in a debug build. QWORD produces roughly 120KLOC and + // reduces assembly time to ~40 seconds. Still terrible, but much better + // than before. See also: https://crbug.com/v8/8475. + return kQuad; +#else + return PlatformEmbeddedFileWriterBase::ByteChunkDataDirective(); +#endif +} + +int PlatformEmbeddedFileWriterWin::WriteByteChunk(const uint8_t* data) { +#if defined(V8_COMPILER_IS_MSVC) + DCHECK_EQ(ByteChunkDataDirective(), kQuad); + const uint64_t* quad_ptr = reinterpret_cast<const uint64_t*>(data); + return HexLiteral(*quad_ptr); +#else + return PlatformEmbeddedFileWriterBase::WriteByteChunk(data); +#endif +} + +#undef SYMBOL_PREFIX +#undef V8_ASSEMBLER_IS_MASM +#undef V8_ASSEMBLER_IS_MARMASM +#undef V8_COMPILER_IS_MSVC + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-win.h b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-win.h new file mode 100644 index 0000000000..376c6cc6ef --- /dev/null +++ b/deps/v8/src/snapshot/embedded/platform-embedded-file-writer-win.h @@ -0,0 +1,78 @@ +// Copyright 2019 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. + +#ifndef V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_WIN_H_ +#define V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_WIN_H_ + +#include "src/base/macros.h" +#include "src/snapshot/embedded/platform-embedded-file-writer-base.h" + +namespace v8 { +namespace internal { + +class PlatformEmbeddedFileWriterWin : public PlatformEmbeddedFileWriterBase { + public: + PlatformEmbeddedFileWriterWin(EmbeddedTargetArch target_arch, + EmbeddedTargetOs target_os) + : target_arch_(target_arch), target_os_(target_os) { + USE(target_os_); + DCHECK_EQ(target_os_, EmbeddedTargetOs::kWin); + } + + void SectionText() override; + void SectionData() override; + void SectionRoData() override; + + void AlignToCodeAlignment() override; + void AlignToDataAlignment() override; + + void DeclareUint32(const char* name, uint32_t value) override; + void DeclarePointerToSymbol(const char* name, const char* target) override; + + void DeclareLabel(const char* name) override; + + void SourceInfo(int fileid, const char* filename, int line) override; + void DeclareFunctionBegin(const char* name) override; + void DeclareFunctionEnd(const char* name) override; + + int HexLiteral(uint64_t value) override; + + void Comment(const char* string) override; + + void FilePrologue() override; + void DeclareExternalFilename(int fileid, const char* filename) override; + void FileEpilogue() override; + + int IndentedDataDirective(DataDirective directive) override; + + DataDirective ByteChunkDataDirective() const override; + int WriteByteChunk(const uint8_t* data) override; + + void StartPdataSection(); + void EndPdataSection(); + void StartXdataSection(); + void EndXdataSection(); + void DeclareExternalFunction(const char* name); + + // Emits an RVA (address relative to the module load address) specified as an + // offset from a given symbol. + void DeclareRvaToSymbol(const char* name, uint64_t offset = 0); + + void MaybeEmitUnwindData(const char* unwind_info_symbol, + const char* embedded_blob_data_symbol, + const EmbeddedData* blob, + const void* unwind_infos) override; + + private: + void DeclareSymbolGlobal(const char* name); + + private: + const EmbeddedTargetArch target_arch_; + const EmbeddedTargetOs target_os_; +}; + +} // namespace internal +} // namespace v8 + +#endif // V8_SNAPSHOT_EMBEDDED_PLATFORM_EMBEDDED_FILE_WRITER_WIN_H_ diff --git a/deps/v8/src/snapshot/mksnapshot.cc b/deps/v8/src/snapshot/mksnapshot.cc index f44f71e145..6bf198230f 100644 --- a/deps/v8/src/snapshot/mksnapshot.cc +++ b/deps/v8/src/snapshot/mksnapshot.cc @@ -8,16 +8,16 @@ #include <iomanip> #include "include/libplatform/libplatform.h" -#include "src/assembler-arch.h" #include "src/base/platform/platform.h" -#include "src/flags.h" -#include "src/msan.h" -#include "src/snapshot/embedded-file-writer.h" +#include "src/codegen/assembler-arch.h" +#include "src/codegen/source-position-table.h" +#include "src/flags/flags.h" +#include "src/sanitizer/msan.h" +#include "src/snapshot/embedded/embedded-file-writer.h" #include "src/snapshot/natives.h" #include "src/snapshot/partial-serializer.h" #include "src/snapshot/snapshot.h" #include "src/snapshot/startup-serializer.h" -#include "src/source-position-table.h" namespace { @@ -70,7 +70,7 @@ class SnapshotFileWriter { static void WriteSnapshotFilePrefix(FILE* fp) { fprintf(fp, "// Autogenerated snapshot file. Do not edit.\n\n"); - fprintf(fp, "#include \"src/v8.h\"\n"); + fprintf(fp, "#include \"src/init/v8.h\"\n"); fprintf(fp, "#include \"src/base/platform/platform.h\"\n\n"); fprintf(fp, "#include \"src/snapshot/snapshot.h\"\n\n"); fprintf(fp, "namespace v8 {\n"); @@ -87,7 +87,8 @@ class SnapshotFileWriter { static void WriteSnapshotFileData(FILE* fp, const i::Vector<const i::byte>& blob) { - fprintf(fp, "static const byte blob_data[] = {\n"); + fprintf(fp, + "alignas(kPointerAlignment) static const byte blob_data[] = {\n"); WriteBinaryContentsAsCArray(fp, blob); fprintf(fp, "};\n"); fprintf(fp, "static const int blob_size = %d;\n", blob.length()); @@ -143,100 +144,37 @@ char* GetExtraCode(char* filename, const char* description) { return chars; } -bool RunExtraCode(v8::Isolate* isolate, v8::Local<v8::Context> context, - const char* utf8_source, const char* name) { +v8::StartupData CreateSnapshotDataBlob(v8::Isolate* isolate, + const char* embedded_source) { v8::base::ElapsedTimer timer; timer.Start(); - v8::Context::Scope context_scope(context); - v8::TryCatch try_catch(isolate); - v8::Local<v8::String> source_string; - if (!v8::String::NewFromUtf8(isolate, utf8_source, v8::NewStringType::kNormal) - .ToLocal(&source_string)) { - return false; - } - v8::Local<v8::String> resource_name = - v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kNormal) - .ToLocalChecked(); - v8::ScriptOrigin origin(resource_name); - v8::ScriptCompiler::Source source(source_string, origin); - v8::Local<v8::Script> script; - if (!v8::ScriptCompiler::Compile(context, &source).ToLocal(&script)) - return false; - if (script->Run(context).IsEmpty()) return false; - if (i::FLAG_profile_deserialization) { - i::PrintF("Executing custom snapshot script %s took %0.3f ms\n", name, - timer.Elapsed().InMillisecondsF()); - } - timer.Stop(); - CHECK(!try_catch.HasCaught()); - return true; -} -v8::StartupData CreateSnapshotDataBlob(v8::SnapshotCreator* snapshot_creator, - const char* script_source = nullptr) { - // Create a new isolate and a new context from scratch, optionally run - // a script to embed, and serialize to create a snapshot blob. - v8::StartupData result = {nullptr, 0}; - v8::base::ElapsedTimer timer; - timer.Start(); - { - v8::Isolate* isolate = snapshot_creator->GetIsolate(); - { - v8::HandleScope scope(isolate); - v8::Local<v8::Context> context = v8::Context::New(isolate); - if (script_source != nullptr && - !RunExtraCode(isolate, context, script_source, "<embedded>")) { - return result; - } - snapshot_creator->SetDefaultContext(context); - } - result = snapshot_creator->CreateBlob( - v8::SnapshotCreator::FunctionCodeHandling::kClear); - } + v8::StartupData result = i::CreateSnapshotDataBlobInternal( + v8::SnapshotCreator::FunctionCodeHandling::kClear, embedded_source, + isolate); if (i::FLAG_profile_deserialization) { i::PrintF("Creating snapshot took %0.3f ms\n", timer.Elapsed().InMillisecondsF()); } + timer.Stop(); return result; } -v8::StartupData WarmUpSnapshotDataBlob(v8::SnapshotCreator* snapshot_creator, +v8::StartupData WarmUpSnapshotDataBlob(v8::StartupData cold_snapshot_blob, const char* warmup_source) { - CHECK_NOT_NULL(warmup_source); - // Use following steps to create a warmed up snapshot blob from a cold one: - // - Create a new isolate from the cold snapshot. - // - Create a new context to run the warmup script. This will trigger - // compilation of executed functions. - // - Create a new context. This context will be unpolluted. - // - Serialize the isolate and the second context into a new snapshot blob. - v8::StartupData result = {nullptr, 0}; v8::base::ElapsedTimer timer; timer.Start(); - { - v8::Isolate* isolate = snapshot_creator->GetIsolate(); - { - v8::HandleScope scope(isolate); - v8::Local<v8::Context> context = v8::Context::New(isolate); - if (!RunExtraCode(isolate, context, warmup_source, "<warm-up>")) { - return result; - } - } - { - v8::HandleScope handle_scope(isolate); - isolate->ContextDisposedNotification(false); - v8::Local<v8::Context> context = v8::Context::New(isolate); - snapshot_creator->SetDefaultContext(context); - } - result = snapshot_creator->CreateBlob( - v8::SnapshotCreator::FunctionCodeHandling::kKeep); - } + + v8::StartupData result = + i::WarmUpSnapshotDataBlobInternal(cold_snapshot_blob, warmup_source); if (i::FLAG_profile_deserialization) { i::PrintF("Warming up snapshot took %0.3f ms\n", timer.Elapsed().InMillisecondsF()); } + timer.Stop(); return result; } @@ -301,9 +239,9 @@ int main(int argc, char** argv) { i::EmbeddedFileWriter embedded_writer; embedded_writer.SetEmbeddedFile(i::FLAG_embedded_src); - if (i::FLAG_embedded_variant != nullptr) { - embedded_writer.SetEmbeddedVariant(i::FLAG_embedded_variant); - } + embedded_writer.SetEmbeddedVariant(i::FLAG_embedded_variant); + embedded_writer.SetTargetArch(i::FLAG_target_arch); + embedded_writer.SetTargetOs(i::FLAG_target_os); std::unique_ptr<char> embed_script( GetExtraCode(argc >= 2 ? argv[1] : nullptr, "embedding")); @@ -331,18 +269,18 @@ int main(int argc, char** argv) { // to be written out if builtins are embedded. i_isolate->RegisterEmbeddedFileWriter(&embedded_writer); } - v8::SnapshotCreator snapshot_creator(isolate); + blob = CreateSnapshotDataBlob(isolate, embed_script.get()); if (i::FLAG_embedded_builtins) { + // At this point, the Isolate has been torn down but the embedded blob + // is still alive (we called DisableEmbeddedBlobRefcounting above). + // That's fine as far as the embedded file writer is concerned. WriteEmbeddedFile(&embedded_writer); } - blob = CreateSnapshotDataBlob(&snapshot_creator, embed_script.get()); } if (warmup_script) { - CHECK(blob.raw_size > 0 && blob.data != nullptr); v8::StartupData cold = blob; - v8::SnapshotCreator snapshot_creator(nullptr, &cold); - blob = WarmUpSnapshotDataBlob(&snapshot_creator, warmup_script.get()); + blob = WarmUpSnapshotDataBlob(cold, warmup_script.get()); delete[] cold.data; } diff --git a/deps/v8/src/snapshot/natives-common.cc b/deps/v8/src/snapshot/natives-common.cc index 4cb7b5f0da..321b74b45c 100644 --- a/deps/v8/src/snapshot/natives-common.cc +++ b/deps/v8/src/snapshot/natives-common.cc @@ -5,7 +5,7 @@ // The common functionality when building with internal or external natives. #include "src/heap/heap.h" -#include "src/objects-inl.h" +#include "src/objects/objects-inl.h" #include "src/snapshot/natives.h" namespace v8 { @@ -19,7 +19,7 @@ NativesExternalStringResource::NativesExternalStringResource(NativeType type, CHECK_EQ(EXTRAS, type_); DCHECK(index < ExtraNatives::GetBuiltinsCount()); source = ExtraNatives::GetScriptSource(index); - data_ = source.start(); + data_ = source.begin(); length_ = source.length(); } diff --git a/deps/v8/src/snapshot/natives-external.cc b/deps/v8/src/snapshot/natives-external.cc index c9177bbc99..fe67f33087 100644 --- a/deps/v8/src/snapshot/natives-external.cc +++ b/deps/v8/src/snapshot/natives-external.cc @@ -6,7 +6,7 @@ #include "src/base/logging.h" #include "src/snapshot/snapshot-source-sink.h" -#include "src/vector.h" +#include "src/utils/vector.h" #ifndef V8_USE_EXTERNAL_STARTUP_DATA #error natives-external.cc is used only for the external snapshot build. @@ -44,7 +44,7 @@ class NativesStore { for (int i = 0; i < static_cast<int>(native_ids_.size()); ++i) { int native_id_length = native_ids_[i].length(); if ((static_cast<int>(strlen(id)) == native_id_length) && - (strncmp(id, native_ids_[i].start(), native_id_length) == 0)) { + (strncmp(id, native_ids_[i].begin(), native_id_length) == 0)) { return i; } } @@ -76,9 +76,9 @@ class NativesStore { const char extension[] = ".js"; Vector<char> name(Vector<char>::New(id_length + sizeof(native) - 1 + sizeof(extension) - 1)); - memcpy(name.start(), native, sizeof(native) - 1); - memcpy(name.start() + sizeof(native) - 1, id, id_length); - memcpy(name.start() + sizeof(native) - 1 + id_length, extension, + memcpy(name.begin(), native, sizeof(native) - 1); + memcpy(name.begin() + sizeof(native) - 1, id, id_length); + memcpy(name.begin() + sizeof(native) - 1 + id_length, extension, sizeof(extension) - 1); return Vector<const char>::cast(name); } diff --git a/deps/v8/src/snapshot/natives.h b/deps/v8/src/snapshot/natives.h index 76b8bf1bde..f294d33b5c 100644 --- a/deps/v8/src/snapshot/natives.h +++ b/deps/v8/src/snapshot/natives.h @@ -6,8 +6,8 @@ #define V8_SNAPSHOT_NATIVES_H_ #include "include/v8.h" -#include "src/objects.h" -#include "src/vector.h" +#include "src/utils/vector.h" +#include "src/objects/objects.h" namespace v8 { class StartupData; } // Forward declaration. diff --git a/deps/v8/src/snapshot/object-deserializer.cc b/deps/v8/src/snapshot/object-deserializer.cc index 44b7088380..63a0cfca17 100644 --- a/deps/v8/src/snapshot/object-deserializer.cc +++ b/deps/v8/src/snapshot/object-deserializer.cc @@ -4,11 +4,11 @@ #include "src/snapshot/object-deserializer.h" -#include "src/assembler-inl.h" +#include "src/codegen/assembler-inl.h" +#include "src/execution/isolate.h" #include "src/heap/heap-inl.h" -#include "src/isolate.h" -#include "src/objects.h" #include "src/objects/allocation-site-inl.h" +#include "src/objects/objects.h" #include "src/objects/slots.h" #include "src/snapshot/code-serializer.h" @@ -61,8 +61,8 @@ void ObjectDeserializer::FlushICache() { for (Code code : new_code_objects()) { // Record all references to embedded objects in the new code object. WriteBarrierForCode(code); - FlushInstructionCache(code->raw_instruction_start(), - code->raw_instruction_size()); + FlushInstructionCache(code.raw_instruction_start(), + code.raw_instruction_size()); } } @@ -73,8 +73,6 @@ void ObjectDeserializer::CommitPostProcessedObjects() { for (Handle<String> string : new_internalized_strings()) { DisallowHeapAllocation no_gc; StringTableInsertionKey key(*string); - DCHECK( - StringTable::ForwardStringIfExists(isolate(), &key, *string).is_null()); StringTable::AddKeyNoResize(isolate(), &key); } @@ -98,14 +96,14 @@ void ObjectDeserializer::LinkAllocationSites() { // Allocation sites are present in the snapshot, and must be linked into // a list at deserialization time. for (AllocationSite site : new_allocation_sites()) { - if (!site->HasWeakNext()) continue; + if (!site.HasWeakNext()) continue; // TODO(mvstanton): consider treating the heap()->allocation_sites_list() // as a (weak) root. If this root is relocated correctly, this becomes // unnecessary. if (heap->allocation_sites_list() == Smi::kZero) { - site->set_weak_next(ReadOnlyRoots(heap).undefined_value()); + site.set_weak_next(ReadOnlyRoots(heap).undefined_value()); } else { - site->set_weak_next(heap->allocation_sites_list()); + site.set_weak_next(heap->allocation_sites_list()); } heap->set_allocation_sites_list(site); } diff --git a/deps/v8/src/snapshot/partial-deserializer.cc b/deps/v8/src/snapshot/partial-deserializer.cc index 4dd25980e8..9b56f129df 100644 --- a/deps/v8/src/snapshot/partial-deserializer.cc +++ b/deps/v8/src/snapshot/partial-deserializer.cc @@ -4,7 +4,7 @@ #include "src/snapshot/partial-deserializer.h" -#include "src/api-inl.h" +#include "src/api/api-inl.h" #include "src/heap/heap-inl.h" #include "src/objects/slots.h" #include "src/snapshot/snapshot.h" diff --git a/deps/v8/src/snapshot/partial-serializer.cc b/deps/v8/src/snapshot/partial-serializer.cc index 6c650be4c1..036f0a0414 100644 --- a/deps/v8/src/snapshot/partial-serializer.cc +++ b/deps/v8/src/snapshot/partial-serializer.cc @@ -5,10 +5,11 @@ #include "src/snapshot/partial-serializer.h" #include "src/snapshot/startup-serializer.h" -#include "src/api-inl.h" -#include "src/math-random.h" -#include "src/microtask-queue.h" -#include "src/objects-inl.h" +#include "src/api/api-inl.h" +#include "src/execution/microtask-queue.h" +#include "src/heap/combined-heap.h" +#include "src/numbers/math-random.h" +#include "src/objects/objects-inl.h" #include "src/objects/slots.h" namespace v8 { @@ -31,29 +32,28 @@ PartialSerializer::~PartialSerializer() { void PartialSerializer::Serialize(Context* o, bool include_global_proxy) { context_ = *o; - DCHECK(context_->IsNativeContext()); + DCHECK(context_.IsNativeContext()); reference_map()->AddAttachedReference( - reinterpret_cast<void*>(context_->global_proxy()->ptr())); + reinterpret_cast<void*>(context_.global_proxy().ptr())); // 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. - context_->set(Context::NEXT_CONTEXT_LINK, - ReadOnlyRoots(isolate()).undefined_value()); - DCHECK(!context_->global_object()->IsUndefined()); + context_.set(Context::NEXT_CONTEXT_LINK, + ReadOnlyRoots(isolate()).undefined_value()); + DCHECK(!context_.global_object().IsUndefined()); // Reset math random cache to get fresh random numbers. MathRandom::ResetContext(context_); #ifdef DEBUG - MicrotaskQueue* microtask_queue = - context_->native_context()->microtask_queue(); + MicrotaskQueue* microtask_queue = context_.native_context().microtask_queue(); DCHECK_EQ(0, microtask_queue->size()); DCHECK(!microtask_queue->HasMicrotasksSuppressions()); DCHECK_EQ(0, microtask_queue->GetMicrotasksScopeDepth()); DCHECK(microtask_queue->DebugMicrotasksScopeDepthIsZero()); #endif - context_->native_context()->set_microtask_queue(nullptr); + context_.native_context().set_microtask_queue(nullptr); VisitRootPointer(Root::kPartialSnapshotCache, nullptr, FullObjectSlot(o)); SerializeDeferredObjects(); @@ -92,18 +92,18 @@ void PartialSerializer::SerializeObject(HeapObject obj) { DCHECK(!startup_serializer_->ReferenceMapContains(obj)); // All the internalized strings that the partial snapshot needs should be // either in the root table or in the partial snapshot cache. - DCHECK(!obj->IsInternalizedString()); + DCHECK(!obj.IsInternalizedString()); // Function and object templates are not context specific. - DCHECK(!obj->IsTemplateInfo()); + DCHECK(!obj.IsTemplateInfo()); // We should not end up at another native context. - DCHECK_IMPLIES(obj != context_, !obj->IsNativeContext()); + DCHECK_IMPLIES(obj != context_, !obj.IsNativeContext()); // Clear literal boilerplates and feedback. - if (obj->IsFeedbackVector()) FeedbackVector::cast(obj)->ClearSlots(isolate()); + if (obj.IsFeedbackVector()) FeedbackVector::cast(obj).ClearSlots(isolate()); // Clear InterruptBudget when serializing FeedbackCell. - if (obj->IsFeedbackCell()) { - FeedbackCell::cast(obj)->set_interrupt_budget( + if (obj.IsFeedbackCell()) { + FeedbackCell::cast(obj).set_interrupt_budget( FeedbackCell::GetInitialInterruptBudget()); } @@ -111,12 +111,12 @@ void PartialSerializer::SerializeObject(HeapObject obj) { return; } - if (obj->IsJSFunction()) { + if (obj.IsJSFunction()) { // Unconditionally reset the JSFunction to its SFI's code, since we can't // serialize optimized code anyway. JSFunction closure = JSFunction::cast(obj); - closure->ResetIfBytecodeFlushed(); - if (closure->is_compiled()) closure->set_code(closure->shared()->GetCode()); + closure.ResetIfBytecodeFlushed(); + if (closure.is_compiled()) closure.set_code(closure.shared().GetCode()); } CheckRehashability(obj); @@ -131,12 +131,12 @@ bool PartialSerializer::ShouldBeInThePartialSnapshotCache(HeapObject o) { // 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->IsAccessorInfo() || - o->IsTemplateInfo() || o->IsClassPositions() || - o->map() == ReadOnlyRoots(startup_serializer_->isolate()) - .fixed_cow_array_map(); + DCHECK(!o.IsScript()); + return o.IsName() || o.IsSharedFunctionInfo() || o.IsHeapNumber() || + o.IsCode() || o.IsScopeInfo() || o.IsAccessorInfo() || + o.IsTemplateInfo() || o.IsClassPositions() || + o.map() == ReadOnlyRoots(startup_serializer_->isolate()) + .fixed_cow_array_map(); } namespace { @@ -144,12 +144,12 @@ bool DataIsEmpty(const StartupData& data) { return data.raw_size == 0; } } // anonymous namespace bool PartialSerializer::SerializeJSObjectWithEmbedderFields(Object obj) { - if (!obj->IsJSObject()) return false; + if (!obj.IsJSObject()) return false; JSObject js_obj = JSObject::cast(obj); - int embedder_fields_count = js_obj->GetEmbedderFieldCount(); + int embedder_fields_count = js_obj.GetEmbedderFieldCount(); if (embedder_fields_count == 0) return false; CHECK_GT(embedder_fields_count, 0); - DCHECK(!js_obj->NeedsRehashing()); + DCHECK(!js_obj.NeedsRehashing()); DisallowHeapAllocation no_gc; DisallowJavascriptExecution no_js(isolate()); @@ -170,14 +170,13 @@ bool PartialSerializer::SerializeJSObjectWithEmbedderFields(Object obj) { EmbedderDataSlot embedder_data_slot(js_obj, i); original_embedder_values.emplace_back(embedder_data_slot.load_raw(no_gc)); Object object = embedder_data_slot.load_tagged(); - if (object->IsHeapObject()) { - DCHECK(isolate()->heap()->Contains(HeapObject::cast(object))); + if (object.IsHeapObject()) { + DCHECK(IsValidHeapObject(isolate()->heap(), HeapObject::cast(object))); serialized_data.push_back({nullptr, 0}); } else { // If no serializer is provided and the field was empty, we serialize it // by default to nullptr. - if (serialize_embedder_fields_.callback == nullptr && - object->ptr() == 0) { + if (serialize_embedder_fields_.callback == nullptr && object.ptr() == 0) { serialized_data.push_back({nullptr, 0}); } else { DCHECK_NOT_NULL(serialize_embedder_fields_.callback); @@ -205,7 +204,7 @@ bool PartialSerializer::SerializeJSObjectWithEmbedderFields(Object obj) { // 4) Obtain back reference for the serialized object. SerializerReference reference = - reference_map()->LookupReference(reinterpret_cast<void*>(js_obj->ptr())); + reference_map()->LookupReference(reinterpret_cast<void*>(js_obj.ptr())); DCHECK(reference.is_back_reference()); // 5) Write data returned by the embedder callbacks into a separate sink, @@ -236,8 +235,8 @@ bool PartialSerializer::SerializeJSObjectWithEmbedderFields(Object obj) { void PartialSerializer::CheckRehashability(HeapObject obj) { if (!can_be_rehashed_) return; - if (!obj->NeedsRehashing()) return; - if (obj->CanBeRehashed()) return; + if (!obj.NeedsRehashing()) return; + if (obj.CanBeRehashed()) return; can_be_rehashed_ = false; } diff --git a/deps/v8/src/snapshot/partial-serializer.h b/deps/v8/src/snapshot/partial-serializer.h index fcba9feed2..d8e9ee2496 100644 --- a/deps/v8/src/snapshot/partial-serializer.h +++ b/deps/v8/src/snapshot/partial-serializer.h @@ -5,9 +5,9 @@ #ifndef V8_SNAPSHOT_PARTIAL_SERIALIZER_H_ #define V8_SNAPSHOT_PARTIAL_SERIALIZER_H_ -#include "src/address-map.h" -#include "src/contexts.h" +#include "src/objects/contexts.h" #include "src/snapshot/serializer.h" +#include "src/utils/address-map.h" namespace v8 { namespace internal { diff --git a/deps/v8/src/snapshot/read-only-deserializer.cc b/deps/v8/src/snapshot/read-only-deserializer.cc index b1b22cc70b..576e644846 100644 --- a/deps/v8/src/snapshot/read-only-deserializer.cc +++ b/deps/v8/src/snapshot/read-only-deserializer.cc @@ -4,12 +4,12 @@ #include "src/snapshot/read-only-deserializer.h" -#include "src/api.h" +#include "src/api/api.h" +#include "src/execution/v8threads.h" #include "src/heap/heap-inl.h" // crbug.com/v8/8499 #include "src/heap/read-only-heap.h" #include "src/objects/slots.h" #include "src/snapshot/snapshot.h" -#include "src/v8threads.h" namespace v8 { namespace internal { @@ -21,12 +21,15 @@ void ReadOnlyDeserializer::DeserializeInto(Isolate* isolate) { V8::FatalProcessOutOfMemory(isolate, "ReadOnlyDeserializer"); } + ReadOnlyHeap* ro_heap = isolate->heap()->read_only_heap(); + // No active threads. DCHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse()); // No active handles. DCHECK(isolate->handle_scope_implementer()->blocks()->empty()); + // Read-only object cache is not yet populated. + DCHECK(!ro_heap->read_only_object_cache_is_initialized()); // Partial snapshot cache is not yet populated. - DCHECK(isolate->heap()->read_only_heap()->read_only_object_cache()->empty()); DCHECK(isolate->partial_snapshot_cache()->empty()); // Builtins are not yet created. DCHECK(!isolate->builtins()->is_initialized()); @@ -36,22 +39,16 @@ void ReadOnlyDeserializer::DeserializeInto(Isolate* isolate) { ReadOnlyRoots roots(isolate); roots.Iterate(this); - isolate->heap() - ->read_only_heap() - ->read_only_space() - ->RepairFreeListsAfterDeserialization(); + ro_heap->read_only_space()->RepairFreeListsAfterDeserialization(); // Deserialize the Read-only Object Cache. - std::vector<Object>* cache = - isolate->heap()->read_only_heap()->read_only_object_cache(); for (size_t i = 0;; ++i) { - // Extend the array ready to get a value when deserializing. - if (cache->size() <= i) cache->push_back(Smi::kZero); + Object* object = ro_heap->ExtendReadOnlyObjectCache(); // During deserialization, the visitor populates the read-only object // cache and eventually terminates the cache with undefined. VisitRootPointer(Root::kReadOnlyObjectCache, nullptr, - FullObjectSlot(&cache->at(i))); - if (cache->at(i)->IsUndefined(roots)) break; + FullObjectSlot(object)); + if (object->IsUndefined(roots)) break; } DeserializeDeferredObjects(); } diff --git a/deps/v8/src/snapshot/read-only-serializer.cc b/deps/v8/src/snapshot/read-only-serializer.cc index a65ce4903e..f4b45a15cc 100644 --- a/deps/v8/src/snapshot/read-only-serializer.cc +++ b/deps/v8/src/snapshot/read-only-serializer.cc @@ -4,14 +4,14 @@ #include "src/snapshot/read-only-serializer.h" -#include "src/api.h" -#include "src/code-tracer.h" -#include "src/global-handles.h" +#include "src/api/api.h" +#include "src/diagnostics/code-tracer.h" +#include "src/execution/v8threads.h" +#include "src/handles/global-handles.h" #include "src/heap/read-only-heap.h" -#include "src/objects-inl.h" +#include "src/objects/objects-inl.h" #include "src/objects/slots.h" #include "src/snapshot/startup-serializer.h" -#include "src/v8threads.h" namespace v8 { namespace internal { @@ -27,7 +27,7 @@ ReadOnlySerializer::~ReadOnlySerializer() { void ReadOnlySerializer::SerializeObject(HeapObject obj) { CHECK(ReadOnlyHeap::Contains(obj)); - CHECK_IMPLIES(obj->IsString(), obj->IsInternalizedString()); + CHECK_IMPLIES(obj.IsString(), obj.IsInternalizedString()); if (SerializeHotObject(obj)) return; if (IsRootAndHasBeenSerialized(obj) && SerializeRoot(obj)) { @@ -40,6 +40,9 @@ void ReadOnlySerializer::SerializeObject(HeapObject obj) { // Object has not yet been serialized. Serialize it here. ObjectSerializer object_serializer(this, obj, &sink_); object_serializer.Serialize(); +#ifdef DEBUG + serialized_objects_.insert(obj); +#endif } void ReadOnlySerializer::SerializeReadOnlyRoots() { @@ -60,6 +63,16 @@ void ReadOnlySerializer::FinalizeSerialization() { FullObjectSlot(&undefined)); SerializeDeferredObjects(); Pad(); + +#ifdef DEBUG + // Check that every object on read-only heap is reachable (and was + // serialized). + ReadOnlyHeapIterator iterator(isolate()->heap()->read_only_heap()); + for (HeapObject object = iterator.Next(); !object.is_null(); + object = iterator.Next()) { + CHECK(serialized_objects_.count(object)); + } +#endif } bool ReadOnlySerializer::MustBeDeferred(HeapObject object) { @@ -75,7 +88,7 @@ bool ReadOnlySerializer::MustBeDeferred(HeapObject object) { // not be fulfilled during deserialization until few first root objects are // serialized. But we must serialize Map objects since deserializer checks // that these root objects are indeed Maps. - return !object->IsMap(); + return !object.IsMap(); } bool ReadOnlySerializer::SerializeUsingReadOnlyObjectCache( diff --git a/deps/v8/src/snapshot/read-only-serializer.h b/deps/v8/src/snapshot/read-only-serializer.h index 753432502e..c73c397647 100644 --- a/deps/v8/src/snapshot/read-only-serializer.h +++ b/deps/v8/src/snapshot/read-only-serializer.h @@ -5,6 +5,8 @@ #ifndef V8_SNAPSHOT_READ_ONLY_SERIALIZER_H_ #define V8_SNAPSHOT_READ_ONLY_SERIALIZER_H_ +#include <unordered_set> + #include "src/snapshot/roots-serializer.h" namespace v8 { @@ -35,6 +37,9 @@ class V8_EXPORT_PRIVATE ReadOnlySerializer : public RootsSerializer { void SerializeObject(HeapObject o) override; bool MustBeDeferred(HeapObject object) override; +#ifdef DEBUG + std::unordered_set<HeapObject, Object::Hasher> serialized_objects_; +#endif DISALLOW_COPY_AND_ASSIGN(ReadOnlySerializer); }; diff --git a/deps/v8/src/snapshot/references.h b/deps/v8/src/snapshot/references.h index ff3196115c..e7c44236ac 100644 --- a/deps/v8/src/snapshot/references.h +++ b/deps/v8/src/snapshot/references.h @@ -5,9 +5,9 @@ #ifndef V8_SNAPSHOT_REFERENCES_H_ #define V8_SNAPSHOT_REFERENCES_H_ -#include "src/assert-scope.h" #include "src/base/hashmap.h" -#include "src/utils.h" +#include "src/common/assert-scope.h" +#include "src/utils/utils.h" namespace v8 { namespace internal { diff --git a/deps/v8/src/snapshot/roots-serializer.cc b/deps/v8/src/snapshot/roots-serializer.cc index e634c45eff..f354dec158 100644 --- a/deps/v8/src/snapshot/roots-serializer.cc +++ b/deps/v8/src/snapshot/roots-serializer.cc @@ -4,9 +4,9 @@ #include "src/snapshot/roots-serializer.h" +#include "src/execution/isolate.h" #include "src/heap/heap.h" -#include "src/isolate.h" -#include "src/objects-inl.h" +#include "src/objects/objects-inl.h" #include "src/objects/slots.h" namespace v8 { @@ -58,8 +58,8 @@ void RootsSerializer::VisitRootPointers(Root root, const char* description, void RootsSerializer::CheckRehashability(HeapObject obj) { if (!can_be_rehashed_) return; - if (!obj->NeedsRehashing()) return; - if (obj->CanBeRehashed()) return; + if (!obj.NeedsRehashing()) return; + if (obj.CanBeRehashed()) return; can_be_rehashed_ = false; } diff --git a/deps/v8/src/snapshot/roots-serializer.h b/deps/v8/src/snapshot/roots-serializer.h index 50c63402d2..cfb59dd75e 100644 --- a/deps/v8/src/snapshot/roots-serializer.h +++ b/deps/v8/src/snapshot/roots-serializer.h @@ -7,8 +7,8 @@ #include <bitset> +#include "src/objects/visitors.h" #include "src/snapshot/serializer.h" -#include "src/visitors.h" namespace v8 { namespace internal { diff --git a/deps/v8/src/snapshot/serializer-allocator.cc b/deps/v8/src/snapshot/serializer-allocator.cc index d596678789..763244137f 100644 --- a/deps/v8/src/snapshot/serializer-allocator.cc +++ b/deps/v8/src/snapshot/serializer-allocator.cc @@ -144,7 +144,7 @@ void SerializerAllocator::OutputStatistics() { for (int space = FIRST_SPACE; space < kNumberOfPreallocatedSpaces; space++) { size_t s = pending_chunk_[space]; for (uint32_t chunk_size : completed_chunks_[space]) s += chunk_size; - PrintF("%16" PRIuS, s); + PrintF("%16zu", s); } STATIC_ASSERT(MAP_SPACE == kNumberOfPreallocatedSpaces); diff --git a/deps/v8/src/snapshot/serializer-common.cc b/deps/v8/src/snapshot/serializer-common.cc index fa8d19e438..2869c2bf24 100644 --- a/deps/v8/src/snapshot/serializer-common.cc +++ b/deps/v8/src/snapshot/serializer-common.cc @@ -4,9 +4,9 @@ #include "src/snapshot/serializer-common.h" -#include "src/external-reference-table.h" -#include "src/objects-inl.h" +#include "src/codegen/external-reference-table.h" #include "src/objects/foreign-inl.h" +#include "src/objects/objects-inl.h" #include "src/objects/slots.h" namespace v8 { @@ -120,28 +120,28 @@ void SerializerDeserializer::Iterate(Isolate* isolate, RootVisitor* visitor) { // and eventually terminates the cache with undefined. visitor->VisitRootPointer(Root::kPartialSnapshotCache, nullptr, FullObjectSlot(&cache->at(i))); - if (cache->at(i)->IsUndefined(isolate)) break; + if (cache->at(i).IsUndefined(isolate)) break; } } bool SerializerDeserializer::CanBeDeferred(HeapObject o) { - return !o->IsString() && !o->IsScript() && !o->IsJSTypedArray(); + return !o.IsString() && !o.IsScript() && !o.IsJSTypedArray(); } void SerializerDeserializer::RestoreExternalReferenceRedirectors( const std::vector<AccessorInfo>& accessor_infos) { // Restore wiped accessor infos. for (AccessorInfo info : accessor_infos) { - Foreign::cast(info->js_getter()) - ->set_foreign_address(info->redirected_getter()); + Foreign::cast(info.js_getter()) + .set_foreign_address(info.redirected_getter()); } } void SerializerDeserializer::RestoreExternalReferenceRedirectors( const std::vector<CallHandlerInfo>& call_handler_infos) { for (CallHandlerInfo info : call_handler_infos) { - Foreign::cast(info->js_callback()) - ->set_foreign_address(info->redirected_callback()); + Foreign::cast(info.js_callback()) + .set_foreign_address(info.redirected_callback()); } } diff --git a/deps/v8/src/snapshot/serializer-common.h b/deps/v8/src/snapshot/serializer-common.h index a373683886..30da8db662 100644 --- a/deps/v8/src/snapshot/serializer-common.h +++ b/deps/v8/src/snapshot/serializer-common.h @@ -5,14 +5,14 @@ #ifndef V8_SNAPSHOT_SERIALIZER_COMMON_H_ #define V8_SNAPSHOT_SERIALIZER_COMMON_H_ -#include "src/address-map.h" #include "src/base/bits.h" -#include "src/external-reference-table.h" -#include "src/globals.h" -#include "src/msan.h" +#include "src/codegen/external-reference-table.h" +#include "src/common/globals.h" +#include "src/common/v8memory.h" +#include "src/objects/visitors.h" +#include "src/sanitizer/msan.h" #include "src/snapshot/references.h" -#include "src/v8memory.h" -#include "src/visitors.h" +#include "src/utils/address-map.h" namespace v8 { namespace internal { @@ -370,13 +370,19 @@ class Checksum { #ifdef MEMORY_SANITIZER // Computing the checksum includes padding bytes for objects like strings. // Mark every object as initialized in the code serializer. - MSAN_MEMORY_IS_INITIALIZED(payload.start(), payload.length()); + MSAN_MEMORY_IS_INITIALIZED(payload.begin(), payload.length()); #endif // MEMORY_SANITIZER // Fletcher's checksum. Modified to reduce 64-bit sums to 32-bit. uintptr_t a = 1; uintptr_t b = 0; - const uintptr_t* cur = reinterpret_cast<const uintptr_t*>(payload.start()); + // TODO(jgruber, v8:9171): The following DCHECK should ideally hold since we + // access payload through an uintptr_t pointer later on; and some + // architectures, e.g. arm, may generate instructions that expect correct + // alignment. However, we do not control alignment for external snapshots. + // DCHECK(IsAligned(reinterpret_cast<intptr_t>(payload.begin()), + // kIntptrSize)); DCHECK(IsAligned(payload.length(), kIntptrSize)); + const uintptr_t* cur = reinterpret_cast<const uintptr_t*>(payload.begin()); const uintptr_t* end = cur + payload.length() / kIntptrSize; while (cur < end) { // Unsigned overflow expected and intended. diff --git a/deps/v8/src/snapshot/serializer.cc b/deps/v8/src/snapshot/serializer.cc index 447a69aea8..9eefbe2c48 100644 --- a/deps/v8/src/snapshot/serializer.cc +++ b/deps/v8/src/snapshot/serializer.cc @@ -4,7 +4,7 @@ #include "src/snapshot/serializer.h" -#include "src/assembler-inl.h" +#include "src/codegen/assembler-inl.h" #include "src/heap/heap-inl.h" // For Space::identity(). #include "src/heap/read-only-heap.h" #include "src/interpreter/interpreter.h" @@ -58,7 +58,7 @@ Serializer::~Serializer() { #ifdef OBJECT_PRINT void Serializer::CountInstanceType(Map map, int size, AllocationSpace space) { - int instance_type = map->instance_type(); + int instance_type = map.instance_type(); instance_type_count_[space][instance_type]++; instance_type_size_[space][instance_type] += size; } @@ -75,8 +75,7 @@ void Serializer::OutputStatistics(const char* name) { #define PRINT_INSTANCE_TYPE(Name) \ for (int space = 0; space < LAST_SPACE; ++space) { \ if (instance_type_count_[space][Name]) { \ - PrintF("%10d %10" PRIuS " %-10s %s\n", \ - instance_type_count_[space][Name], \ + PrintF("%10d %10zu %-10s %s\n", instance_type_count_[space][Name], \ instance_type_size_[space][Name], \ Heap::GetSpaceName(static_cast<AllocationSpace>(space)), #Name); \ } \ @@ -108,7 +107,7 @@ void Serializer::VisitRootPointers(Root root, const char* description, } void Serializer::SerializeRootObject(Object object) { - if (object->IsSmi()) { + if (object.IsSmi()) { PutSmi(Smi::cast(object)); } else { SerializeObject(HeapObject::cast(object)); @@ -116,12 +115,10 @@ void Serializer::SerializeRootObject(Object object) { } #ifdef DEBUG -void Serializer::PrintStack() { PrintStack(std::cout); } - -void Serializer::PrintStack(std::ostream& out) { +void Serializer::PrintStack() { for (const auto o : stack_) { - o.Print(out); - out << "\n"; + o.Print(); + PrintF("\n"); } } #endif // DEBUG @@ -144,10 +141,9 @@ bool Serializer::SerializeHotObject(HeapObject obj) { DCHECK(index >= 0 && index < kNumberOfHotObjects); if (FLAG_trace_serializer) { PrintF(" Encoding hot object %d:", index); - obj->ShortPrint(); + obj.ShortPrint(); PrintF("\n"); } - // TODO(ishell): remove kHotObjectWithSkip sink_.Put(kHotObject + index, "HotObject"); return true; } @@ -170,7 +166,7 @@ bool Serializer::SerializeBackReference(HeapObject obj) { DCHECK(reference.is_back_reference()); if (FLAG_trace_serializer) { PrintF(" Encoding back reference to: "); - obj->ShortPrint(); + obj.ShortPrint(); PrintF("\n"); } @@ -183,15 +179,15 @@ bool Serializer::SerializeBackReference(HeapObject obj) { } bool Serializer::ObjectIsBytecodeHandler(HeapObject obj) const { - if (!obj->IsCode()) return false; - return (Code::cast(obj)->kind() == Code::BYTECODE_HANDLER); + if (!obj.IsCode()) return false; + return (Code::cast(obj).kind() == Code::BYTECODE_HANDLER); } void Serializer::PutRoot(RootIndex root, HeapObject object) { int root_index = static_cast<int>(root); if (FLAG_trace_serializer) { PrintF(" Encoding root %d:", root_index); - object->ShortPrint(); + object.ShortPrint(); PrintF("\n"); } @@ -247,7 +243,7 @@ void Serializer::PutAttachedReference(SerializerReference reference) { } int Serializer::PutAlignmentPrefix(HeapObject object) { - AllocationAlignment alignment = HeapObject::RequiredAlignment(object->map()); + AllocationAlignment alignment = HeapObject::RequiredAlignment(object.map()); if (alignment != kWordAligned) { DCHECK(1 <= alignment && alignment <= 3); byte prefix = (kAlignmentPrefix - 1) + alignment; @@ -290,10 +286,10 @@ void Serializer::InitializeCodeAddressMap() { Code Serializer::CopyCode(Code code) { code_buffer_.clear(); // Clear buffer without deleting backing store. - int size = code->CodeSize(); + int size = code.CodeSize(); code_buffer_.insert(code_buffer_.end(), - reinterpret_cast<byte*>(code->address()), - reinterpret_cast<byte*>(code->address() + size)); + reinterpret_cast<byte*>(code.address()), + reinterpret_cast<byte*>(code.address() + size)); // When pointer compression is enabled the checked cast will try to // decompress map field of off-heap Code object. return Code::unchecked_cast(HeapObject::FromAddress( @@ -304,16 +300,16 @@ void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space, int size, Map map) { if (serializer_->code_address_map_) { const char* code_name = - serializer_->code_address_map_->Lookup(object_->address()); + serializer_->code_address_map_->Lookup(object_.address()); LOG(serializer_->isolate_, - CodeNameEvent(object_->address(), sink_->Position(), code_name)); + CodeNameEvent(object_.address(), sink_->Position(), code_name)); } SerializerReference back_reference; if (space == LO_SPACE) { sink_->Put(kNewObject + space, "NewLargeObject"); sink_->PutInt(size >> kObjectAlignmentBits, "ObjectSizeInWords"); - CHECK(!object_->IsCode()); + CHECK(!object_.IsCode()); back_reference = serializer_->allocator()->AllocateLargeObject(size); } else if (space == MAP_SPACE) { DCHECK_EQ(Map::kSize, size); @@ -363,56 +359,48 @@ int32_t Serializer::ObjectSerializer::SerializeBackingStore( void Serializer::ObjectSerializer::SerializeJSTypedArray() { JSTypedArray typed_array = JSTypedArray::cast(object_); - FixedTypedArrayBase elements = - FixedTypedArrayBase::cast(typed_array->elements()); - - if (!typed_array->WasDetached()) { - if (!typed_array->is_on_heap()) { + if (!typed_array.WasDetached()) { + if (!typed_array.is_on_heap()) { // Explicitly serialize the backing store now. - JSArrayBuffer buffer = JSArrayBuffer::cast(typed_array->buffer()); - CHECK_LE(buffer->byte_length(), Smi::kMaxValue); - CHECK_LE(typed_array->byte_offset(), Smi::kMaxValue); - int32_t byte_length = static_cast<int32_t>(buffer->byte_length()); - int32_t byte_offset = static_cast<int32_t>(typed_array->byte_offset()); + JSArrayBuffer buffer = JSArrayBuffer::cast(typed_array.buffer()); + CHECK_LE(buffer.byte_length(), Smi::kMaxValue); + CHECK_LE(typed_array.byte_offset(), Smi::kMaxValue); + int32_t byte_length = static_cast<int32_t>(buffer.byte_length()); + int32_t byte_offset = static_cast<int32_t>(typed_array.byte_offset()); // We need to calculate the backing store from the external pointer // because the ArrayBuffer may already have been serialized. void* backing_store = reinterpret_cast<void*>( - reinterpret_cast<intptr_t>(elements->external_pointer()) - + reinterpret_cast<intptr_t>(typed_array.external_pointer()) - byte_offset); int32_t ref = SerializeBackingStore(backing_store, byte_length); // The external_pointer is the backing_store + typed_array->byte_offset. // To properly share the buffer, we set the backing store ref here. On // deserialization we re-add the byte_offset to external_pointer. - elements->set_external_pointer( + typed_array.set_external_pointer( reinterpret_cast<void*>(Smi::FromInt(ref).ptr())); } } else { - // When a JSArrayBuffer is detached, the FixedTypedArray that points to the - // same backing store does not know anything about it. This fixup step finds - // detached TypedArrays and clears the values in the FixedTypedArray so that - // we don't try to serialize the now invalid backing store. - elements->set_external_pointer(reinterpret_cast<void*>(Smi::kZero.ptr())); - elements->set_length(0); + typed_array.set_external_pointer(nullptr); } SerializeObject(); } void Serializer::ObjectSerializer::SerializeJSArrayBuffer() { JSArrayBuffer buffer = JSArrayBuffer::cast(object_); - void* backing_store = buffer->backing_store(); + void* backing_store = buffer.backing_store(); // We cannot store byte_length larger than Smi range in the snapshot. - CHECK_LE(buffer->byte_length(), Smi::kMaxValue); - int32_t byte_length = static_cast<int32_t>(buffer->byte_length()); + CHECK_LE(buffer.byte_length(), Smi::kMaxValue); + int32_t byte_length = static_cast<int32_t>(buffer.byte_length()); // The embedder-allocated backing store only exists for the off-heap case. if (backing_store != nullptr) { int32_t ref = SerializeBackingStore(backing_store, byte_length); - buffer->set_backing_store(reinterpret_cast<void*>(Smi::FromInt(ref).ptr())); + buffer.set_backing_store(reinterpret_cast<void*>(Smi::FromInt(ref).ptr())); } SerializeObject(); - buffer->set_backing_store(backing_store); + buffer.set_backing_store(backing_store); } void Serializer::ObjectSerializer::SerializeExternalString() { @@ -422,30 +410,30 @@ void Serializer::ObjectSerializer::SerializeExternalString() { // for native native source code strings, we replace the resource field // with the native source id. // For the rest we serialize them to look like ordinary sequential strings. - if (object_->map() != ReadOnlyRoots(heap).native_source_string_map()) { + if (object_.map() != ReadOnlyRoots(heap).native_source_string_map()) { ExternalString string = ExternalString::cast(object_); - Address resource = string->resource_as_address(); + Address resource = string.resource_as_address(); ExternalReferenceEncoder::Value reference; if (serializer_->external_reference_encoder_.TryEncode(resource).To( &reference)) { DCHECK(reference.is_from_api()); - string->set_uint32_as_resource(reference.index()); + string.set_uint32_as_resource(reference.index()); SerializeObject(); - string->set_address_as_resource(resource); + string.set_address_as_resource(resource); } else { SerializeExternalStringAsSequentialString(); } } else { ExternalOneByteString string = ExternalOneByteString::cast(object_); - DCHECK(string->is_uncached()); + DCHECK(string.is_uncached()); const NativesExternalStringResource* resource = reinterpret_cast<const NativesExternalStringResource*>( - string->resource()); + string.resource()); // Replace the resource field with the type and index of the native source. - string->set_resource(resource->EncodeForSerialization()); + string.set_resource(resource->EncodeForSerialization()); SerializeObject(); // Restore the resource field. - string->set_resource(resource); + string.set_resource(resource); } } @@ -453,29 +441,29 @@ void Serializer::ObjectSerializer::SerializeExternalStringAsSequentialString() { // Instead of serializing this as an external string, we serialize // an imaginary sequential string with the same content. ReadOnlyRoots roots(serializer_->isolate()); - DCHECK(object_->IsExternalString()); - DCHECK(object_->map() != roots.native_source_string_map()); + DCHECK(object_.IsExternalString()); + DCHECK(object_.map() != roots.native_source_string_map()); ExternalString string = ExternalString::cast(object_); - int length = string->length(); + int length = string.length(); Map map; int content_size; int allocation_size; const byte* resource; // Find the map and size for the imaginary sequential string. - bool internalized = object_->IsInternalizedString(); - if (object_->IsExternalOneByteString()) { + bool internalized = object_.IsInternalizedString(); + if (object_.IsExternalOneByteString()) { map = internalized ? roots.one_byte_internalized_string_map() : roots.one_byte_string_map(); allocation_size = SeqOneByteString::SizeFor(length); content_size = length * kCharSize; resource = reinterpret_cast<const byte*>( - ExternalOneByteString::cast(string)->resource()->data()); + ExternalOneByteString::cast(string).resource()->data()); } else { map = internalized ? roots.internalized_string_map() : roots.string_map(); allocation_size = SeqTwoByteString::SizeFor(length); content_size = length * kShortSize; resource = reinterpret_cast<const byte*>( - ExternalTwoByteString::cast(string)->resource()->data()); + ExternalTwoByteString::cast(string).resource()->data()); } AllocationSpace space = @@ -491,7 +479,7 @@ void Serializer::ObjectSerializer::SerializeExternalStringAsSequentialString() { sink_->PutInt(bytes_to_output, "length"); // Serialize string header (except for map). - uint8_t* string_start = reinterpret_cast<uint8_t*>(string->address()); + uint8_t* string_start = reinterpret_cast<uint8_t*>(string.address()); for (int i = HeapObject::kHeaderSize; i < SeqString::kHeaderSize; i++) { sink_->PutSection(string_start[i], "StringHeader"); } @@ -511,19 +499,19 @@ void Serializer::ObjectSerializer::SerializeExternalStringAsSequentialString() { class UnlinkWeakNextScope { public: explicit UnlinkWeakNextScope(Heap* heap, HeapObject object) { - if (object->IsAllocationSite() && - AllocationSite::cast(object)->HasWeakNext()) { + if (object.IsAllocationSite() && + AllocationSite::cast(object).HasWeakNext()) { object_ = object; - next_ = AllocationSite::cast(object)->weak_next(); - AllocationSite::cast(object)->set_weak_next( + next_ = AllocationSite::cast(object).weak_next(); + AllocationSite::cast(object).set_weak_next( ReadOnlyRoots(heap).undefined_value()); } } ~UnlinkWeakNextScope() { if (!object_.is_null()) { - AllocationSite::cast(object_)->set_weak_next(next_, - UPDATE_WEAK_WRITE_BARRIER); + AllocationSite::cast(object_).set_weak_next(next_, + UPDATE_WEAK_WRITE_BARRIER); } } @@ -536,48 +524,48 @@ class UnlinkWeakNextScope { void Serializer::ObjectSerializer::Serialize() { if (FLAG_trace_serializer) { PrintF(" Encoding heap object: "); - object_->ShortPrint(); + object_.ShortPrint(); PrintF("\n"); } - if (object_->IsExternalString()) { + if (object_.IsExternalString()) { SerializeExternalString(); return; } else if (!ReadOnlyHeap::Contains(object_)) { // Only clear padding for strings outside RO_SPACE. RO_SPACE should have // been cleared elsewhere. - if (object_->IsSeqOneByteString()) { + if (object_.IsSeqOneByteString()) { // Clear padding bytes at the end. Done here to avoid having to do this // at allocation sites in generated code. - SeqOneByteString::cast(object_)->clear_padding(); - } else if (object_->IsSeqTwoByteString()) { - SeqTwoByteString::cast(object_)->clear_padding(); + SeqOneByteString::cast(object_).clear_padding(); + } else if (object_.IsSeqTwoByteString()) { + SeqTwoByteString::cast(object_).clear_padding(); } } - if (object_->IsJSTypedArray()) { + if (object_.IsJSTypedArray()) { SerializeJSTypedArray(); return; } - if (object_->IsJSArrayBuffer()) { + if (object_.IsJSArrayBuffer()) { SerializeJSArrayBuffer(); return; } // We don't expect fillers. - DCHECK(!object_->IsFiller()); + DCHECK(!object_.IsFiller()); - if (object_->IsScript()) { + if (object_.IsScript()) { // Clear cached line ends. Object undefined = ReadOnlyRoots(serializer_->isolate()).undefined_value(); - Script::cast(object_)->set_line_ends(undefined); + Script::cast(object_).set_line_ends(undefined); } SerializeObject(); } void Serializer::ObjectSerializer::SerializeObject() { - int size = object_->Size(); - Map map = object_->map(); + int size = object_.Size(); + Map map = object_.map(); AllocationSpace space = MemoryChunk::FromHeapObject(object_)->owner()->identity(); // Young generation large objects are tenured. @@ -606,12 +594,12 @@ void Serializer::ObjectSerializer::SerializeObject() { void Serializer::ObjectSerializer::SerializeDeferred() { if (FLAG_trace_serializer) { PrintF(" Encoding deferred heap object: "); - object_->ShortPrint(); + object_.ShortPrint(); PrintF("\n"); } - int size = object_->Size(); - Map map = object_->map(); + int size = object_.Size(); + Map map = object_.map(); SerializerReference back_reference = serializer_->reference_map()->LookupReference( reinterpret_cast<void*>(object_.ptr())); @@ -631,16 +619,16 @@ void Serializer::ObjectSerializer::SerializeDeferred() { void Serializer::ObjectSerializer::SerializeContent(Map map, int size) { UnlinkWeakNextScope unlink_weak_next(serializer_->isolate()->heap(), object_); - if (object_->IsCode()) { + if (object_.IsCode()) { // For code objects, output raw bytes first. OutputCode(size); // Then iterate references via reloc info. - object_->IterateBody(map, size, this); + object_.IterateBody(map, size, this); } else { // For other objects, iterate references first. - object_->IterateBody(map, size, this); + object_.IterateBody(map, size, this); // Then output data payload, if any. - OutputRawData(object_->address() + size); + OutputRawData(object_.address() + size); } } @@ -714,7 +702,7 @@ void Serializer::ObjectSerializer::VisitEmbeddedPointer(Code host, void Serializer::ObjectSerializer::VisitExternalReference(Foreign host, Address* p) { auto encoded_reference = - serializer_->EncodeExternalReference(host->foreign_address()); + serializer_->EncodeExternalReference(host.foreign_address()); if (encoded_reference.is_from_api()) { sink_->Put(kApiReference, "ApiRef"); } else { @@ -741,10 +729,10 @@ void Serializer::ObjectSerializer::VisitExternalReference(Code host, void Serializer::ObjectSerializer::VisitInternalReference(Code host, RelocInfo* rinfo) { - Address entry = Code::cast(object_)->entry(); + Address entry = Code::cast(object_).entry(); DCHECK_GE(rinfo->target_internal_reference(), entry); uintptr_t target_offset = rinfo->target_internal_reference() - entry; - DCHECK_LE(target_offset, Code::cast(object_)->raw_instruction_size()); + DCHECK_LE(target_offset, Code::cast(object_).raw_instruction_size()); sink_->Put(kInternalReference, "InternalRef"); sink_->PutInt(target_offset, "internal ref value"); } @@ -767,7 +755,7 @@ void Serializer::ObjectSerializer::VisitOffHeapTarget(Code host, CHECK(Builtins::IsIsolateIndependentBuiltin(target)); sink_->Put(kOffHeapTarget, "OffHeapTarget"); - sink_->PutInt(target->builtin_index(), "builtin index"); + sink_->PutInt(target.builtin_index(), "builtin index"); bytes_processed_so_far_ += rinfo->target_address_size(); } @@ -807,7 +795,7 @@ void OutputRawWithCustomField(SnapshotByteSink* sink, Address object_start, } // anonymous namespace void Serializer::ObjectSerializer::OutputRawData(Address up_to) { - Address object_start = object_->address(); + Address object_start = object_.address(); int base = bytes_processed_so_far_; int up_to_offset = static_cast<int>(up_to - object_start); int to_skip = up_to_offset - bytes_processed_so_far_; @@ -829,13 +817,13 @@ void Serializer::ObjectSerializer::OutputRawData(Address up_to) { __msan_check_mem_is_initialized( reinterpret_cast<void*>(object_start + base), bytes_to_output); #endif // MEMORY_SANITIZER - if (object_->IsBytecodeArray()) { + if (object_.IsBytecodeArray()) { // The bytecode age field can be changed by GC concurrently. byte field_value = BytecodeArray::kNoAgeBytecodeAge; OutputRawWithCustomField(sink_, object_start, base, bytes_to_output, BytecodeArray::kBytecodeAgeOffset, sizeof(field_value), &field_value); - } else if (object_->IsDescriptorArray()) { + } else if (object_.IsDescriptorArray()) { // The number of marked descriptors field can be changed by GC // concurrently. byte field_value[2]; @@ -859,7 +847,8 @@ void Serializer::ObjectSerializer::OutputCode(int size) { // and wipe all pointers in the copy, which we then serialize. Code off_heap_code = serializer_->CopyCode(on_heap_code); int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | - RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | + RelocInfo::ModeMask(RelocInfo::FULL_EMBEDDED_OBJECT) | + RelocInfo::ModeMask(RelocInfo::COMPRESSED_EMBEDDED_OBJECT) | RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) | RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) | @@ -868,7 +857,7 @@ void Serializer::ObjectSerializer::OutputCode(int size) { // With enabled pointer compression normal accessors no longer work for // off-heap objects, so we have to get the relocation info data via the // on-heap code object. - ByteArray relocation_info = on_heap_code->unchecked_relocation_info(); + ByteArray relocation_info = on_heap_code.unchecked_relocation_info(); for (RelocIterator it(off_heap_code, relocation_info, mode_mask); !it.done(); it.next()) { RelocInfo* rinfo = it.rinfo(); @@ -876,9 +865,9 @@ void Serializer::ObjectSerializer::OutputCode(int size) { } // We need to wipe out the header fields *after* wiping out the // relocations, because some of these fields are needed for the latter. - off_heap_code->WipeOutHeader(); + off_heap_code.WipeOutHeader(); - Address start = off_heap_code->address() + Code::kDataStart; + Address start = off_heap_code.address() + Code::kDataStart; int bytes_to_output = size - Code::kDataStart; DCHECK(IsAligned(bytes_to_output, kTaggedSize)); diff --git a/deps/v8/src/snapshot/serializer.h b/deps/v8/src/snapshot/serializer.h index 49ffddbefb..c9e7fada80 100644 --- a/deps/v8/src/snapshot/serializer.h +++ b/deps/v8/src/snapshot/serializer.h @@ -7,10 +7,10 @@ #include <map> -#include "src/isolate.h" -#include "src/log.h" -#include "src/objects.h" -#include "src/snapshot/embedded-data.h" +#include "src/execution/isolate.h" +#include "src/logging/log.h" +#include "src/objects/objects.h" +#include "src/snapshot/embedded/embedded-data.h" #include "src/snapshot/serializer-allocator.h" #include "src/snapshot/serializer-common.h" #include "src/snapshot/snapshot-source-sink.h" @@ -29,7 +29,7 @@ class CodeAddressMap : public CodeEventLogger { } void CodeMoveEvent(AbstractCode from, AbstractCode to) override { - address_to_name_map_.Move(from->address(), to->address()); + address_to_name_map_.Move(from.address(), to.address()); } void CodeDisableOptEvent(AbstractCode code, @@ -116,7 +116,7 @@ class CodeAddressMap : public CodeEventLogger { void LogRecordedBuffer(AbstractCode code, SharedFunctionInfo, const char* name, int length) override { - address_to_name_map_.Insert(code->address(), name, length); + address_to_name_map_.Insert(code.address(), name, length); } void LogRecordedBuffer(const wasm::WasmCode* code, const char* name, @@ -167,7 +167,7 @@ class Serializer : public SerializerDeserializer { bool ReferenceMapContains(HeapObject o) { return reference_map() - ->LookupReference(reinterpret_cast<void*>(o->ptr())) + ->LookupReference(reinterpret_cast<void*>(o.ptr())) .is_valid(); } @@ -235,7 +235,7 @@ class Serializer : public SerializerDeserializer { Code CopyCode(Code code); void QueueDeferredObject(HeapObject obj) { - DCHECK(reference_map_.LookupReference(reinterpret_cast<void*>(obj->ptr())) + DCHECK(reference_map_.LookupReference(reinterpret_cast<void*>(obj.ptr())) .is_back_reference()); deferred_objects_.push_back(obj); } @@ -250,7 +250,6 @@ class Serializer : public SerializerDeserializer { void PushStack(HeapObject o) { stack_.push_back(o); } void PopStack() { stack_.pop_back(); } void PrintStack(); - void PrintStack(std::ostream&); #endif // DEBUG SerializerReferenceMap* reference_map() { return &reference_map_; } diff --git a/deps/v8/src/snapshot/snapshot-common.cc b/deps/v8/src/snapshot/snapshot-common.cc index 271317836c..f489999f88 100644 --- a/deps/v8/src/snapshot/snapshot-common.cc +++ b/deps/v8/src/snapshot/snapshot-common.cc @@ -7,11 +7,12 @@ #include "src/snapshot/snapshot.h" #include "src/base/platform/platform.h" -#include "src/counters.h" +#include "src/logging/counters.h" #include "src/snapshot/partial-deserializer.h" #include "src/snapshot/read-only-deserializer.h" #include "src/snapshot/startup-deserializer.h" -#include "src/version.h" +#include "src/utils/memcopy.h" +#include "src/utils/version.h" namespace v8 { namespace internal { @@ -151,7 +152,7 @@ v8::StartupData Snapshot::CreateSnapshotBlob( uint32_t payload_length = static_cast<uint32_t>(startup_snapshot->RawData().length()); CopyBytes(data + payload_offset, - reinterpret_cast<const char*>(startup_snapshot->RawData().start()), + reinterpret_cast<const char*>(startup_snapshot->RawData().begin()), payload_length); if (FLAG_profile_deserialization) { PrintF("Snapshot blob consists of:\n%10d bytes in %d chunks for startup\n", @@ -165,7 +166,7 @@ v8::StartupData Snapshot::CreateSnapshotBlob( payload_length = read_only_snapshot->RawData().length(); CopyBytes( data + payload_offset, - reinterpret_cast<const char*>(read_only_snapshot->RawData().start()), + reinterpret_cast<const char*>(read_only_snapshot->RawData().begin()), payload_length); if (FLAG_profile_deserialization) { PrintF("%10d bytes for read-only\n", payload_length); @@ -179,7 +180,7 @@ v8::StartupData Snapshot::CreateSnapshotBlob( payload_length = context_snapshot->RawData().length(); CopyBytes( data + payload_offset, - reinterpret_cast<const char*>(context_snapshot->RawData().start()), + reinterpret_cast<const char*>(context_snapshot->RawData().begin()), payload_length); if (FLAG_profile_deserialization) { PrintF("%10d bytes in %d chunks for context #%d\n", payload_length, @@ -379,29 +380,55 @@ bool RunExtraCode(v8::Isolate* isolate, v8::Local<v8::Context> context, } // namespace -// TODO(jgruber): Merge with related code in mksnapshot.cc and -// inspector-test.cc. v8::StartupData CreateSnapshotDataBlobInternal( v8::SnapshotCreator::FunctionCodeHandling function_code_handling, - const char* embedded_source) { - // Create a new isolate and a new context from scratch, optionally run - // a script to embed, and serialize to create a snapshot blob. - v8::StartupData result = {nullptr, 0}; + const char* embedded_source, v8::Isolate* isolate) { + // If no isolate is passed in, create it (and a new context) from scratch. + if (isolate == nullptr) isolate = v8::Isolate::Allocate(); + + // Optionally run a script to embed, and serialize to create a snapshot blob. + v8::SnapshotCreator snapshot_creator(isolate); { - v8::SnapshotCreator snapshot_creator; - v8::Isolate* isolate = snapshot_creator.GetIsolate(); - { - v8::HandleScope scope(isolate); - v8::Local<v8::Context> context = v8::Context::New(isolate); - if (embedded_source != nullptr && - !RunExtraCode(isolate, context, embedded_source, "<embedded>")) { - return result; - } - snapshot_creator.SetDefaultContext(context); + v8::HandleScope scope(isolate); + v8::Local<v8::Context> context = v8::Context::New(isolate); + if (embedded_source != nullptr && + !RunExtraCode(isolate, context, embedded_source, "<embedded>")) { + return {}; } - result = snapshot_creator.CreateBlob(function_code_handling); + snapshot_creator.SetDefaultContext(context); } - return result; + return snapshot_creator.CreateBlob(function_code_handling); +} + +v8::StartupData WarmUpSnapshotDataBlobInternal( + v8::StartupData cold_snapshot_blob, const char* warmup_source) { + CHECK(cold_snapshot_blob.raw_size > 0 && cold_snapshot_blob.data != nullptr); + CHECK_NOT_NULL(warmup_source); + + // Use following steps to create a warmed up snapshot blob from a cold one: + // - Create a new isolate from the cold snapshot. + // - Create a new context to run the warmup script. This will trigger + // compilation of executed functions. + // - Create a new context. This context will be unpolluted. + // - Serialize the isolate and the second context into a new snapshot blob. + v8::SnapshotCreator snapshot_creator(nullptr, &cold_snapshot_blob); + v8::Isolate* isolate = snapshot_creator.GetIsolate(); + { + v8::HandleScope scope(isolate); + v8::Local<v8::Context> context = v8::Context::New(isolate); + if (!RunExtraCode(isolate, context, warmup_source, "<warm-up>")) { + return {}; + } + } + { + v8::HandleScope handle_scope(isolate); + isolate->ContextDisposedNotification(false); + v8::Local<v8::Context> context = v8::Context::New(isolate); + snapshot_creator.SetDefaultContext(context); + } + + return snapshot_creator.CreateBlob( + v8::SnapshotCreator::FunctionCodeHandling::kKeep); } } // namespace internal diff --git a/deps/v8/src/snapshot/snapshot-external.cc b/deps/v8/src/snapshot/snapshot-external.cc index c5f56ebb5a..d77ddae2aa 100644 --- a/deps/v8/src/snapshot/snapshot-external.cc +++ b/deps/v8/src/snapshot/snapshot-external.cc @@ -7,9 +7,8 @@ #include "src/snapshot/snapshot.h" #include "src/base/platform/mutex.h" +#include "src/init/v8.h" // for V8::Initialize #include "src/snapshot/snapshot-source-sink.h" -#include "src/v8.h" // for V8::Initialize - #ifndef V8_USE_EXTERNAL_STARTUP_DATA #error snapshot-external.cc is used only for the external snapshot build. diff --git a/deps/v8/src/snapshot/snapshot-source-sink.cc b/deps/v8/src/snapshot/snapshot-source-sink.cc index ffc6ad0973..e39e2b393c 100644 --- a/deps/v8/src/snapshot/snapshot-source-sink.cc +++ b/deps/v8/src/snapshot/snapshot-source-sink.cc @@ -6,8 +6,8 @@ #include "src/snapshot/snapshot-source-sink.h" #include "src/base/logging.h" -#include "src/handles-inl.h" -#include "src/objects-inl.h" +#include "src/handles/handles-inl.h" +#include "src/objects/objects-inl.h" namespace v8 { namespace internal { diff --git a/deps/v8/src/snapshot/snapshot-source-sink.h b/deps/v8/src/snapshot/snapshot-source-sink.h index f5b35b174e..61396aaa71 100644 --- a/deps/v8/src/snapshot/snapshot-source-sink.h +++ b/deps/v8/src/snapshot/snapshot-source-sink.h @@ -6,7 +6,7 @@ #define V8_SNAPSHOT_SNAPSHOT_SOURCE_SINK_H_ #include "src/base/logging.h" -#include "src/utils.h" +#include "src/utils/utils.h" namespace v8 { namespace internal { @@ -25,7 +25,7 @@ class SnapshotByteSource final { position_(0) {} explicit SnapshotByteSource(Vector<const byte> payload) - : data_(payload.start()), length_(payload.length()), position_(0) {} + : data_(payload.begin()), length_(payload.length()), position_(0) {} ~SnapshotByteSource() = default; diff --git a/deps/v8/src/snapshot/snapshot.h b/deps/v8/src/snapshot/snapshot.h index 3f50f1060e..a9995b2d3e 100644 --- a/deps/v8/src/snapshot/snapshot.h +++ b/deps/v8/src/snapshot/snapshot.h @@ -8,8 +8,7 @@ #include "src/snapshot/partial-serializer.h" #include "src/snapshot/startup-serializer.h" -#include "src/objects-inl.h" -#include "src/utils.h" +#include "src/utils/utils.h" namespace v8 { namespace internal { @@ -163,7 +162,12 @@ class Snapshot : public AllStatic { // mksnapshot. V8_EXPORT_PRIVATE v8::StartupData CreateSnapshotDataBlobInternal( v8::SnapshotCreator::FunctionCodeHandling function_code_handling, - const char* embedded_source); + const char* embedded_source, v8::Isolate* isolate = nullptr); + +// Convenience wrapper around snapshot data blob warmup used e.g. by tests and +// mksnapshot. +V8_EXPORT_PRIVATE v8::StartupData WarmUpSnapshotDataBlobInternal( + v8::StartupData cold_snapshot_blob, const char* warmup_source); #ifdef V8_USE_EXTERNAL_STARTUP_DATA void SetSnapshotFromFile(StartupData* snapshot_blob); diff --git a/deps/v8/src/snapshot/startup-deserializer.cc b/deps/v8/src/snapshot/startup-deserializer.cc index 65def345ce..168bc678fe 100644 --- a/deps/v8/src/snapshot/startup-deserializer.cc +++ b/deps/v8/src/snapshot/startup-deserializer.cc @@ -4,11 +4,11 @@ #include "src/snapshot/startup-deserializer.h" -#include "src/api.h" -#include "src/assembler-inl.h" +#include "src/api/api.h" +#include "src/codegen/assembler-inl.h" +#include "src/execution/v8threads.h" #include "src/heap/heap-inl.h" #include "src/snapshot/snapshot.h" -#include "src/v8threads.h" namespace v8 { namespace internal { diff --git a/deps/v8/src/snapshot/startup-serializer.cc b/deps/v8/src/snapshot/startup-serializer.cc index 47b3f0f41b..62a786f984 100644 --- a/deps/v8/src/snapshot/startup-serializer.cc +++ b/deps/v8/src/snapshot/startup-serializer.cc @@ -4,18 +4,17 @@ #include "src/snapshot/startup-serializer.h" -#include "src/api.h" -#include "src/code-tracer.h" -#include "src/contexts.h" -#include "src/deoptimizer.h" -#include "src/global-handles.h" +#include "src/api/api.h" +#include "src/deoptimizer/deoptimizer.h" +#include "src/execution/v8threads.h" +#include "src/handles/global-handles.h" #include "src/heap/heap-inl.h" #include "src/heap/read-only-heap.h" -#include "src/objects-inl.h" +#include "src/objects/contexts.h" #include "src/objects/foreign-inl.h" +#include "src/objects/objects-inl.h" #include "src/objects/slots.h" #include "src/snapshot/read-only-serializer.h" -#include "src/v8threads.h" namespace v8 { namespace internal { @@ -37,25 +36,25 @@ StartupSerializer::~StartupSerializer() { namespace { bool IsUnexpectedCodeObject(Isolate* isolate, HeapObject obj) { - if (!obj->IsCode()) return false; + if (!obj.IsCode()) return false; Code code = Code::cast(obj); // TODO(v8:8768): Deopt entry code should not be serialized. - if (code->kind() == Code::STUB && isolate->deoptimizer_data() != nullptr) { + if (code.kind() == Code::STUB && isolate->deoptimizer_data() != nullptr) { if (isolate->deoptimizer_data()->IsDeoptEntryCode(code)) return false; } - if (code->kind() == Code::REGEXP) return false; - if (!code->is_builtin()) return true; + if (code.kind() == Code::REGEXP) return false; + if (!code.is_builtin()) return true; if (!FLAG_embedded_builtins) return false; - if (code->is_off_heap_trampoline()) return false; + if (code.is_off_heap_trampoline()) return false; // An on-heap builtin. We only expect this for the interpreter entry // trampoline copy stored on the root list and transitively called builtins. // See Heap::interpreter_entry_trampoline_for_profiling. - switch (code->builtin_index()) { + switch (code.builtin_index()) { case Builtins::kAbort: case Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit: case Builtins::kInterpreterEntryTrampoline: @@ -72,16 +71,7 @@ bool IsUnexpectedCodeObject(Isolate* isolate, HeapObject obj) { #endif // DEBUG void StartupSerializer::SerializeObject(HeapObject obj) { -#ifdef DEBUG - if (obj.IsJSFunction()) { - v8::base::OS::PrintError("Reference stack:\n"); - PrintStack(std::cerr); - obj.Print(std::cerr); - FATAL( - "JSFunction should be added through the context snapshot instead of " - "the isolate snapshot"); - } -#endif // DEBUG + DCHECK(!obj.IsJSFunction()); DCHECK(!IsUnexpectedCodeObject(isolate(), obj)); if (SerializeHotObject(obj)) return; @@ -94,26 +84,25 @@ void StartupSerializer::SerializeObject(HeapObject obj) { use_simulator = true; #endif - if (use_simulator && obj->IsAccessorInfo()) { + if (use_simulator && obj.IsAccessorInfo()) { // Wipe external reference redirects in the accessor info. AccessorInfo info = AccessorInfo::cast(obj); - Address original_address = Foreign::cast(info->getter())->foreign_address(); - Foreign::cast(info->js_getter())->set_foreign_address(original_address); + Address original_address = Foreign::cast(info.getter()).foreign_address(); + Foreign::cast(info.js_getter()).set_foreign_address(original_address); accessor_infos_.push_back(info); - } else if (use_simulator && obj->IsCallHandlerInfo()) { + } else if (use_simulator && obj.IsCallHandlerInfo()) { CallHandlerInfo info = CallHandlerInfo::cast(obj); - Address original_address = - Foreign::cast(info->callback())->foreign_address(); - Foreign::cast(info->js_callback())->set_foreign_address(original_address); + Address original_address = Foreign::cast(info.callback()).foreign_address(); + Foreign::cast(info.js_callback()).set_foreign_address(original_address); call_handler_infos_.push_back(info); - } else if (obj->IsScript() && Script::cast(obj)->IsUserJavaScript()) { - Script::cast(obj)->set_context_data( + } else if (obj.IsScript() && Script::cast(obj).IsUserJavaScript()) { + Script::cast(obj).set_context_data( ReadOnlyRoots(isolate()).uninitialized_symbol()); - } else if (obj->IsSharedFunctionInfo()) { + } else if (obj.IsSharedFunctionInfo()) { // Clear inferred name for native functions. SharedFunctionInfo shared = SharedFunctionInfo::cast(obj); - if (!shared->IsSubjectToDebugging() && shared->HasUncompiledData()) { - shared->uncompiled_data()->set_inferred_name( + if (!shared.IsSubjectToDebugging() && shared.HasUncompiledData()) { + shared.uncompiled_data().set_inferred_name( ReadOnlyRoots(isolate()).empty_string()); } } @@ -160,7 +149,7 @@ SerializedHandleChecker::SerializedHandleChecker(Isolate* isolate, : isolate_(isolate) { AddToSet(isolate->heap()->serialized_objects()); for (auto const& context : *contexts) { - AddToSet(context->serialized_objects()); + AddToSet(context.serialized_objects()); } } @@ -177,8 +166,8 @@ void StartupSerializer::SerializeUsingPartialSnapshotCache( } void SerializedHandleChecker::AddToSet(FixedArray serialized) { - int length = serialized->length(); - for (int i = 0; i < length; i++) serialized_.insert(serialized->get(i)); + int length = serialized.length(); + for (int i = 0; i < length; i++) serialized_.insert(serialized.get(i)); } void SerializedHandleChecker::VisitRootPointers(Root root, @@ -189,7 +178,7 @@ void SerializedHandleChecker::VisitRootPointers(Root root, if (serialized_.find(*p) != serialized_.end()) continue; PrintF("%s handle not serialized: ", root == Root::kGlobalHandles ? "global" : "eternal"); - (*p)->Print(); + (*p).Print(); ok_ = false; } } |