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