11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/snapshot/code-serializer.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <memory> 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "src/base/logging.h" 101cb0ef41Sopenharmony_ci#include "src/base/platform/elapsed-timer.h" 111cb0ef41Sopenharmony_ci#include "src/base/platform/platform.h" 121cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h" 131cb0ef41Sopenharmony_ci#include "src/common/globals.h" 141cb0ef41Sopenharmony_ci#include "src/debug/debug.h" 151cb0ef41Sopenharmony_ci#include "src/handles/maybe-handles.h" 161cb0ef41Sopenharmony_ci#include "src/handles/persistent-handles.h" 171cb0ef41Sopenharmony_ci#include "src/heap/heap-inl.h" 181cb0ef41Sopenharmony_ci#include "src/heap/local-factory-inl.h" 191cb0ef41Sopenharmony_ci#include "src/heap/parked-scope.h" 201cb0ef41Sopenharmony_ci#include "src/logging/counters-scopes.h" 211cb0ef41Sopenharmony_ci#include "src/logging/log.h" 221cb0ef41Sopenharmony_ci#include "src/logging/runtime-call-stats-scope.h" 231cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 241cb0ef41Sopenharmony_ci#include "src/objects/shared-function-info.h" 251cb0ef41Sopenharmony_ci#include "src/objects/slots.h" 261cb0ef41Sopenharmony_ci#include "src/objects/visitors.h" 271cb0ef41Sopenharmony_ci#include "src/snapshot/object-deserializer.h" 281cb0ef41Sopenharmony_ci#include "src/snapshot/snapshot-utils.h" 291cb0ef41Sopenharmony_ci#include "src/snapshot/snapshot.h" 301cb0ef41Sopenharmony_ci#include "src/utils/version.h" 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_cinamespace v8 { 331cb0ef41Sopenharmony_cinamespace internal { 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ciAlignedCachedData::AlignedCachedData(const byte* data, int length) 361cb0ef41Sopenharmony_ci : owns_data_(false), rejected_(false), data_(data), length_(length) { 371cb0ef41Sopenharmony_ci if (!IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)) { 381cb0ef41Sopenharmony_ci byte* copy = NewArray<byte>(length); 391cb0ef41Sopenharmony_ci DCHECK(IsAligned(reinterpret_cast<intptr_t>(copy), kPointerAlignment)); 401cb0ef41Sopenharmony_ci CopyBytes(copy, data, length); 411cb0ef41Sopenharmony_ci data_ = copy; 421cb0ef41Sopenharmony_ci AcquireDataOwnership(); 431cb0ef41Sopenharmony_ci } 441cb0ef41Sopenharmony_ci} 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ciCodeSerializer::CodeSerializer(Isolate* isolate, uint32_t source_hash) 471cb0ef41Sopenharmony_ci : Serializer(isolate, Snapshot::kDefaultSerializerFlags), 481cb0ef41Sopenharmony_ci source_hash_(source_hash) {} 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci// static 511cb0ef41Sopenharmony_ciScriptCompiler::CachedData* CodeSerializer::Serialize( 521cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> info) { 531cb0ef41Sopenharmony_ci Isolate* isolate = info->GetIsolate(); 541cb0ef41Sopenharmony_ci TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.Execute"); 551cb0ef41Sopenharmony_ci NestedTimedHistogramScope histogram_timer( 561cb0ef41Sopenharmony_ci isolate->counters()->compile_serialize()); 571cb0ef41Sopenharmony_ci RCS_SCOPE(isolate, RuntimeCallCounterId::kCompileSerialize); 581cb0ef41Sopenharmony_ci TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileSerialize"); 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci base::ElapsedTimer timer; 611cb0ef41Sopenharmony_ci if (FLAG_profile_deserialization) timer.Start(); 621cb0ef41Sopenharmony_ci Handle<Script> script(Script::cast(info->script()), isolate); 631cb0ef41Sopenharmony_ci if (FLAG_trace_serializer) { 641cb0ef41Sopenharmony_ci PrintF("[Serializing from"); 651cb0ef41Sopenharmony_ci script->name().ShortPrint(); 661cb0ef41Sopenharmony_ci PrintF("]\n"); 671cb0ef41Sopenharmony_ci } 681cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 691cb0ef41Sopenharmony_ci // TODO(7110): Enable serialization of Asm modules once the AsmWasmData is 701cb0ef41Sopenharmony_ci // context independent. 711cb0ef41Sopenharmony_ci if (script->ContainsAsmModule()) return nullptr; 721cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci // Serialize code object. 751cb0ef41Sopenharmony_ci Handle<String> source(String::cast(script->source()), isolate); 761cb0ef41Sopenharmony_ci HandleScope scope(isolate); 771cb0ef41Sopenharmony_ci CodeSerializer cs(isolate, SerializedCodeData::SourceHash( 781cb0ef41Sopenharmony_ci source, script->origin_options())); 791cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 801cb0ef41Sopenharmony_ci cs.reference_map()->AddAttachedReference(*source); 811cb0ef41Sopenharmony_ci AlignedCachedData* cached_data = cs.SerializeSharedFunctionInfo(info); 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci if (FLAG_profile_deserialization) { 841cb0ef41Sopenharmony_ci double ms = timer.Elapsed().InMillisecondsF(); 851cb0ef41Sopenharmony_ci int length = cached_data->length(); 861cb0ef41Sopenharmony_ci PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci ScriptCompiler::CachedData* result = 901cb0ef41Sopenharmony_ci new ScriptCompiler::CachedData(cached_data->data(), cached_data->length(), 911cb0ef41Sopenharmony_ci ScriptCompiler::CachedData::BufferOwned); 921cb0ef41Sopenharmony_ci cached_data->ReleaseDataOwnership(); 931cb0ef41Sopenharmony_ci delete cached_data; 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci return result; 961cb0ef41Sopenharmony_ci} 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ciAlignedCachedData* CodeSerializer::SerializeSharedFunctionInfo( 991cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> info) { 1001cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci VisitRootPointer(Root::kHandleScope, nullptr, 1031cb0ef41Sopenharmony_ci FullObjectSlot(info.location())); 1041cb0ef41Sopenharmony_ci SerializeDeferredObjects(); 1051cb0ef41Sopenharmony_ci Pad(); 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci SerializedCodeData data(sink_.data(), this); 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci return data.GetScriptData(); 1101cb0ef41Sopenharmony_ci} 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_cibool CodeSerializer::SerializeReadOnlyObject( 1131cb0ef41Sopenharmony_ci HeapObject obj, const DisallowGarbageCollection& no_gc) { 1141cb0ef41Sopenharmony_ci if (!ReadOnlyHeap::Contains(obj)) return false; 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci // For objects on the read-only heap, never serialize the object, but instead 1171cb0ef41Sopenharmony_ci // create a back reference that encodes the page number as the chunk_index and 1181cb0ef41Sopenharmony_ci // the offset within the page as the chunk_offset. 1191cb0ef41Sopenharmony_ci Address address = obj.address(); 1201cb0ef41Sopenharmony_ci BasicMemoryChunk* chunk = BasicMemoryChunk::FromAddress(address); 1211cb0ef41Sopenharmony_ci uint32_t chunk_index = 0; 1221cb0ef41Sopenharmony_ci ReadOnlySpace* const read_only_space = isolate()->heap()->read_only_space(); 1231cb0ef41Sopenharmony_ci for (ReadOnlyPage* page : read_only_space->pages()) { 1241cb0ef41Sopenharmony_ci if (chunk == page) break; 1251cb0ef41Sopenharmony_ci ++chunk_index; 1261cb0ef41Sopenharmony_ci } 1271cb0ef41Sopenharmony_ci uint32_t chunk_offset = static_cast<uint32_t>(chunk->Offset(address)); 1281cb0ef41Sopenharmony_ci sink_.Put(kReadOnlyHeapRef, "ReadOnlyHeapRef"); 1291cb0ef41Sopenharmony_ci sink_.PutInt(chunk_index, "ReadOnlyHeapRefChunkIndex"); 1301cb0ef41Sopenharmony_ci sink_.PutInt(chunk_offset, "ReadOnlyHeapRefChunkOffset"); 1311cb0ef41Sopenharmony_ci return true; 1321cb0ef41Sopenharmony_ci} 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_civoid CodeSerializer::SerializeObjectImpl(Handle<HeapObject> obj) { 1351cb0ef41Sopenharmony_ci ReadOnlyRoots roots(isolate()); 1361cb0ef41Sopenharmony_ci InstanceType instance_type; 1371cb0ef41Sopenharmony_ci { 1381cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 1391cb0ef41Sopenharmony_ci HeapObject raw = *obj; 1401cb0ef41Sopenharmony_ci if (SerializeHotObject(raw)) return; 1411cb0ef41Sopenharmony_ci if (SerializeRoot(raw)) return; 1421cb0ef41Sopenharmony_ci if (SerializeBackReference(raw)) return; 1431cb0ef41Sopenharmony_ci if (SerializeReadOnlyObject(raw, no_gc)) return; 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci instance_type = raw.map().instance_type(); 1461cb0ef41Sopenharmony_ci CHECK(!InstanceTypeChecker::IsCode(instance_type)); 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci if (ElideObject(raw)) { 1491cb0ef41Sopenharmony_ci AllowGarbageCollection allow_gc; 1501cb0ef41Sopenharmony_ci return SerializeObject(roots.undefined_value_handle()); 1511cb0ef41Sopenharmony_ci } 1521cb0ef41Sopenharmony_ci } 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci if (InstanceTypeChecker::IsScript(instance_type)) { 1551cb0ef41Sopenharmony_ci Handle<FixedArray> host_options; 1561cb0ef41Sopenharmony_ci Handle<Object> context_data; 1571cb0ef41Sopenharmony_ci { 1581cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 1591cb0ef41Sopenharmony_ci Script script_obj = Script::cast(*obj); 1601cb0ef41Sopenharmony_ci DCHECK_NE(script_obj.compilation_type(), Script::COMPILATION_TYPE_EVAL); 1611cb0ef41Sopenharmony_ci // We want to differentiate between undefined and uninitialized_symbol for 1621cb0ef41Sopenharmony_ci // context_data for now. It is hack to allow debugging for scripts that 1631cb0ef41Sopenharmony_ci // are included as a part of custom snapshot. (see 1641cb0ef41Sopenharmony_ci // debug::Script::IsEmbedded()) 1651cb0ef41Sopenharmony_ci Object raw_context_data = script_obj.context_data(); 1661cb0ef41Sopenharmony_ci if (raw_context_data != roots.undefined_value() && 1671cb0ef41Sopenharmony_ci raw_context_data != roots.uninitialized_symbol()) { 1681cb0ef41Sopenharmony_ci script_obj.set_context_data(roots.undefined_value()); 1691cb0ef41Sopenharmony_ci } 1701cb0ef41Sopenharmony_ci context_data = handle(raw_context_data, isolate()); 1711cb0ef41Sopenharmony_ci // We don't want to serialize host options to avoid serializing 1721cb0ef41Sopenharmony_ci // unnecessary object graph. 1731cb0ef41Sopenharmony_ci host_options = handle(script_obj.host_defined_options(), isolate()); 1741cb0ef41Sopenharmony_ci script_obj.set_host_defined_options(roots.empty_fixed_array()); 1751cb0ef41Sopenharmony_ci } 1761cb0ef41Sopenharmony_ci SerializeGeneric(obj); 1771cb0ef41Sopenharmony_ci { 1781cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 1791cb0ef41Sopenharmony_ci Script script_obj = Script::cast(*obj); 1801cb0ef41Sopenharmony_ci script_obj.set_host_defined_options(*host_options); 1811cb0ef41Sopenharmony_ci script_obj.set_context_data(*context_data); 1821cb0ef41Sopenharmony_ci } 1831cb0ef41Sopenharmony_ci return; 1841cb0ef41Sopenharmony_ci } else if (InstanceTypeChecker::IsSharedFunctionInfo(instance_type)) { 1851cb0ef41Sopenharmony_ci Handle<DebugInfo> debug_info; 1861cb0ef41Sopenharmony_ci bool restore_bytecode = false; 1871cb0ef41Sopenharmony_ci { 1881cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 1891cb0ef41Sopenharmony_ci SharedFunctionInfo sfi = SharedFunctionInfo::cast(*obj); 1901cb0ef41Sopenharmony_ci DCHECK(!sfi.IsApiFunction()); 1911cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 1921cb0ef41Sopenharmony_ci // TODO(7110): Enable serializing of Asm modules once the AsmWasmData 1931cb0ef41Sopenharmony_ci // is context independent. 1941cb0ef41Sopenharmony_ci DCHECK(!sfi.HasAsmWasmData()); 1951cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci if (sfi.HasDebugInfo()) { 1981cb0ef41Sopenharmony_ci // Clear debug info. 1991cb0ef41Sopenharmony_ci DebugInfo raw_debug_info = sfi.GetDebugInfo(); 2001cb0ef41Sopenharmony_ci if (raw_debug_info.HasInstrumentedBytecodeArray()) { 2011cb0ef41Sopenharmony_ci restore_bytecode = true; 2021cb0ef41Sopenharmony_ci sfi.SetActiveBytecodeArray(raw_debug_info.OriginalBytecodeArray()); 2031cb0ef41Sopenharmony_ci } 2041cb0ef41Sopenharmony_ci sfi.set_script_or_debug_info(raw_debug_info.script(), kReleaseStore); 2051cb0ef41Sopenharmony_ci debug_info = handle(raw_debug_info, isolate()); 2061cb0ef41Sopenharmony_ci } 2071cb0ef41Sopenharmony_ci DCHECK(!sfi.HasDebugInfo()); 2081cb0ef41Sopenharmony_ci } 2091cb0ef41Sopenharmony_ci SerializeGeneric(obj); 2101cb0ef41Sopenharmony_ci // Restore debug info 2111cb0ef41Sopenharmony_ci if (!debug_info.is_null()) { 2121cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 2131cb0ef41Sopenharmony_ci SharedFunctionInfo sfi = SharedFunctionInfo::cast(*obj); 2141cb0ef41Sopenharmony_ci sfi.set_script_or_debug_info(*debug_info, kReleaseStore); 2151cb0ef41Sopenharmony_ci if (restore_bytecode) { 2161cb0ef41Sopenharmony_ci sfi.SetActiveBytecodeArray(debug_info->DebugBytecodeArray()); 2171cb0ef41Sopenharmony_ci } 2181cb0ef41Sopenharmony_ci } 2191cb0ef41Sopenharmony_ci return; 2201cb0ef41Sopenharmony_ci } else if (InstanceTypeChecker::IsUncompiledDataWithoutPreparseDataWithJob( 2211cb0ef41Sopenharmony_ci instance_type)) { 2221cb0ef41Sopenharmony_ci Handle<UncompiledDataWithoutPreparseDataWithJob> data = 2231cb0ef41Sopenharmony_ci Handle<UncompiledDataWithoutPreparseDataWithJob>::cast(obj); 2241cb0ef41Sopenharmony_ci Address job = data->job(); 2251cb0ef41Sopenharmony_ci data->set_job(kNullAddress); 2261cb0ef41Sopenharmony_ci SerializeGeneric(data); 2271cb0ef41Sopenharmony_ci data->set_job(job); 2281cb0ef41Sopenharmony_ci return; 2291cb0ef41Sopenharmony_ci } else if (InstanceTypeChecker::IsUncompiledDataWithPreparseDataAndJob( 2301cb0ef41Sopenharmony_ci instance_type)) { 2311cb0ef41Sopenharmony_ci Handle<UncompiledDataWithPreparseDataAndJob> data = 2321cb0ef41Sopenharmony_ci Handle<UncompiledDataWithPreparseDataAndJob>::cast(obj); 2331cb0ef41Sopenharmony_ci Address job = data->job(); 2341cb0ef41Sopenharmony_ci data->set_job(kNullAddress); 2351cb0ef41Sopenharmony_ci SerializeGeneric(data); 2361cb0ef41Sopenharmony_ci data->set_job(job); 2371cb0ef41Sopenharmony_ci return; 2381cb0ef41Sopenharmony_ci } 2391cb0ef41Sopenharmony_ci 2401cb0ef41Sopenharmony_ci // NOTE(mmarchini): If we try to serialize an InterpreterData our process 2411cb0ef41Sopenharmony_ci // will crash since it stores a code object. Instead, we serialize the 2421cb0ef41Sopenharmony_ci // bytecode array stored within the InterpreterData, which is the important 2431cb0ef41Sopenharmony_ci // information. On deserialization we'll create our code objects again, if 2441cb0ef41Sopenharmony_ci // --interpreted-frames-native-stack is on. See v8:9122 for more context 2451cb0ef41Sopenharmony_ci#ifndef V8_TARGET_ARCH_ARM 2461cb0ef41Sopenharmony_ci if (V8_UNLIKELY(FLAG_interpreted_frames_native_stack) && 2471cb0ef41Sopenharmony_ci obj->IsInterpreterData()) { 2481cb0ef41Sopenharmony_ci obj = handle(InterpreterData::cast(*obj).bytecode_array(), isolate()); 2491cb0ef41Sopenharmony_ci } 2501cb0ef41Sopenharmony_ci#endif // V8_TARGET_ARCH_ARM 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_ci // Past this point we should not see any (context-specific) maps anymore. 2531cb0ef41Sopenharmony_ci CHECK(!InstanceTypeChecker::IsMap(instance_type)); 2541cb0ef41Sopenharmony_ci // There should be no references to the global object embedded. 2551cb0ef41Sopenharmony_ci CHECK(!InstanceTypeChecker::IsJSGlobalProxy(instance_type) && 2561cb0ef41Sopenharmony_ci !InstanceTypeChecker::IsJSGlobalObject(instance_type)); 2571cb0ef41Sopenharmony_ci // Embedded FixedArrays that need rehashing must support rehashing. 2581cb0ef41Sopenharmony_ci CHECK_IMPLIES(obj->NeedsRehashing(cage_base()), 2591cb0ef41Sopenharmony_ci obj->CanBeRehashed(cage_base())); 2601cb0ef41Sopenharmony_ci // We expect no instantiated function objects or contexts. 2611cb0ef41Sopenharmony_ci CHECK(!InstanceTypeChecker::IsJSFunction(instance_type) && 2621cb0ef41Sopenharmony_ci !InstanceTypeChecker::IsContext(instance_type)); 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ci SerializeGeneric(obj); 2651cb0ef41Sopenharmony_ci} 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_civoid CodeSerializer::SerializeGeneric(Handle<HeapObject> heap_object) { 2681cb0ef41Sopenharmony_ci // Object has not yet been serialized. Serialize it here. 2691cb0ef41Sopenharmony_ci ObjectSerializer serializer(this, heap_object, &sink_); 2701cb0ef41Sopenharmony_ci serializer.Serialize(); 2711cb0ef41Sopenharmony_ci} 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_cinamespace { 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci#ifndef V8_TARGET_ARCH_ARM 2761cb0ef41Sopenharmony_ci// NOTE(mmarchini): when FLAG_interpreted_frames_native_stack is on, we want to 2771cb0ef41Sopenharmony_ci// create duplicates of InterpreterEntryTrampoline for the deserialized 2781cb0ef41Sopenharmony_ci// functions, otherwise we'll call the builtin IET for those functions (which 2791cb0ef41Sopenharmony_ci// is not what a user of this flag wants). 2801cb0ef41Sopenharmony_civoid CreateInterpreterDataForDeserializedCode(Isolate* isolate, 2811cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> sfi, 2821cb0ef41Sopenharmony_ci bool log_code_creation) { 2831cb0ef41Sopenharmony_ci Handle<Script> script(Script::cast(sfi->script()), isolate); 2841cb0ef41Sopenharmony_ci String name = ReadOnlyRoots(isolate).empty_string(); 2851cb0ef41Sopenharmony_ci if (script->name().IsString()) name = String::cast(script->name()); 2861cb0ef41Sopenharmony_ci Handle<String> name_handle(name, isolate); 2871cb0ef41Sopenharmony_ci 2881cb0ef41Sopenharmony_ci SharedFunctionInfo::ScriptIterator iter(isolate, *script); 2891cb0ef41Sopenharmony_ci for (SharedFunctionInfo shared_info = iter.Next(); !shared_info.is_null(); 2901cb0ef41Sopenharmony_ci shared_info = iter.Next()) { 2911cb0ef41Sopenharmony_ci IsCompiledScope is_compiled(shared_info, isolate); 2921cb0ef41Sopenharmony_ci if (!is_compiled.is_compiled()) continue; 2931cb0ef41Sopenharmony_ci DCHECK(shared_info.HasBytecodeArray()); 2941cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> info = handle(shared_info, isolate); 2951cb0ef41Sopenharmony_ci Handle<Code> code = isolate->factory()->CopyCode(Handle<Code>::cast( 2961cb0ef41Sopenharmony_ci isolate->factory()->interpreter_entry_trampoline_for_profiling())); 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci Handle<InterpreterData> interpreter_data = 2991cb0ef41Sopenharmony_ci Handle<InterpreterData>::cast(isolate->factory()->NewStruct( 3001cb0ef41Sopenharmony_ci INTERPRETER_DATA_TYPE, AllocationType::kOld)); 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_ci interpreter_data->set_bytecode_array(info->GetBytecodeArray(isolate)); 3031cb0ef41Sopenharmony_ci interpreter_data->set_interpreter_trampoline(ToCodeT(*code)); 3041cb0ef41Sopenharmony_ci if (info->HasBaselineCode()) { 3051cb0ef41Sopenharmony_ci FromCodeT(info->baseline_code(kAcquireLoad)) 3061cb0ef41Sopenharmony_ci .set_bytecode_or_interpreter_data(*interpreter_data); 3071cb0ef41Sopenharmony_ci } else { 3081cb0ef41Sopenharmony_ci info->set_interpreter_data(*interpreter_data); 3091cb0ef41Sopenharmony_ci } 3101cb0ef41Sopenharmony_ci 3111cb0ef41Sopenharmony_ci if (!log_code_creation) continue; 3121cb0ef41Sopenharmony_ci Handle<AbstractCode> abstract_code = Handle<AbstractCode>::cast(code); 3131cb0ef41Sopenharmony_ci int line_num = script->GetLineNumber(info->StartPosition()) + 1; 3141cb0ef41Sopenharmony_ci int column_num = script->GetColumnNumber(info->StartPosition()) + 1; 3151cb0ef41Sopenharmony_ci PROFILE(isolate, 3161cb0ef41Sopenharmony_ci CodeCreateEvent(CodeEventListener::FUNCTION_TAG, abstract_code, 3171cb0ef41Sopenharmony_ci info, name_handle, line_num, column_num)); 3181cb0ef41Sopenharmony_ci } 3191cb0ef41Sopenharmony_ci} 3201cb0ef41Sopenharmony_ci#endif // V8_TARGET_ARCH_ARM 3211cb0ef41Sopenharmony_ci 3221cb0ef41Sopenharmony_ciclass StressOffThreadDeserializeThread final : public base::Thread { 3231cb0ef41Sopenharmony_ci public: 3241cb0ef41Sopenharmony_ci explicit StressOffThreadDeserializeThread(Isolate* isolate, 3251cb0ef41Sopenharmony_ci AlignedCachedData* cached_data) 3261cb0ef41Sopenharmony_ci : Thread( 3271cb0ef41Sopenharmony_ci base::Thread::Options("StressOffThreadDeserializeThread", 2 * MB)), 3281cb0ef41Sopenharmony_ci isolate_(isolate), 3291cb0ef41Sopenharmony_ci cached_data_(cached_data) {} 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_ci void Run() final { 3321cb0ef41Sopenharmony_ci LocalIsolate local_isolate(isolate_, ThreadKind::kBackground); 3331cb0ef41Sopenharmony_ci UnparkedScope unparked_scope(&local_isolate); 3341cb0ef41Sopenharmony_ci LocalHandleScope handle_scope(&local_isolate); 3351cb0ef41Sopenharmony_ci off_thread_data_ = 3361cb0ef41Sopenharmony_ci CodeSerializer::StartDeserializeOffThread(&local_isolate, cached_data_); 3371cb0ef41Sopenharmony_ci } 3381cb0ef41Sopenharmony_ci 3391cb0ef41Sopenharmony_ci MaybeHandle<SharedFunctionInfo> Finalize(Isolate* isolate, 3401cb0ef41Sopenharmony_ci Handle<String> source, 3411cb0ef41Sopenharmony_ci ScriptOriginOptions origin_options) { 3421cb0ef41Sopenharmony_ci return CodeSerializer::FinishOffThreadDeserialize( 3431cb0ef41Sopenharmony_ci isolate, std::move(off_thread_data_), cached_data_, source, 3441cb0ef41Sopenharmony_ci origin_options); 3451cb0ef41Sopenharmony_ci } 3461cb0ef41Sopenharmony_ci 3471cb0ef41Sopenharmony_ci private: 3481cb0ef41Sopenharmony_ci Isolate* isolate_; 3491cb0ef41Sopenharmony_ci AlignedCachedData* cached_data_; 3501cb0ef41Sopenharmony_ci CodeSerializer::OffThreadDeserializeData off_thread_data_; 3511cb0ef41Sopenharmony_ci}; 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_civoid FinalizeDeserialization(Isolate* isolate, 3541cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> result, 3551cb0ef41Sopenharmony_ci const base::ElapsedTimer& timer) { 3561cb0ef41Sopenharmony_ci const bool log_code_creation = 3571cb0ef41Sopenharmony_ci isolate->logger()->is_listening_to_code_events() || 3581cb0ef41Sopenharmony_ci isolate->is_profiling() || 3591cb0ef41Sopenharmony_ci isolate->code_event_dispatcher()->IsListeningToCodeEvents(); 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_ci#ifndef V8_TARGET_ARCH_ARM 3621cb0ef41Sopenharmony_ci if (V8_UNLIKELY(FLAG_interpreted_frames_native_stack)) 3631cb0ef41Sopenharmony_ci CreateInterpreterDataForDeserializedCode(isolate, result, 3641cb0ef41Sopenharmony_ci log_code_creation); 3651cb0ef41Sopenharmony_ci#endif // V8_TARGET_ARCH_ARM 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ci bool needs_source_positions = isolate->NeedsSourcePositionsForProfiling(); 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_ci if (log_code_creation || FLAG_log_function_events) { 3701cb0ef41Sopenharmony_ci Handle<Script> script(Script::cast(result->script()), isolate); 3711cb0ef41Sopenharmony_ci Handle<String> name(script->name().IsString() 3721cb0ef41Sopenharmony_ci ? String::cast(script->name()) 3731cb0ef41Sopenharmony_ci : ReadOnlyRoots(isolate).empty_string(), 3741cb0ef41Sopenharmony_ci isolate); 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci if (FLAG_log_function_events) { 3771cb0ef41Sopenharmony_ci LOG(isolate, 3781cb0ef41Sopenharmony_ci FunctionEvent("deserialize", script->id(), 3791cb0ef41Sopenharmony_ci timer.Elapsed().InMillisecondsF(), 3801cb0ef41Sopenharmony_ci result->StartPosition(), result->EndPosition(), *name)); 3811cb0ef41Sopenharmony_ci } 3821cb0ef41Sopenharmony_ci if (log_code_creation) { 3831cb0ef41Sopenharmony_ci Script::InitLineEnds(isolate, script); 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci SharedFunctionInfo::ScriptIterator iter(isolate, *script); 3861cb0ef41Sopenharmony_ci for (SharedFunctionInfo info = iter.Next(); !info.is_null(); 3871cb0ef41Sopenharmony_ci info = iter.Next()) { 3881cb0ef41Sopenharmony_ci if (info.is_compiled()) { 3891cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> shared_info(info, isolate); 3901cb0ef41Sopenharmony_ci if (needs_source_positions) { 3911cb0ef41Sopenharmony_ci SharedFunctionInfo::EnsureSourcePositionsAvailable(isolate, 3921cb0ef41Sopenharmony_ci shared_info); 3931cb0ef41Sopenharmony_ci } 3941cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 3951cb0ef41Sopenharmony_ci int line_num = 3961cb0ef41Sopenharmony_ci script->GetLineNumber(shared_info->StartPosition()) + 1; 3971cb0ef41Sopenharmony_ci int column_num = 3981cb0ef41Sopenharmony_ci script->GetColumnNumber(shared_info->StartPosition()) + 1; 3991cb0ef41Sopenharmony_ci PROFILE( 4001cb0ef41Sopenharmony_ci isolate, 4011cb0ef41Sopenharmony_ci CodeCreateEvent( 4021cb0ef41Sopenharmony_ci shared_info->is_toplevel() ? CodeEventListener::SCRIPT_TAG 4031cb0ef41Sopenharmony_ci : CodeEventListener::FUNCTION_TAG, 4041cb0ef41Sopenharmony_ci handle(shared_info->abstract_code(isolate), isolate), 4051cb0ef41Sopenharmony_ci shared_info, name, line_num, column_num)); 4061cb0ef41Sopenharmony_ci } 4071cb0ef41Sopenharmony_ci } 4081cb0ef41Sopenharmony_ci } 4091cb0ef41Sopenharmony_ci } 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_ci if (needs_source_positions) { 4121cb0ef41Sopenharmony_ci Handle<Script> script(Script::cast(result->script()), isolate); 4131cb0ef41Sopenharmony_ci Script::InitLineEnds(isolate, script); 4141cb0ef41Sopenharmony_ci } 4151cb0ef41Sopenharmony_ci} 4161cb0ef41Sopenharmony_ci 4171cb0ef41Sopenharmony_ci} // namespace 4181cb0ef41Sopenharmony_ci 4191cb0ef41Sopenharmony_ciMaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( 4201cb0ef41Sopenharmony_ci Isolate* isolate, AlignedCachedData* cached_data, Handle<String> source, 4211cb0ef41Sopenharmony_ci ScriptOriginOptions origin_options) { 4221cb0ef41Sopenharmony_ci if (FLAG_stress_background_compile) { 4231cb0ef41Sopenharmony_ci StressOffThreadDeserializeThread thread(isolate, cached_data); 4241cb0ef41Sopenharmony_ci CHECK(thread.Start()); 4251cb0ef41Sopenharmony_ci thread.Join(); 4261cb0ef41Sopenharmony_ci return thread.Finalize(isolate, source, origin_options); 4271cb0ef41Sopenharmony_ci // TODO(leszeks): Compare off-thread deserialized data to on-thread. 4281cb0ef41Sopenharmony_ci } 4291cb0ef41Sopenharmony_ci 4301cb0ef41Sopenharmony_ci base::ElapsedTimer timer; 4311cb0ef41Sopenharmony_ci if (FLAG_profile_deserialization || FLAG_log_function_events) timer.Start(); 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_ci HandleScope scope(isolate); 4341cb0ef41Sopenharmony_ci 4351cb0ef41Sopenharmony_ci SerializedCodeSanityCheckResult sanity_check_result = 4361cb0ef41Sopenharmony_ci SerializedCodeSanityCheckResult::kSuccess; 4371cb0ef41Sopenharmony_ci const SerializedCodeData scd = SerializedCodeData::FromCachedData( 4381cb0ef41Sopenharmony_ci cached_data, SerializedCodeData::SourceHash(source, origin_options), 4391cb0ef41Sopenharmony_ci &sanity_check_result); 4401cb0ef41Sopenharmony_ci if (sanity_check_result != SerializedCodeSanityCheckResult::kSuccess) { 4411cb0ef41Sopenharmony_ci if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n"); 4421cb0ef41Sopenharmony_ci DCHECK(cached_data->rejected()); 4431cb0ef41Sopenharmony_ci isolate->counters()->code_cache_reject_reason()->AddSample( 4441cb0ef41Sopenharmony_ci static_cast<int>(sanity_check_result)); 4451cb0ef41Sopenharmony_ci return MaybeHandle<SharedFunctionInfo>(); 4461cb0ef41Sopenharmony_ci } 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_ci // Deserialize. 4491cb0ef41Sopenharmony_ci MaybeHandle<SharedFunctionInfo> maybe_result = 4501cb0ef41Sopenharmony_ci ObjectDeserializer::DeserializeSharedFunctionInfo(isolate, &scd, source); 4511cb0ef41Sopenharmony_ci 4521cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> result; 4531cb0ef41Sopenharmony_ci if (!maybe_result.ToHandle(&result)) { 4541cb0ef41Sopenharmony_ci // Deserializing may fail if the reservations cannot be fulfilled. 4551cb0ef41Sopenharmony_ci if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n"); 4561cb0ef41Sopenharmony_ci return MaybeHandle<SharedFunctionInfo>(); 4571cb0ef41Sopenharmony_ci } 4581cb0ef41Sopenharmony_ci 4591cb0ef41Sopenharmony_ci if (FLAG_profile_deserialization) { 4601cb0ef41Sopenharmony_ci double ms = timer.Elapsed().InMillisecondsF(); 4611cb0ef41Sopenharmony_ci int length = cached_data->length(); 4621cb0ef41Sopenharmony_ci PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms); 4631cb0ef41Sopenharmony_ci } 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci FinalizeDeserialization(isolate, result, timer); 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_ci return scope.CloseAndEscape(result); 4681cb0ef41Sopenharmony_ci} 4691cb0ef41Sopenharmony_ci 4701cb0ef41Sopenharmony_ciCodeSerializer::OffThreadDeserializeData 4711cb0ef41Sopenharmony_ciCodeSerializer::StartDeserializeOffThread(LocalIsolate* local_isolate, 4721cb0ef41Sopenharmony_ci AlignedCachedData* cached_data) { 4731cb0ef41Sopenharmony_ci OffThreadDeserializeData result; 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_ci DCHECK(!local_isolate->heap()->HasPersistentHandles()); 4761cb0ef41Sopenharmony_ci 4771cb0ef41Sopenharmony_ci const SerializedCodeData scd = 4781cb0ef41Sopenharmony_ci SerializedCodeData::FromCachedDataWithoutSource( 4791cb0ef41Sopenharmony_ci cached_data, &result.sanity_check_result); 4801cb0ef41Sopenharmony_ci if (result.sanity_check_result != SerializedCodeSanityCheckResult::kSuccess) { 4811cb0ef41Sopenharmony_ci // Exit early but don't report yet, we'll re-check this when finishing on 4821cb0ef41Sopenharmony_ci // the main thread 4831cb0ef41Sopenharmony_ci DCHECK(cached_data->rejected()); 4841cb0ef41Sopenharmony_ci return result; 4851cb0ef41Sopenharmony_ci } 4861cb0ef41Sopenharmony_ci 4871cb0ef41Sopenharmony_ci MaybeHandle<SharedFunctionInfo> local_maybe_result = 4881cb0ef41Sopenharmony_ci OffThreadObjectDeserializer::DeserializeSharedFunctionInfo( 4891cb0ef41Sopenharmony_ci local_isolate, &scd, &result.scripts); 4901cb0ef41Sopenharmony_ci 4911cb0ef41Sopenharmony_ci result.maybe_result = 4921cb0ef41Sopenharmony_ci local_isolate->heap()->NewPersistentMaybeHandle(local_maybe_result); 4931cb0ef41Sopenharmony_ci result.persistent_handles = local_isolate->heap()->DetachPersistentHandles(); 4941cb0ef41Sopenharmony_ci 4951cb0ef41Sopenharmony_ci return result; 4961cb0ef41Sopenharmony_ci} 4971cb0ef41Sopenharmony_ci 4981cb0ef41Sopenharmony_ciMaybeHandle<SharedFunctionInfo> CodeSerializer::FinishOffThreadDeserialize( 4991cb0ef41Sopenharmony_ci Isolate* isolate, OffThreadDeserializeData&& data, 5001cb0ef41Sopenharmony_ci AlignedCachedData* cached_data, Handle<String> source, 5011cb0ef41Sopenharmony_ci ScriptOriginOptions origin_options) { 5021cb0ef41Sopenharmony_ci base::ElapsedTimer timer; 5031cb0ef41Sopenharmony_ci if (FLAG_profile_deserialization || FLAG_log_function_events) timer.Start(); 5041cb0ef41Sopenharmony_ci 5051cb0ef41Sopenharmony_ci HandleScope scope(isolate); 5061cb0ef41Sopenharmony_ci 5071cb0ef41Sopenharmony_ci // Do a source sanity check now that we have the source. It's important for 5081cb0ef41Sopenharmony_ci // FromPartiallySanityCheckedCachedData call that the sanity_check_result 5091cb0ef41Sopenharmony_ci // holds the result of the off-thread sanity check. 5101cb0ef41Sopenharmony_ci SerializedCodeSanityCheckResult sanity_check_result = 5111cb0ef41Sopenharmony_ci data.sanity_check_result; 5121cb0ef41Sopenharmony_ci const SerializedCodeData scd = 5131cb0ef41Sopenharmony_ci SerializedCodeData::FromPartiallySanityCheckedCachedData( 5141cb0ef41Sopenharmony_ci cached_data, SerializedCodeData::SourceHash(source, origin_options), 5151cb0ef41Sopenharmony_ci &sanity_check_result); 5161cb0ef41Sopenharmony_ci if (sanity_check_result != SerializedCodeSanityCheckResult::kSuccess) { 5171cb0ef41Sopenharmony_ci // The only case where the deserialization result could exist despite a 5181cb0ef41Sopenharmony_ci // check failure is on a source mismatch, since we can't test for this 5191cb0ef41Sopenharmony_ci // off-thread. 5201cb0ef41Sopenharmony_ci DCHECK_IMPLIES(!data.maybe_result.is_null(), 5211cb0ef41Sopenharmony_ci sanity_check_result == 5221cb0ef41Sopenharmony_ci SerializedCodeSanityCheckResult::kSourceMismatch); 5231cb0ef41Sopenharmony_ci // The only kind of sanity check we can't test for off-thread is a source 5241cb0ef41Sopenharmony_ci // mismatch. 5251cb0ef41Sopenharmony_ci DCHECK_IMPLIES(sanity_check_result != data.sanity_check_result, 5261cb0ef41Sopenharmony_ci sanity_check_result == 5271cb0ef41Sopenharmony_ci SerializedCodeSanityCheckResult::kSourceMismatch); 5281cb0ef41Sopenharmony_ci if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n"); 5291cb0ef41Sopenharmony_ci DCHECK(cached_data->rejected()); 5301cb0ef41Sopenharmony_ci isolate->counters()->code_cache_reject_reason()->AddSample( 5311cb0ef41Sopenharmony_ci static_cast<int>(sanity_check_result)); 5321cb0ef41Sopenharmony_ci return MaybeHandle<SharedFunctionInfo>(); 5331cb0ef41Sopenharmony_ci } 5341cb0ef41Sopenharmony_ci 5351cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> result; 5361cb0ef41Sopenharmony_ci if (!data.maybe_result.ToHandle(&result)) { 5371cb0ef41Sopenharmony_ci // Deserializing may fail if the reservations cannot be fulfilled. 5381cb0ef41Sopenharmony_ci if (FLAG_profile_deserialization) { 5391cb0ef41Sopenharmony_ci PrintF("[Off-thread deserializing failed]\n"); 5401cb0ef41Sopenharmony_ci } 5411cb0ef41Sopenharmony_ci return MaybeHandle<SharedFunctionInfo>(); 5421cb0ef41Sopenharmony_ci } 5431cb0ef41Sopenharmony_ci 5441cb0ef41Sopenharmony_ci // Change the result persistent handle into a regular handle. 5451cb0ef41Sopenharmony_ci DCHECK(data.persistent_handles->Contains(result.location())); 5461cb0ef41Sopenharmony_ci result = handle(*result, isolate); 5471cb0ef41Sopenharmony_ci 5481cb0ef41Sopenharmony_ci // Fix up the source on the script. This should be the only deserialized 5491cb0ef41Sopenharmony_ci // script, and the off-thread deserializer should have set its source to 5501cb0ef41Sopenharmony_ci // the empty string. 5511cb0ef41Sopenharmony_ci DCHECK_EQ(data.scripts.size(), 1); 5521cb0ef41Sopenharmony_ci DCHECK_EQ(result->script(), *data.scripts[0]); 5531cb0ef41Sopenharmony_ci DCHECK_EQ(Script::cast(result->script()).source(), 5541cb0ef41Sopenharmony_ci ReadOnlyRoots(isolate).empty_string()); 5551cb0ef41Sopenharmony_ci Script::cast(result->script()).set_source(*source); 5561cb0ef41Sopenharmony_ci 5571cb0ef41Sopenharmony_ci // Fix up the script list to include the newly deserialized script. 5581cb0ef41Sopenharmony_ci Handle<WeakArrayList> list = isolate->factory()->script_list(); 5591cb0ef41Sopenharmony_ci for (Handle<Script> script : data.scripts) { 5601cb0ef41Sopenharmony_ci DCHECK(data.persistent_handles->Contains(script.location())); 5611cb0ef41Sopenharmony_ci list = 5621cb0ef41Sopenharmony_ci WeakArrayList::AddToEnd(isolate, list, MaybeObjectHandle::Weak(script)); 5631cb0ef41Sopenharmony_ci } 5641cb0ef41Sopenharmony_ci isolate->heap()->SetRootScriptList(*list); 5651cb0ef41Sopenharmony_ci 5661cb0ef41Sopenharmony_ci if (FLAG_profile_deserialization) { 5671cb0ef41Sopenharmony_ci double ms = timer.Elapsed().InMillisecondsF(); 5681cb0ef41Sopenharmony_ci int length = cached_data->length(); 5691cb0ef41Sopenharmony_ci PrintF("[Finishing off-thread deserialize from %d bytes took %0.3f ms]\n", 5701cb0ef41Sopenharmony_ci length, ms); 5711cb0ef41Sopenharmony_ci } 5721cb0ef41Sopenharmony_ci 5731cb0ef41Sopenharmony_ci FinalizeDeserialization(isolate, result, timer); 5741cb0ef41Sopenharmony_ci 5751cb0ef41Sopenharmony_ci return scope.CloseAndEscape(result); 5761cb0ef41Sopenharmony_ci} 5771cb0ef41Sopenharmony_ci 5781cb0ef41Sopenharmony_ciSerializedCodeData::SerializedCodeData(const std::vector<byte>* payload, 5791cb0ef41Sopenharmony_ci const CodeSerializer* cs) { 5801cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 5811cb0ef41Sopenharmony_ci 5821cb0ef41Sopenharmony_ci // Calculate sizes. 5831cb0ef41Sopenharmony_ci uint32_t size = kHeaderSize + static_cast<uint32_t>(payload->size()); 5841cb0ef41Sopenharmony_ci DCHECK(IsAligned(size, kPointerAlignment)); 5851cb0ef41Sopenharmony_ci 5861cb0ef41Sopenharmony_ci // Allocate backing store and create result data. 5871cb0ef41Sopenharmony_ci AllocateData(size); 5881cb0ef41Sopenharmony_ci 5891cb0ef41Sopenharmony_ci // Zero out pre-payload data. Part of that is only used for padding. 5901cb0ef41Sopenharmony_ci memset(data_, 0, kHeaderSize); 5911cb0ef41Sopenharmony_ci 5921cb0ef41Sopenharmony_ci // Set header values. 5931cb0ef41Sopenharmony_ci SetMagicNumber(); 5941cb0ef41Sopenharmony_ci SetHeaderValue(kVersionHashOffset, Version::Hash()); 5951cb0ef41Sopenharmony_ci SetHeaderValue(kSourceHashOffset, cs->source_hash()); 5961cb0ef41Sopenharmony_ci SetHeaderValue(kFlagHashOffset, FlagList::Hash()); 5971cb0ef41Sopenharmony_ci SetHeaderValue(kPayloadLengthOffset, static_cast<uint32_t>(payload->size())); 5981cb0ef41Sopenharmony_ci 5991cb0ef41Sopenharmony_ci // Zero out any padding in the header. 6001cb0ef41Sopenharmony_ci memset(data_ + kUnalignedHeaderSize, 0, kHeaderSize - kUnalignedHeaderSize); 6011cb0ef41Sopenharmony_ci 6021cb0ef41Sopenharmony_ci // Copy serialized data. 6031cb0ef41Sopenharmony_ci CopyBytes(data_ + kHeaderSize, payload->data(), 6041cb0ef41Sopenharmony_ci static_cast<size_t>(payload->size())); 6051cb0ef41Sopenharmony_ci uint32_t checksum = 6061cb0ef41Sopenharmony_ci FLAG_verify_snapshot_checksum ? Checksum(ChecksummedContent()) : 0; 6071cb0ef41Sopenharmony_ci SetHeaderValue(kChecksumOffset, checksum); 6081cb0ef41Sopenharmony_ci} 6091cb0ef41Sopenharmony_ci 6101cb0ef41Sopenharmony_ciSerializedCodeSanityCheckResult SerializedCodeData::SanityCheck( 6111cb0ef41Sopenharmony_ci uint32_t expected_source_hash) const { 6121cb0ef41Sopenharmony_ci SerializedCodeSanityCheckResult result = SanityCheckWithoutSource(); 6131cb0ef41Sopenharmony_ci if (result != SerializedCodeSanityCheckResult::kSuccess) return result; 6141cb0ef41Sopenharmony_ci return SanityCheckJustSource(expected_source_hash); 6151cb0ef41Sopenharmony_ci} 6161cb0ef41Sopenharmony_ci 6171cb0ef41Sopenharmony_ciSerializedCodeSanityCheckResult SerializedCodeData::SanityCheckJustSource( 6181cb0ef41Sopenharmony_ci uint32_t expected_source_hash) const { 6191cb0ef41Sopenharmony_ci uint32_t source_hash = GetHeaderValue(kSourceHashOffset); 6201cb0ef41Sopenharmony_ci if (source_hash != expected_source_hash) { 6211cb0ef41Sopenharmony_ci return SerializedCodeSanityCheckResult::kSourceMismatch; 6221cb0ef41Sopenharmony_ci } 6231cb0ef41Sopenharmony_ci return SerializedCodeSanityCheckResult::kSuccess; 6241cb0ef41Sopenharmony_ci} 6251cb0ef41Sopenharmony_ci 6261cb0ef41Sopenharmony_ciSerializedCodeSanityCheckResult SerializedCodeData::SanityCheckWithoutSource() 6271cb0ef41Sopenharmony_ci const { 6281cb0ef41Sopenharmony_ci if (this->size_ < kHeaderSize) { 6291cb0ef41Sopenharmony_ci return SerializedCodeSanityCheckResult::kInvalidHeader; 6301cb0ef41Sopenharmony_ci } 6311cb0ef41Sopenharmony_ci uint32_t magic_number = GetMagicNumber(); 6321cb0ef41Sopenharmony_ci if (magic_number != kMagicNumber) { 6331cb0ef41Sopenharmony_ci return SerializedCodeSanityCheckResult::kMagicNumberMismatch; 6341cb0ef41Sopenharmony_ci } 6351cb0ef41Sopenharmony_ci uint32_t version_hash = GetHeaderValue(kVersionHashOffset); 6361cb0ef41Sopenharmony_ci if (version_hash != Version::Hash()) { 6371cb0ef41Sopenharmony_ci return SerializedCodeSanityCheckResult::kVersionMismatch; 6381cb0ef41Sopenharmony_ci } 6391cb0ef41Sopenharmony_ci uint32_t flags_hash = GetHeaderValue(kFlagHashOffset); 6401cb0ef41Sopenharmony_ci if (flags_hash != FlagList::Hash()) { 6411cb0ef41Sopenharmony_ci return SerializedCodeSanityCheckResult::kFlagsMismatch; 6421cb0ef41Sopenharmony_ci } 6431cb0ef41Sopenharmony_ci uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset); 6441cb0ef41Sopenharmony_ci uint32_t max_payload_length = this->size_ - kHeaderSize; 6451cb0ef41Sopenharmony_ci if (payload_length > max_payload_length) { 6461cb0ef41Sopenharmony_ci return SerializedCodeSanityCheckResult::kLengthMismatch; 6471cb0ef41Sopenharmony_ci } 6481cb0ef41Sopenharmony_ci if (FLAG_verify_snapshot_checksum) { 6491cb0ef41Sopenharmony_ci uint32_t checksum = GetHeaderValue(kChecksumOffset); 6501cb0ef41Sopenharmony_ci if (Checksum(ChecksummedContent()) != checksum) { 6511cb0ef41Sopenharmony_ci return SerializedCodeSanityCheckResult::kChecksumMismatch; 6521cb0ef41Sopenharmony_ci } 6531cb0ef41Sopenharmony_ci } 6541cb0ef41Sopenharmony_ci return SerializedCodeSanityCheckResult::kSuccess; 6551cb0ef41Sopenharmony_ci} 6561cb0ef41Sopenharmony_ci 6571cb0ef41Sopenharmony_ciuint32_t SerializedCodeData::SourceHash(Handle<String> source, 6581cb0ef41Sopenharmony_ci ScriptOriginOptions origin_options) { 6591cb0ef41Sopenharmony_ci const uint32_t source_length = source->length(); 6601cb0ef41Sopenharmony_ci 6611cb0ef41Sopenharmony_ci static constexpr uint32_t kModuleFlagMask = (1 << 31); 6621cb0ef41Sopenharmony_ci const uint32_t is_module = origin_options.IsModule() ? kModuleFlagMask : 0; 6631cb0ef41Sopenharmony_ci DCHECK_EQ(0, source_length & kModuleFlagMask); 6641cb0ef41Sopenharmony_ci 6651cb0ef41Sopenharmony_ci return source_length | is_module; 6661cb0ef41Sopenharmony_ci} 6671cb0ef41Sopenharmony_ci 6681cb0ef41Sopenharmony_ci// Return ScriptData object and relinquish ownership over it to the caller. 6691cb0ef41Sopenharmony_ciAlignedCachedData* SerializedCodeData::GetScriptData() { 6701cb0ef41Sopenharmony_ci DCHECK(owns_data_); 6711cb0ef41Sopenharmony_ci AlignedCachedData* result = new AlignedCachedData(data_, size_); 6721cb0ef41Sopenharmony_ci result->AcquireDataOwnership(); 6731cb0ef41Sopenharmony_ci owns_data_ = false; 6741cb0ef41Sopenharmony_ci data_ = nullptr; 6751cb0ef41Sopenharmony_ci return result; 6761cb0ef41Sopenharmony_ci} 6771cb0ef41Sopenharmony_ci 6781cb0ef41Sopenharmony_cibase::Vector<const byte> SerializedCodeData::Payload() const { 6791cb0ef41Sopenharmony_ci const byte* payload = data_ + kHeaderSize; 6801cb0ef41Sopenharmony_ci DCHECK(IsAligned(reinterpret_cast<intptr_t>(payload), kPointerAlignment)); 6811cb0ef41Sopenharmony_ci int length = GetHeaderValue(kPayloadLengthOffset); 6821cb0ef41Sopenharmony_ci DCHECK_EQ(data_ + size_, payload + length); 6831cb0ef41Sopenharmony_ci return base::Vector<const byte>(payload, length); 6841cb0ef41Sopenharmony_ci} 6851cb0ef41Sopenharmony_ci 6861cb0ef41Sopenharmony_ciSerializedCodeData::SerializedCodeData(AlignedCachedData* data) 6871cb0ef41Sopenharmony_ci : SerializedData(const_cast<byte*>(data->data()), data->length()) {} 6881cb0ef41Sopenharmony_ci 6891cb0ef41Sopenharmony_ciSerializedCodeData SerializedCodeData::FromCachedData( 6901cb0ef41Sopenharmony_ci AlignedCachedData* cached_data, uint32_t expected_source_hash, 6911cb0ef41Sopenharmony_ci SerializedCodeSanityCheckResult* rejection_result) { 6921cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 6931cb0ef41Sopenharmony_ci SerializedCodeData scd(cached_data); 6941cb0ef41Sopenharmony_ci *rejection_result = scd.SanityCheck(expected_source_hash); 6951cb0ef41Sopenharmony_ci if (*rejection_result != SerializedCodeSanityCheckResult::kSuccess) { 6961cb0ef41Sopenharmony_ci cached_data->Reject(); 6971cb0ef41Sopenharmony_ci return SerializedCodeData(nullptr, 0); 6981cb0ef41Sopenharmony_ci } 6991cb0ef41Sopenharmony_ci return scd; 7001cb0ef41Sopenharmony_ci} 7011cb0ef41Sopenharmony_ci 7021cb0ef41Sopenharmony_ciSerializedCodeData SerializedCodeData::FromCachedDataWithoutSource( 7031cb0ef41Sopenharmony_ci AlignedCachedData* cached_data, 7041cb0ef41Sopenharmony_ci SerializedCodeSanityCheckResult* rejection_result) { 7051cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 7061cb0ef41Sopenharmony_ci SerializedCodeData scd(cached_data); 7071cb0ef41Sopenharmony_ci *rejection_result = scd.SanityCheckWithoutSource(); 7081cb0ef41Sopenharmony_ci if (*rejection_result != SerializedCodeSanityCheckResult::kSuccess) { 7091cb0ef41Sopenharmony_ci cached_data->Reject(); 7101cb0ef41Sopenharmony_ci return SerializedCodeData(nullptr, 0); 7111cb0ef41Sopenharmony_ci } 7121cb0ef41Sopenharmony_ci return scd; 7131cb0ef41Sopenharmony_ci} 7141cb0ef41Sopenharmony_ci 7151cb0ef41Sopenharmony_ciSerializedCodeData SerializedCodeData::FromPartiallySanityCheckedCachedData( 7161cb0ef41Sopenharmony_ci AlignedCachedData* cached_data, uint32_t expected_source_hash, 7171cb0ef41Sopenharmony_ci SerializedCodeSanityCheckResult* rejection_result) { 7181cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 7191cb0ef41Sopenharmony_ci // The previous call to FromCachedDataWithoutSource may have already rejected 7201cb0ef41Sopenharmony_ci // the cached data, so re-use the previous rejection result if it's not a 7211cb0ef41Sopenharmony_ci // success. 7221cb0ef41Sopenharmony_ci if (*rejection_result != SerializedCodeSanityCheckResult::kSuccess) { 7231cb0ef41Sopenharmony_ci // FromCachedDataWithoutSource doesn't check the source, so there can't be 7241cb0ef41Sopenharmony_ci // a source mismatch. 7251cb0ef41Sopenharmony_ci DCHECK_NE(*rejection_result, 7261cb0ef41Sopenharmony_ci SerializedCodeSanityCheckResult::kSourceMismatch); 7271cb0ef41Sopenharmony_ci cached_data->Reject(); 7281cb0ef41Sopenharmony_ci return SerializedCodeData(nullptr, 0); 7291cb0ef41Sopenharmony_ci } 7301cb0ef41Sopenharmony_ci SerializedCodeData scd(cached_data); 7311cb0ef41Sopenharmony_ci *rejection_result = scd.SanityCheckJustSource(expected_source_hash); 7321cb0ef41Sopenharmony_ci if (*rejection_result != SerializedCodeSanityCheckResult::kSuccess) { 7331cb0ef41Sopenharmony_ci // This check only checks the source, so the only possible failure is a 7341cb0ef41Sopenharmony_ci // source mismatch. 7351cb0ef41Sopenharmony_ci DCHECK_EQ(*rejection_result, 7361cb0ef41Sopenharmony_ci SerializedCodeSanityCheckResult::kSourceMismatch); 7371cb0ef41Sopenharmony_ci cached_data->Reject(); 7381cb0ef41Sopenharmony_ci return SerializedCodeData(nullptr, 0); 7391cb0ef41Sopenharmony_ci } 7401cb0ef41Sopenharmony_ci return scd; 7411cb0ef41Sopenharmony_ci} 7421cb0ef41Sopenharmony_ci 7431cb0ef41Sopenharmony_ci} // namespace internal 7441cb0ef41Sopenharmony_ci} // namespace v8 745