14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_SNAPSHOT_MEM_SNAPSHOT_PROCESSOR_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_SNAPSHOT_MEM_SNAPSHOT_PROCESSOR_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include <iostream>
204514f5e3Sopenharmony_ci#include <fstream>
214514f5e3Sopenharmony_ci#include <sstream>
224514f5e3Sopenharmony_ci
234514f5e3Sopenharmony_ci#include "ecmascript/snapshot/mem/encode_bit.h"
244514f5e3Sopenharmony_ci#include "ecmascript/jspandafile/method_literal.h"
254514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value.h"
264514f5e3Sopenharmony_ci#include "ecmascript/mem/object_xray.h"
274514f5e3Sopenharmony_ci
284514f5e3Sopenharmony_ci#include "libpandabase/macros.h"
294514f5e3Sopenharmony_ci
304514f5e3Sopenharmony_cinamespace panda::ecmascript {
314514f5e3Sopenharmony_ciclass EcmaVM;
324514f5e3Sopenharmony_ciclass JSPandaFile;
334514f5e3Sopenharmony_ciclass AOTFileManager;
344514f5e3Sopenharmony_ci
354514f5e3Sopenharmony_cienum class SnapshotType {
364514f5e3Sopenharmony_ci    VM_ROOT,
374514f5e3Sopenharmony_ci    BUILTINS,
384514f5e3Sopenharmony_ci    AI
394514f5e3Sopenharmony_ci};
404514f5e3Sopenharmony_ci
414514f5e3Sopenharmony_cistruct SnapshotRegionHeadInfo {
424514f5e3Sopenharmony_ci    uint32_t regionIndex_ {0};
434514f5e3Sopenharmony_ci    uint32_t aliveObjectSize_ {0};
444514f5e3Sopenharmony_ci
454514f5e3Sopenharmony_ci    static constexpr size_t RegionHeadInfoSize()
464514f5e3Sopenharmony_ci    {
474514f5e3Sopenharmony_ci        return sizeof(SnapshotRegionHeadInfo);
484514f5e3Sopenharmony_ci    }
494514f5e3Sopenharmony_ci};
504514f5e3Sopenharmony_ci
514514f5e3Sopenharmony_ciusing ObjectEncode = std::pair<uint64_t, ecmascript::EncodeBit>;
524514f5e3Sopenharmony_ci
534514f5e3Sopenharmony_ciclass SnapshotProcessor final {
544514f5e3Sopenharmony_cipublic:
554514f5e3Sopenharmony_ci    explicit SnapshotProcessor(EcmaVM *vm)
564514f5e3Sopenharmony_ci        : vm_(vm), sHeap_(SharedHeap::GetInstance()) {}
574514f5e3Sopenharmony_ci    ~SnapshotProcessor();
584514f5e3Sopenharmony_ci
594514f5e3Sopenharmony_ci    void Initialize();
604514f5e3Sopenharmony_ci    void StopAllocate();
614514f5e3Sopenharmony_ci    void WriteObjectToFile(std::fstream &write);
624514f5e3Sopenharmony_ci    std::vector<uint32_t> StatisticsObjectSize();
634514f5e3Sopenharmony_ci    void ProcessObjectQueue(CQueue<TaggedObject *> *queue, std::unordered_map<uint64_t, ObjectEncode> *data);
644514f5e3Sopenharmony_ci    void SerializeObject(TaggedObject *objectHeader, CQueue<TaggedObject *> *queue,
654514f5e3Sopenharmony_ci                         std::unordered_map<uint64_t, ObjectEncode> *data);
664514f5e3Sopenharmony_ci    void Relocate(SnapshotType type, const JSPandaFile *jsPandaFile,
674514f5e3Sopenharmony_ci                  uint64_t rootObjSize);
684514f5e3Sopenharmony_ci    void RelocateSpaceObject(const JSPandaFile *jsPandaFile, Space* space, SnapshotType type, MethodLiteral* methods,
694514f5e3Sopenharmony_ci                             size_t methodNums, size_t rootObjSize);
704514f5e3Sopenharmony_ci    void SerializePandaFileMethod();
714514f5e3Sopenharmony_ci    uintptr_t GetNewObj(size_t objectSize, TaggedObject *objectHeader);
724514f5e3Sopenharmony_ci    EncodeBit EncodeTaggedObject(TaggedObject *objectHeader, CQueue<TaggedObject *> *queue,
734514f5e3Sopenharmony_ci                                 std::unordered_map<uint64_t, ObjectEncode> *data);
744514f5e3Sopenharmony_ci    EncodeBit GetObjectEncode(JSTaggedValue object, CQueue<TaggedObject *> *queue,
754514f5e3Sopenharmony_ci                              std::unordered_map<uint64_t, ObjectEncode> *data);
764514f5e3Sopenharmony_ci    void EncodeTaggedObjectRange(ObjectSlot start, ObjectSlot end, CQueue<TaggedObject *> *queue,
774514f5e3Sopenharmony_ci                                 std::unordered_map<uint64_t, ObjectEncode> *data);
784514f5e3Sopenharmony_ci    void DeserializeObjectExcludeString(uintptr_t oldSpaceBegin, size_t oldSpaceObjSize, size_t nonMovableObjSize,
794514f5e3Sopenharmony_ci                                        size_t machineCodeObjSize, size_t snapshotObjSize, size_t hugeSpaceObjSize);
804514f5e3Sopenharmony_ci    void DeserializeString(uintptr_t stringBegin, uintptr_t stringEnd);
814514f5e3Sopenharmony_ci
824514f5e3Sopenharmony_ci    void AddRootObjectToAOTFileManager(SnapshotType type, const CString &fileName);
834514f5e3Sopenharmony_ci
844514f5e3Sopenharmony_ci    void SetProgramSerializeStart()
854514f5e3Sopenharmony_ci    {
864514f5e3Sopenharmony_ci        programSerialize_ = true;
874514f5e3Sopenharmony_ci    }
884514f5e3Sopenharmony_ci
894514f5e3Sopenharmony_ci    void SetBuiltinsSerializeStart()
904514f5e3Sopenharmony_ci    {
914514f5e3Sopenharmony_ci        builtinsSerialize_ = true;
924514f5e3Sopenharmony_ci    }
934514f5e3Sopenharmony_ci
944514f5e3Sopenharmony_ci    void SetBuiltinsDeserializeStart()
954514f5e3Sopenharmony_ci    {
964514f5e3Sopenharmony_ci        builtinsDeserialize_ = true;
974514f5e3Sopenharmony_ci    }
984514f5e3Sopenharmony_ci
994514f5e3Sopenharmony_ci    const CVector<uintptr_t> GetStringVector() const
1004514f5e3Sopenharmony_ci    {
1014514f5e3Sopenharmony_ci        return stringVector_;
1024514f5e3Sopenharmony_ci    }
1034514f5e3Sopenharmony_ci
1044514f5e3Sopenharmony_ci    LocalSpace* GetOldLocalSpace() const
1054514f5e3Sopenharmony_ci    {
1064514f5e3Sopenharmony_ci        return oldLocalSpace_;
1074514f5e3Sopenharmony_ci    }
1084514f5e3Sopenharmony_ci
1094514f5e3Sopenharmony_ci    size_t GetNativeTableSize() const;
1104514f5e3Sopenharmony_ci
1114514f5e3Sopenharmony_ciprivate:
1124514f5e3Sopenharmony_ci    size_t GetMarkGCBitSetSize() const
1134514f5e3Sopenharmony_ci    {
1144514f5e3Sopenharmony_ci        return GCBitset::SizeOfGCBitset(DEFAULT_REGION_SIZE -
1154514f5e3Sopenharmony_ci            AlignUp(sizeof(Region), static_cast<size_t>(MemAlignment::MEM_ALIGN_REGION)));
1164514f5e3Sopenharmony_ci    }
1174514f5e3Sopenharmony_ci
1184514f5e3Sopenharmony_ci    bool VisitObjectBodyWithRep(TaggedObject *root, ObjectSlot slot, uintptr_t obj, int index, VisitObjectArea area);
1194514f5e3Sopenharmony_ci    void SetObjectEncodeField(uintptr_t obj, size_t offset, uint64_t value);
1204514f5e3Sopenharmony_ci
1214514f5e3Sopenharmony_ci    EncodeBit SerializeObjectHeader(TaggedObject *objectHeader, size_t objectType, CQueue<TaggedObject *> *queue,
1224514f5e3Sopenharmony_ci                                    std::unordered_map<uint64_t, ObjectEncode> *data);
1234514f5e3Sopenharmony_ci    uint64_t SerializeTaggedField(JSTaggedType *tagged, CQueue<TaggedObject *> *queue,
1244514f5e3Sopenharmony_ci                                  std::unordered_map<uint64_t, ObjectEncode> *data);
1254514f5e3Sopenharmony_ci    void DeserializeField(TaggedObject *objectHeader);
1264514f5e3Sopenharmony_ci    void DeserializeTaggedField(uint64_t *value, TaggedObject *root);
1274514f5e3Sopenharmony_ci    void DeserializeNativePointer(uint64_t *value);
1284514f5e3Sopenharmony_ci    void DeserializeClassWord(TaggedObject *object);
1294514f5e3Sopenharmony_ci    void DeserializePandaMethod(uintptr_t begin, uintptr_t end, MethodLiteral *methods,
1304514f5e3Sopenharmony_ci                                size_t &methodNums, size_t &others);
1314514f5e3Sopenharmony_ci    void DeserializeSpaceObject(uintptr_t beginAddr, Space* space, size_t spaceObjSize);
1324514f5e3Sopenharmony_ci    void DeserializeHugeSpaceObject(uintptr_t beginAddr, HugeObjectSpace* space, size_t hugeSpaceObjSize);
1334514f5e3Sopenharmony_ci    void HandleRootObject(SnapshotType type, uintptr_t rootObjectAddr, size_t objType, size_t &constSpecialIndex);
1344514f5e3Sopenharmony_ci
1354514f5e3Sopenharmony_ci    EncodeBit NativePointerToEncodeBit(void *nativePointer);
1364514f5e3Sopenharmony_ci    size_t SearchNativeMethodIndex(void *nativePointer);
1374514f5e3Sopenharmony_ci    uintptr_t TaggedObjectEncodeBitToAddr(EncodeBit taggedBit);
1384514f5e3Sopenharmony_ci    void WriteSpaceObjectToFile(Space* space, std::fstream &write);
1394514f5e3Sopenharmony_ci    void WriteHugeObjectToFile(HugeObjectSpace* space, std::fstream &writer);
1404514f5e3Sopenharmony_ci    uint32_t StatisticsSpaceObjectSize(Space* space);
1414514f5e3Sopenharmony_ci    uint32_t StatisticsHugeObjectSize(HugeObjectSpace* space);
1424514f5e3Sopenharmony_ci    uintptr_t AllocateObjectToLocalSpace(Space *space, size_t objectSize);
1434514f5e3Sopenharmony_ci    SnapshotRegionHeadInfo GenerateRegionHeadInfo(Region *region);
1444514f5e3Sopenharmony_ci    void ResetRegionUnusedRange(Region *region);
1454514f5e3Sopenharmony_ci
1464514f5e3Sopenharmony_ci    EcmaVM *vm_ {nullptr};
1474514f5e3Sopenharmony_ci    SharedHeap* sHeap_ {nullptr};
1484514f5e3Sopenharmony_ci    LocalSpace *oldLocalSpace_ {nullptr};
1494514f5e3Sopenharmony_ci    LocalSpace *nonMovableLocalSpace_ {nullptr};
1504514f5e3Sopenharmony_ci    LocalSpace *machineCodeLocalSpace_ {nullptr};
1514514f5e3Sopenharmony_ci    SnapshotSpace *snapshotLocalSpace_ {nullptr};
1524514f5e3Sopenharmony_ci    HugeObjectSpace *hugeObjectLocalSpace_ {nullptr};
1534514f5e3Sopenharmony_ci    bool programSerialize_ {false};
1544514f5e3Sopenharmony_ci    bool builtinsSerialize_ {false};
1554514f5e3Sopenharmony_ci    bool builtinsDeserialize_ {false};
1564514f5e3Sopenharmony_ci    CVector<uintptr_t> pandaMethod_;
1574514f5e3Sopenharmony_ci    CVector<uintptr_t> stringVector_;
1584514f5e3Sopenharmony_ci    /**
1594514f5e3Sopenharmony_ci     * In deserialize, RuntimeLock for string table may cause a SharedGC, making strings just created invalid,
1604514f5e3Sopenharmony_ci     * so use handle to protect.
1614514f5e3Sopenharmony_ci    */
1624514f5e3Sopenharmony_ci    CVector<JSHandle<EcmaString>> deserializeStringVector_;
1634514f5e3Sopenharmony_ci    std::unordered_map<size_t, Region *> regionIndexMap_;
1644514f5e3Sopenharmony_ci    size_t regionIndex_ {0};
1654514f5e3Sopenharmony_ci    bool isRootObjRelocate_ {false};
1664514f5e3Sopenharmony_ci    JSTaggedValue root_ {JSTaggedValue::Hole()};
1674514f5e3Sopenharmony_ci
1684514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(SnapshotProcessor);
1694514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(SnapshotProcessor);
1704514f5e3Sopenharmony_ci};
1714514f5e3Sopenharmony_ci
1724514f5e3Sopenharmony_ciclass SnapshotHelper {
1734514f5e3Sopenharmony_cipublic:
1744514f5e3Sopenharmony_ci    // when snapshot serialize, huge obj size is writed to region snapshotData_ high 32 bits
1754514f5e3Sopenharmony_ci    static inline uint64_t EncodeHugeObjectSize(uint64_t objSize)
1764514f5e3Sopenharmony_ci    {
1774514f5e3Sopenharmony_ci        return objSize << Constants::UINT_32_BITS_COUNT;
1784514f5e3Sopenharmony_ci    }
1794514f5e3Sopenharmony_ci
1804514f5e3Sopenharmony_ci    // get huge object size which is saved in region snapshotData_ high 32 bits
1814514f5e3Sopenharmony_ci    static inline size_t GetHugeObjectSize(uint64_t snapshotData)
1824514f5e3Sopenharmony_ci    {
1834514f5e3Sopenharmony_ci        return snapshotData >> Constants::UINT_32_BITS_COUNT;
1844514f5e3Sopenharmony_ci    }
1854514f5e3Sopenharmony_ci
1864514f5e3Sopenharmony_ci    // get huge object region index which is saved in region snapshotMark_ low 32 bits
1874514f5e3Sopenharmony_ci    static inline size_t GetHugeObjectRegionIndex(uint64_t snapshotData)
1884514f5e3Sopenharmony_ci    {
1894514f5e3Sopenharmony_ci        return snapshotData & Constants::MAX_UINT_32;
1904514f5e3Sopenharmony_ci    }
1914514f5e3Sopenharmony_ci};
1924514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
1934514f5e3Sopenharmony_ci
1944514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_SNAPSHOT_MEM_SNAPSHOT_PROCESSOR_H
195