14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2022-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#include "ecmascript/deoptimizer/deoptimizer.h"
164514f5e3Sopenharmony_ci
174514f5e3Sopenharmony_ci#include <cmath>
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include "ecmascript/dfx/stackinfo/js_stackinfo.h"
204514f5e3Sopenharmony_ci#include "ecmascript/interpreter/slow_runtime_stub.h"
214514f5e3Sopenharmony_ci#include "ecmascript/jit/jit.h"
224514f5e3Sopenharmony_ci#include "ecmascript/stubs/runtime_stubs-inl.h"
234514f5e3Sopenharmony_ci
244514f5e3Sopenharmony_cinamespace panda::ecmascript {
254514f5e3Sopenharmony_ciclass FrameWriter {
264514f5e3Sopenharmony_cipublic:
274514f5e3Sopenharmony_ci    explicit FrameWriter(Deoptimizier *deoptimizier) : thread_(deoptimizier->GetThread())
284514f5e3Sopenharmony_ci    {
294514f5e3Sopenharmony_ci        JSTaggedType *prevSp = const_cast<JSTaggedType *>(thread_->GetCurrentSPFrame());
304514f5e3Sopenharmony_ci        start_ = top_ = EcmaInterpreter::GetInterpreterFrameEnd(thread_, prevSp);
314514f5e3Sopenharmony_ci    }
324514f5e3Sopenharmony_ci
334514f5e3Sopenharmony_ci    void PushValue(JSTaggedType value)
344514f5e3Sopenharmony_ci    {
354514f5e3Sopenharmony_ci        *(--top_) = value;
364514f5e3Sopenharmony_ci    }
374514f5e3Sopenharmony_ci
384514f5e3Sopenharmony_ci    void PushRawValue(uintptr_t value)
394514f5e3Sopenharmony_ci    {
404514f5e3Sopenharmony_ci        *(--top_) = value;
414514f5e3Sopenharmony_ci    }
424514f5e3Sopenharmony_ci
434514f5e3Sopenharmony_ci    bool Reserve(size_t size)
444514f5e3Sopenharmony_ci    {
454514f5e3Sopenharmony_ci        return !thread_->DoStackOverflowCheck(top_ - size);
464514f5e3Sopenharmony_ci    }
474514f5e3Sopenharmony_ci
484514f5e3Sopenharmony_ci    AsmInterpretedFrame *ReserveAsmInterpretedFrame()
494514f5e3Sopenharmony_ci    {
504514f5e3Sopenharmony_ci        auto frame = AsmInterpretedFrame::GetFrameFromSp(top_);
514514f5e3Sopenharmony_ci        top_ = reinterpret_cast<JSTaggedType *>(frame);
524514f5e3Sopenharmony_ci        return frame;
534514f5e3Sopenharmony_ci    }
544514f5e3Sopenharmony_ci
554514f5e3Sopenharmony_ci    JSTaggedType *GetStart() const
564514f5e3Sopenharmony_ci    {
574514f5e3Sopenharmony_ci        return start_;
584514f5e3Sopenharmony_ci    }
594514f5e3Sopenharmony_ci
604514f5e3Sopenharmony_ci    JSTaggedType *GetTop() const
614514f5e3Sopenharmony_ci    {
624514f5e3Sopenharmony_ci        return top_;
634514f5e3Sopenharmony_ci    }
644514f5e3Sopenharmony_ci
654514f5e3Sopenharmony_ci    JSTaggedType *GetFirstFrame() const
664514f5e3Sopenharmony_ci    {
674514f5e3Sopenharmony_ci        return firstFrame_;
684514f5e3Sopenharmony_ci    }
694514f5e3Sopenharmony_ci
704514f5e3Sopenharmony_ci    void RecordFirstFrame()
714514f5e3Sopenharmony_ci    {
724514f5e3Sopenharmony_ci        firstFrame_ = top_;
734514f5e3Sopenharmony_ci    }
744514f5e3Sopenharmony_ci
754514f5e3Sopenharmony_ci    void ReviseValueByIndex(JSTaggedType value, size_t index)
764514f5e3Sopenharmony_ci    {
774514f5e3Sopenharmony_ci        ASSERT(index < static_cast<size_t>(start_ - top_));
784514f5e3Sopenharmony_ci        *(top_ + index) = value;
794514f5e3Sopenharmony_ci    }
804514f5e3Sopenharmony_ci
814514f5e3Sopenharmony_ciprivate:
824514f5e3Sopenharmony_ci    JSThread *thread_ {nullptr};
834514f5e3Sopenharmony_ci    JSTaggedType *start_ {nullptr};
844514f5e3Sopenharmony_ci    JSTaggedType *top_ {nullptr};
854514f5e3Sopenharmony_ci    JSTaggedType *firstFrame_ {nullptr};
864514f5e3Sopenharmony_ci};
874514f5e3Sopenharmony_ci
884514f5e3Sopenharmony_ciDeoptimizier::Deoptimizier(JSThread *thread, size_t depth) : thread_(thread), inlineDepth_(depth)
894514f5e3Sopenharmony_ci{
904514f5e3Sopenharmony_ci    CalleeReg callreg;
914514f5e3Sopenharmony_ci    numCalleeRegs_ = static_cast<size_t>(callreg.GetCallRegNum());
924514f5e3Sopenharmony_ci    JSRuntimeOptions options = thread_->GetEcmaVM()->GetJSOptions();
934514f5e3Sopenharmony_ci    traceDeopt_ = options.GetTraceDeopt();
944514f5e3Sopenharmony_ci}
954514f5e3Sopenharmony_ci
964514f5e3Sopenharmony_civoid Deoptimizier::CollectVregs(const std::vector<kungfu::ARKDeopt>& deoptBundle, size_t shift)
974514f5e3Sopenharmony_ci{
984514f5e3Sopenharmony_ci    deoptVregs_.clear();
994514f5e3Sopenharmony_ci    for (size_t i = 0; i < deoptBundle.size(); i++) {
1004514f5e3Sopenharmony_ci        ARKDeopt deopt = deoptBundle.at(i);
1014514f5e3Sopenharmony_ci        JSTaggedType v;
1024514f5e3Sopenharmony_ci        VRegId id = deopt.id;
1034514f5e3Sopenharmony_ci        if (std::holds_alternative<DwarfRegAndOffsetType>(deopt.value)) {
1044514f5e3Sopenharmony_ci            ASSERT(deopt.kind == LocationTy::Kind::INDIRECT);
1054514f5e3Sopenharmony_ci            auto value = std::get<DwarfRegAndOffsetType>(deopt.value);
1064514f5e3Sopenharmony_ci            DwarfRegType dwarfReg = value.first;
1074514f5e3Sopenharmony_ci            OffsetType offset = value.second;
1084514f5e3Sopenharmony_ci            ASSERT (dwarfReg == GCStackMapRegisters::FP || dwarfReg == GCStackMapRegisters::SP);
1094514f5e3Sopenharmony_ci            uintptr_t addr;
1104514f5e3Sopenharmony_ci            if (dwarfReg == GCStackMapRegisters::SP) {
1114514f5e3Sopenharmony_ci                addr = context_.callsiteSp + offset;
1124514f5e3Sopenharmony_ci            } else {
1134514f5e3Sopenharmony_ci                addr = context_.callsiteFp + offset;
1144514f5e3Sopenharmony_ci            }
1154514f5e3Sopenharmony_ci            v = *(reinterpret_cast<JSTaggedType *>(addr));
1164514f5e3Sopenharmony_ci        } else if (std::holds_alternative<LargeInt>(deopt.value)) {
1174514f5e3Sopenharmony_ci            ASSERT(deopt.kind == LocationTy::Kind::CONSTANTNDEX);
1184514f5e3Sopenharmony_ci            v = JSTaggedType(static_cast<int64_t>(std::get<LargeInt>(deopt.value)));
1194514f5e3Sopenharmony_ci        } else {
1204514f5e3Sopenharmony_ci            ASSERT(std::holds_alternative<IntType>(deopt.value));
1214514f5e3Sopenharmony_ci            ASSERT(deopt.kind == LocationTy::Kind::CONSTANT);
1224514f5e3Sopenharmony_ci            v = JSTaggedType(static_cast<int64_t>(std::get<IntType>(deopt.value)));
1234514f5e3Sopenharmony_ci        }
1244514f5e3Sopenharmony_ci        size_t curDepth = DecodeDeoptDepth(id, shift);
1254514f5e3Sopenharmony_ci        OffsetType vregId = static_cast<OffsetType>(DecodeVregIndex(id, shift));
1264514f5e3Sopenharmony_ci        if (vregId != static_cast<OffsetType>(SpecVregIndex::PC_OFFSET_INDEX)) {
1274514f5e3Sopenharmony_ci            deoptVregs_.insert({{curDepth, vregId}, JSHandle<JSTaggedValue>(thread_, JSTaggedValue(v))});
1284514f5e3Sopenharmony_ci        } else {
1294514f5e3Sopenharmony_ci            pc_.insert({curDepth, static_cast<size_t>(v)});
1304514f5e3Sopenharmony_ci        }
1314514f5e3Sopenharmony_ci    }
1324514f5e3Sopenharmony_ci}
1334514f5e3Sopenharmony_ci
1344514f5e3Sopenharmony_ci// when AOT trigger deopt, frame layout as the following
1354514f5e3Sopenharmony_ci// * OptimizedJSFunctionFrame layout description as the following:
1364514f5e3Sopenharmony_ci//               +--------------------------+ ---------------
1374514f5e3Sopenharmony_ci//               |        ......            |               ^
1384514f5e3Sopenharmony_ci//               |        ......            |       callerFunction
1394514f5e3Sopenharmony_ci//               |        ......            |               |
1404514f5e3Sopenharmony_ci//               |--------------------------|               |
1414514f5e3Sopenharmony_ci//               |        args              |               v
1424514f5e3Sopenharmony_ci//               +--------------------------+ ---------------
1434514f5e3Sopenharmony_ci//               |       returnAddr         |               ^
1444514f5e3Sopenharmony_ci//               |--------------------------|               |
1454514f5e3Sopenharmony_ci//               |       callsiteFp         |               |
1464514f5e3Sopenharmony_ci//               |--------------------------|   OptimizedJSFunction  FrameType:OPTIMIZED_JS_FUNCTION_FRAME
1474514f5e3Sopenharmony_ci//               |       frameType          |               |
1484514f5e3Sopenharmony_ci//               |--------------------------|               |
1494514f5e3Sopenharmony_ci//               |       call-target        |               |
1504514f5e3Sopenharmony_ci//               |--------------------------|               |
1514514f5e3Sopenharmony_ci//               |       lexEnv             |               |
1524514f5e3Sopenharmony_ci//               |--------------------------|               |
1534514f5e3Sopenharmony_ci//               |       ...........        |               v
1544514f5e3Sopenharmony_ci//               +--------------------------+ ---------------
1554514f5e3Sopenharmony_ci//               |       returnAddr         |               ^
1564514f5e3Sopenharmony_ci//               |--------------------------|               |
1574514f5e3Sopenharmony_ci//               |       callsiteFp         |               |
1584514f5e3Sopenharmony_ci//               |--------------------------|   __llvm_deoptimize  FrameType:OPTIMIZED_FRAME
1594514f5e3Sopenharmony_ci//               |       frameType          |               |
1604514f5e3Sopenharmony_ci//               |--------------------------|               |
1614514f5e3Sopenharmony_ci//               |       No CalleeSave      |               |
1624514f5e3Sopenharmony_ci//               |       Registers          |               v
1634514f5e3Sopenharmony_ci//               +--------------------------+ ---------------
1644514f5e3Sopenharmony_ci//               |       returnAddr         |               ^
1654514f5e3Sopenharmony_ci//               |--------------------------|               |
1664514f5e3Sopenharmony_ci//               |       callsiteFp         |               |
1674514f5e3Sopenharmony_ci//               |--------------------------|   DeoptHandlerAsm  FrameType:ASM_BRIDGE_FRAME
1684514f5e3Sopenharmony_ci//               |       frameType          |               |
1694514f5e3Sopenharmony_ci//               |--------------------------|               |
1704514f5e3Sopenharmony_ci//               |       glue               |               |
1714514f5e3Sopenharmony_ci//               |--------------------------|               |
1724514f5e3Sopenharmony_ci//               | CalleeSave Registers     |               v
1734514f5e3Sopenharmony_ci//               +--------------------------+ ---------------
1744514f5e3Sopenharmony_ci//               |       .........          |               ^
1754514f5e3Sopenharmony_ci//               |       .........          |     CallRuntime   FrameType:LEAVE_FRAME
1764514f5e3Sopenharmony_ci//               |       .........          |               |
1774514f5e3Sopenharmony_ci//               |       .........          |               v
1784514f5e3Sopenharmony_ci//               |--------------------------| ---------------
1794514f5e3Sopenharmony_ci
1804514f5e3Sopenharmony_ci// After gathering the necessary information(After Call Runtime), frame layout after constructing
1814514f5e3Sopenharmony_ci// asminterpreterframe is shown as the following:
1824514f5e3Sopenharmony_ci//               +----------------------------------+---------+
1834514f5e3Sopenharmony_ci//               |        ......                    |         ^
1844514f5e3Sopenharmony_ci//               |        ......                    |   callerFunction
1854514f5e3Sopenharmony_ci//               |        ......                    |         |
1864514f5e3Sopenharmony_ci//               |----------------------------------|         |
1874514f5e3Sopenharmony_ci//               |        args                      |         v
1884514f5e3Sopenharmony_ci//               +----------------------------------+---------+
1894514f5e3Sopenharmony_ci//               |       returnAddr                 |         ^
1904514f5e3Sopenharmony_ci//               |----------------------------------|         |
1914514f5e3Sopenharmony_ci//               |       frameType                  |         |
1924514f5e3Sopenharmony_ci//               |----------------------------------|    ASM_INTERPRETER_BRIDGE_FRAME
1934514f5e3Sopenharmony_ci//               |       callsiteFp                 |         |
1944514f5e3Sopenharmony_ci//               |----------------------------------|         |
1954514f5e3Sopenharmony_ci//               |       ...........                |         v
1964514f5e3Sopenharmony_ci//               +----------------------------------+---------+
1974514f5e3Sopenharmony_ci//               |       returnAddr                 |
1984514f5e3Sopenharmony_ci//               |----------------------------------|
1994514f5e3Sopenharmony_ci//               |    argv[n-1]                     |
2004514f5e3Sopenharmony_ci//               |----------------------------------|
2014514f5e3Sopenharmony_ci//               |    ......                        |
2024514f5e3Sopenharmony_ci//               |----------------------------------|
2034514f5e3Sopenharmony_ci//               |    thisArg [maybe not exist]     |
2044514f5e3Sopenharmony_ci//               |----------------------------------|
2054514f5e3Sopenharmony_ci//               |    newTarget [maybe not exist]   |
2064514f5e3Sopenharmony_ci//               |----------------------------------|
2074514f5e3Sopenharmony_ci//               |    ......                        |
2084514f5e3Sopenharmony_ci//               |----------------------------------|
2094514f5e3Sopenharmony_ci//               |    Vregs [not exist in native]   |
2104514f5e3Sopenharmony_ci//               +----------------------------------+--------+
2114514f5e3Sopenharmony_ci//               |        .  .  .   .               |        ^
2124514f5e3Sopenharmony_ci//               |     InterpretedFrameBase         |        |
2134514f5e3Sopenharmony_ci//               |        .  .  .   .               |        |
2144514f5e3Sopenharmony_ci//               |----------------------------------|        |
2154514f5e3Sopenharmony_ci//               |    pc(bytecode addr)             |        |
2164514f5e3Sopenharmony_ci//               |----------------------------------|        |
2174514f5e3Sopenharmony_ci//               |    sp(current stack pointer)     |        |
2184514f5e3Sopenharmony_ci//               |----------------------------------|   AsmInterpretedFrame 0
2194514f5e3Sopenharmony_ci//               |    callSize                      |        |
2204514f5e3Sopenharmony_ci//               |----------------------------------|        |
2214514f5e3Sopenharmony_ci//               |    env                           |        |
2224514f5e3Sopenharmony_ci//               |----------------------------------|        |
2234514f5e3Sopenharmony_ci//               |    acc                           |        |
2244514f5e3Sopenharmony_ci//               |----------------------------------|        |
2254514f5e3Sopenharmony_ci//               |    thisObj                       |        |
2264514f5e3Sopenharmony_ci//               |----------------------------------|        |
2274514f5e3Sopenharmony_ci//               |    call-target                   |        v
2284514f5e3Sopenharmony_ci//               +----------------------------------+--------+
2294514f5e3Sopenharmony_ci//               |    argv[n-1]                     |
2304514f5e3Sopenharmony_ci//               |----------------------------------|
2314514f5e3Sopenharmony_ci//               |    ......                        |
2324514f5e3Sopenharmony_ci//               |----------------------------------|
2334514f5e3Sopenharmony_ci//               |    thisArg [maybe not exist]     |
2344514f5e3Sopenharmony_ci//               |----------------------------------|
2354514f5e3Sopenharmony_ci//               |    newTarget [maybe not exist]   |
2364514f5e3Sopenharmony_ci//               |----------------------------------|
2374514f5e3Sopenharmony_ci//               |    ......                        |
2384514f5e3Sopenharmony_ci//               |----------------------------------|
2394514f5e3Sopenharmony_ci//               |    Vregs [not exist in native]   |
2404514f5e3Sopenharmony_ci//               +----------------------------------+--------+
2414514f5e3Sopenharmony_ci//               |        .  .  .   .               |        ^
2424514f5e3Sopenharmony_ci//               |     InterpretedFrameBase         |        |
2434514f5e3Sopenharmony_ci//               |        .  .  .   .               |        |
2444514f5e3Sopenharmony_ci//               |----------------------------------|        |
2454514f5e3Sopenharmony_ci//               |    pc(bytecode addr)             |        |
2464514f5e3Sopenharmony_ci//               |----------------------------------|        |
2474514f5e3Sopenharmony_ci//               |    sp(current stack pointer)     |        |
2484514f5e3Sopenharmony_ci//               |----------------------------------|   AsmInterpretedFrame 1
2494514f5e3Sopenharmony_ci//               |    callSize                      |        |
2504514f5e3Sopenharmony_ci//               |----------------------------------|        |
2514514f5e3Sopenharmony_ci//               |    env                           |        |
2524514f5e3Sopenharmony_ci//               |----------------------------------|        |
2534514f5e3Sopenharmony_ci//               |    acc                           |        |
2544514f5e3Sopenharmony_ci//               |----------------------------------|        |
2554514f5e3Sopenharmony_ci//               |    thisObj                       |        |
2564514f5e3Sopenharmony_ci//               |----------------------------------|        |
2574514f5e3Sopenharmony_ci//               |    call-target                   |        v
2584514f5e3Sopenharmony_ci//               +----------------------------------+--------+
2594514f5e3Sopenharmony_ci//               |        .  .  .   .               |        ^
2604514f5e3Sopenharmony_ci//               |        .  .  .   .               |   AsmInterpretedFrame n
2614514f5e3Sopenharmony_ci//               |        .  .  .   .               |        v
2624514f5e3Sopenharmony_ci//               +----------------------------------+--------+
2634514f5e3Sopenharmony_ci
2644514f5e3Sopenharmony_citemplate<class T>
2654514f5e3Sopenharmony_civoid Deoptimizier::AssistCollectDeoptBundleVec(FrameIterator &it, T &frame)
2664514f5e3Sopenharmony_ci{
2674514f5e3Sopenharmony_ci    CalleeRegAndOffsetVec calleeRegInfo;
2684514f5e3Sopenharmony_ci    frame->GetFuncCalleeRegAndOffset(it, calleeRegInfo);
2694514f5e3Sopenharmony_ci    context_.calleeRegAndOffset = calleeRegInfo;
2704514f5e3Sopenharmony_ci    context_.callsiteSp = it.GetCallSiteSp();
2714514f5e3Sopenharmony_ci    context_.callsiteFp = reinterpret_cast<uintptr_t>(it.GetSp());
2724514f5e3Sopenharmony_ci    auto preFrameSp = frame->ComputePrevFrameSp(it);
2734514f5e3Sopenharmony_ci    frameArgc_ = frame->GetArgc(preFrameSp);
2744514f5e3Sopenharmony_ci    frameArgvs_ = frame->GetArgv(preFrameSp);
2754514f5e3Sopenharmony_ci    stackContext_.callFrameTop_ = it.GetPrevFrameCallSiteSp();
2764514f5e3Sopenharmony_ci    stackContext_.returnAddr_ = frame->GetReturnAddr();
2774514f5e3Sopenharmony_ci    stackContext_.callerFp_ = reinterpret_cast<uintptr_t>(frame->GetPrevFrameFp());
2784514f5e3Sopenharmony_ci}
2794514f5e3Sopenharmony_ci
2804514f5e3Sopenharmony_civoid Deoptimizier::CollectDeoptBundleVec(std::vector<ARKDeopt>& deoptBundle)
2814514f5e3Sopenharmony_ci{
2824514f5e3Sopenharmony_ci    JSTaggedType *lastLeave = const_cast<JSTaggedType *>(thread_->GetLastLeaveFrame());
2834514f5e3Sopenharmony_ci    FrameIterator it(lastLeave, thread_);
2844514f5e3Sopenharmony_ci    // note: last deopt bridge frame is generated by DeoptHandlerAsm, callee Regs is grow from this frame
2854514f5e3Sopenharmony_ci    for (; !it.Done() && deoptBundle.empty(); it.Advance<GCVisitedFlag::DEOPT>()) {
2864514f5e3Sopenharmony_ci        FrameType type = it.GetFrameType();
2874514f5e3Sopenharmony_ci        switch (type) {
2884514f5e3Sopenharmony_ci            case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
2894514f5e3Sopenharmony_ci            case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
2904514f5e3Sopenharmony_ci                auto frame = it.GetFrame<OptimizedJSFunctionFrame>();
2914514f5e3Sopenharmony_ci                frame->GetDeoptBundleInfo(it, deoptBundle);
2924514f5e3Sopenharmony_ci                AssistCollectDeoptBundleVec(it, frame);
2934514f5e3Sopenharmony_ci                break;
2944514f5e3Sopenharmony_ci            }
2954514f5e3Sopenharmony_ci            case FrameType::FASTJIT_FUNCTION_FRAME:
2964514f5e3Sopenharmony_ci            case FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME: {
2974514f5e3Sopenharmony_ci                auto frame = it.GetFrame<FASTJITFunctionFrame>();
2984514f5e3Sopenharmony_ci                frame->GetDeoptBundleInfo(it, deoptBundle);
2994514f5e3Sopenharmony_ci                AssistCollectDeoptBundleVec(it, frame);
3004514f5e3Sopenharmony_ci                break;
3014514f5e3Sopenharmony_ci            }
3024514f5e3Sopenharmony_ci            case FrameType::ASM_BRIDGE_FRAME: {
3034514f5e3Sopenharmony_ci                auto sp = reinterpret_cast<uintptr_t*>(it.GetSp());
3044514f5e3Sopenharmony_ci                static constexpr size_t TYPE_GLUE_SLOT = 2; // 2: skip type & glue
3054514f5e3Sopenharmony_ci                sp -= TYPE_GLUE_SLOT;
3064514f5e3Sopenharmony_ci                calleeRegAddr_ = sp - numCalleeRegs_;
3074514f5e3Sopenharmony_ci                break;
3084514f5e3Sopenharmony_ci            }
3094514f5e3Sopenharmony_ci            case FrameType::OPTIMIZED_FRAME:
3104514f5e3Sopenharmony_ci            case FrameType::LEAVE_FRAME:
3114514f5e3Sopenharmony_ci                break;
3124514f5e3Sopenharmony_ci            default: {
3134514f5e3Sopenharmony_ci                LOG_FULL(FATAL) << "frame type error!";
3144514f5e3Sopenharmony_ci                UNREACHABLE();
3154514f5e3Sopenharmony_ci            }
3164514f5e3Sopenharmony_ci        }
3174514f5e3Sopenharmony_ci    }
3184514f5e3Sopenharmony_ci    ASSERT(!it.Done());
3194514f5e3Sopenharmony_ci}
3204514f5e3Sopenharmony_ci
3214514f5e3Sopenharmony_ciMethod* Deoptimizier::GetMethod(JSTaggedValue &target)
3224514f5e3Sopenharmony_ci{
3234514f5e3Sopenharmony_ci    ECMAObject *callTarget = reinterpret_cast<ECMAObject*>(target.GetTaggedObject());
3244514f5e3Sopenharmony_ci    ASSERT(callTarget != nullptr);
3254514f5e3Sopenharmony_ci    Method *method = callTarget->GetCallTarget();
3264514f5e3Sopenharmony_ci    return method;
3274514f5e3Sopenharmony_ci}
3284514f5e3Sopenharmony_ci
3294514f5e3Sopenharmony_civoid Deoptimizier::RelocateCalleeSave()
3304514f5e3Sopenharmony_ci{
3314514f5e3Sopenharmony_ci    CalleeReg callreg;
3324514f5e3Sopenharmony_ci    for (auto &it: context_.calleeRegAndOffset) {
3334514f5e3Sopenharmony_ci        auto reg = it.first;
3344514f5e3Sopenharmony_ci        auto offset = it.second;
3354514f5e3Sopenharmony_ci        uintptr_t value = *(reinterpret_cast<uintptr_t *>(context_.callsiteFp + offset));
3364514f5e3Sopenharmony_ci        int order = callreg.FindCallRegOrder(reg);
3374514f5e3Sopenharmony_ci        calleeRegAddr_[order] = value;
3384514f5e3Sopenharmony_ci    }
3394514f5e3Sopenharmony_ci}
3404514f5e3Sopenharmony_ci
3414514f5e3Sopenharmony_cibool Deoptimizier::CollectVirtualRegisters(JSTaggedValue callTarget, Method *method, FrameWriter *frameWriter,
3424514f5e3Sopenharmony_ci    size_t curDepth)
3434514f5e3Sopenharmony_ci{
3444514f5e3Sopenharmony_ci    int32_t actualNumArgs = 0;
3454514f5e3Sopenharmony_ci    int32_t declaredNumArgs = 0;
3464514f5e3Sopenharmony_ci    if (curDepth == 0) {
3474514f5e3Sopenharmony_ci        actualNumArgs = static_cast<int32_t>(GetDeoptValue(curDepth,
3484514f5e3Sopenharmony_ci            static_cast<int32_t>(SpecVregIndex::ACTUAL_ARGC_INDEX)).GetInt());
3494514f5e3Sopenharmony_ci        declaredNumArgs = static_cast<int32_t>(method->GetNumArgsWithCallField());
3504514f5e3Sopenharmony_ci    } else {
3514514f5e3Sopenharmony_ci        // inline method actualNumArgs equal to declaredNumArgs
3524514f5e3Sopenharmony_ci        actualNumArgs = static_cast<int32_t>(method->GetNumArgsWithCallField());
3534514f5e3Sopenharmony_ci        declaredNumArgs = static_cast<int32_t>(method->GetNumArgsWithCallField());
3544514f5e3Sopenharmony_ci    }
3554514f5e3Sopenharmony_ci
3564514f5e3Sopenharmony_ci    int32_t callFieldNumVregs = static_cast<int32_t>(method->GetNumVregsWithCallField());
3574514f5e3Sopenharmony_ci
3584514f5e3Sopenharmony_ci    // layout of frame:
3594514f5e3Sopenharmony_ci    // [maybe argc] [actual args] [reserved args] [call field virtual regs]
3604514f5e3Sopenharmony_ci
3614514f5e3Sopenharmony_ci    // [maybe argc]
3624514f5e3Sopenharmony_ci    bool isFastCall = JSFunctionBase::IsFastCallFromCallTarget(callTarget);
3634514f5e3Sopenharmony_ci    if (!isFastCall && declaredNumArgs != actualNumArgs) {
3644514f5e3Sopenharmony_ci        auto value = JSTaggedValue(actualNumArgs);
3654514f5e3Sopenharmony_ci        frameWriter->PushValue(value.GetRawData());
3664514f5e3Sopenharmony_ci    }
3674514f5e3Sopenharmony_ci    int32_t virtualIndex = declaredNumArgs + callFieldNumVregs +
3684514f5e3Sopenharmony_ci        static_cast<int32_t>(method->GetNumRevervedArgs()) - 1;
3694514f5e3Sopenharmony_ci    if (!frameWriter->Reserve(static_cast<size_t>(virtualIndex))) {
3704514f5e3Sopenharmony_ci        return false;
3714514f5e3Sopenharmony_ci    }
3724514f5e3Sopenharmony_ci    for (int32_t i = static_cast<int32_t>(declaredNumArgs - 1); i >= 0; i--) {
3734514f5e3Sopenharmony_ci        JSTaggedValue value = JSTaggedValue::Undefined();
3744514f5e3Sopenharmony_ci        // deopt value
3754514f5e3Sopenharmony_ci        if (HasDeoptValue(curDepth, virtualIndex)) {
3764514f5e3Sopenharmony_ci            value = GetDeoptValue(curDepth, virtualIndex);
3774514f5e3Sopenharmony_ci        }
3784514f5e3Sopenharmony_ci        frameWriter->PushValue(value.GetRawData());
3794514f5e3Sopenharmony_ci        virtualIndex--;
3804514f5e3Sopenharmony_ci    }
3814514f5e3Sopenharmony_ci
3824514f5e3Sopenharmony_ci    // [reserved args]
3834514f5e3Sopenharmony_ci    if (method->HaveThisWithCallField()) {
3844514f5e3Sopenharmony_ci        JSTaggedValue value = deoptVregs_.at(
3854514f5e3Sopenharmony_ci            {curDepth, static_cast<OffsetType>(SpecVregIndex::THIS_OBJECT_INDEX)}).GetTaggedValue();
3864514f5e3Sopenharmony_ci        frameWriter->PushValue(value.GetRawData());
3874514f5e3Sopenharmony_ci        virtualIndex--;
3884514f5e3Sopenharmony_ci    }
3894514f5e3Sopenharmony_ci    if (method->HaveNewTargetWithCallField()) {
3904514f5e3Sopenharmony_ci        JSTaggedValue value = deoptVregs_.at(
3914514f5e3Sopenharmony_ci            {curDepth, static_cast<OffsetType>(SpecVregIndex::NEWTARGET_INDEX)}).GetTaggedValue();
3924514f5e3Sopenharmony_ci        frameWriter->PushValue(value.GetRawData());
3934514f5e3Sopenharmony_ci        virtualIndex--;
3944514f5e3Sopenharmony_ci    }
3954514f5e3Sopenharmony_ci    if (method->HaveFuncWithCallField()) {
3964514f5e3Sopenharmony_ci        JSTaggedValue value = deoptVregs_.at(
3974514f5e3Sopenharmony_ci            {curDepth, static_cast<OffsetType>(SpecVregIndex::FUNC_INDEX)}).GetTaggedValue();
3984514f5e3Sopenharmony_ci        frameWriter->PushValue(value.GetRawData());
3994514f5e3Sopenharmony_ci        virtualIndex--;
4004514f5e3Sopenharmony_ci    }
4014514f5e3Sopenharmony_ci
4024514f5e3Sopenharmony_ci    // [call field virtual regs]
4034514f5e3Sopenharmony_ci    for (int32_t i = virtualIndex; i >= 0; i--) {
4044514f5e3Sopenharmony_ci        JSTaggedValue value = GetDeoptValue(curDepth, virtualIndex);
4054514f5e3Sopenharmony_ci        frameWriter->PushValue(value.GetRawData());
4064514f5e3Sopenharmony_ci        virtualIndex--;
4074514f5e3Sopenharmony_ci    }
4084514f5e3Sopenharmony_ci    // revise correct a0 - aN virtual regs , for example: ldobjbyname key; sta a2; update value to a2
4094514f5e3Sopenharmony_ci    //         +--------------------------+            ^
4104514f5e3Sopenharmony_ci    //         |       aN                 |            |
4114514f5e3Sopenharmony_ci    //         +--------------------------+            |
4124514f5e3Sopenharmony_ci    //         |       ...                |            |
4134514f5e3Sopenharmony_ci    //         +--------------------------+            |
4144514f5e3Sopenharmony_ci    //         |       a2(this)           |            |
4154514f5e3Sopenharmony_ci    //         +--------------------------+   revise correct vreg
4164514f5e3Sopenharmony_ci    //         |       a1(newtarget)      |            |
4174514f5e3Sopenharmony_ci    //         +--------------------------+            |
4184514f5e3Sopenharmony_ci    //         |       a0(func)           |            |
4194514f5e3Sopenharmony_ci    //         |--------------------------|            v
4204514f5e3Sopenharmony_ci    //         |       v0 - vN            |
4214514f5e3Sopenharmony_ci    //  sp --> |--------------------------|
4224514f5e3Sopenharmony_ci    int32_t vregsAndArgsNum = declaredNumArgs + callFieldNumVregs +
4234514f5e3Sopenharmony_ci        static_cast<int32_t>(method->GetNumRevervedArgs());
4244514f5e3Sopenharmony_ci    for (int32_t i = callFieldNumVregs; i < vregsAndArgsNum; i++) {
4254514f5e3Sopenharmony_ci        JSTaggedValue value = JSTaggedValue::Undefined();
4264514f5e3Sopenharmony_ci        if (HasDeoptValue(curDepth, i)) {
4274514f5e3Sopenharmony_ci            value = GetDeoptValue(curDepth, i);
4284514f5e3Sopenharmony_ci            frameWriter->ReviseValueByIndex(value.GetRawData(), i);
4294514f5e3Sopenharmony_ci        }
4304514f5e3Sopenharmony_ci    }
4314514f5e3Sopenharmony_ci    return true;
4324514f5e3Sopenharmony_ci}
4334514f5e3Sopenharmony_ci
4344514f5e3Sopenharmony_civoid Deoptimizier::Dump(JSTaggedValue callTarget, kungfu::DeoptType type, size_t depth)
4354514f5e3Sopenharmony_ci{
4364514f5e3Sopenharmony_ci    if (thread_->IsPGOProfilerEnable()) {
4374514f5e3Sopenharmony_ci        JSFunction *function = JSFunction::Cast(callTarget);
4384514f5e3Sopenharmony_ci        auto profileTypeInfo = function->GetProfileTypeInfo();
4394514f5e3Sopenharmony_ci        if (profileTypeInfo.IsUndefined()) {
4404514f5e3Sopenharmony_ci            SlowRuntimeStub::NotifyInlineCache(thread_, function);
4414514f5e3Sopenharmony_ci        }
4424514f5e3Sopenharmony_ci    }
4434514f5e3Sopenharmony_ci    if (traceDeopt_) {
4444514f5e3Sopenharmony_ci        std::string checkType = DisplayItems(type);
4454514f5e3Sopenharmony_ci        LOG_TRACE(INFO) << "Check Type: " << checkType;
4464514f5e3Sopenharmony_ci        std::string data = JsStackInfo::BuildJsStackTrace(thread_, true);
4474514f5e3Sopenharmony_ci        LOG_COMPILER(INFO) << "Deoptimize" << data;
4484514f5e3Sopenharmony_ci        const uint8_t *pc = GetMethod(callTarget)->GetBytecodeArray() + pc_.at(depth);
4494514f5e3Sopenharmony_ci        BytecodeInstruction inst(pc);
4504514f5e3Sopenharmony_ci        LOG_COMPILER(INFO) << inst;
4514514f5e3Sopenharmony_ci    }
4524514f5e3Sopenharmony_ci}
4534514f5e3Sopenharmony_ci
4544514f5e3Sopenharmony_cistd::string Deoptimizier::DisplayItems(DeoptType type)
4554514f5e3Sopenharmony_ci{
4564514f5e3Sopenharmony_ci    const std::map<DeoptType, const char *> strMap = {
4574514f5e3Sopenharmony_ci#define DEOPT_NAME_MAP(NAME, TYPE) {DeoptType::TYPE, #NAME},
4584514f5e3Sopenharmony_ci        GATE_META_DATA_DEOPT_REASON(DEOPT_NAME_MAP)
4594514f5e3Sopenharmony_ci#undef DEOPT_NAME_MAP
4604514f5e3Sopenharmony_ci    };
4614514f5e3Sopenharmony_ci    if (strMap.count(type) > 0) {
4624514f5e3Sopenharmony_ci        return strMap.at(type);
4634514f5e3Sopenharmony_ci    }
4644514f5e3Sopenharmony_ci    return "DeoptType-" + std::to_string(static_cast<uint8_t>(type));
4654514f5e3Sopenharmony_ci}
4664514f5e3Sopenharmony_ci
4674514f5e3Sopenharmony_ci// layout of frameWriter
4684514f5e3Sopenharmony_ci//   |--------------------------| --------------> start(n)
4694514f5e3Sopenharmony_ci//   |          args            |
4704514f5e3Sopenharmony_ci//   |          this            |
4714514f5e3Sopenharmony_ci//   |        newTarget         |
4724514f5e3Sopenharmony_ci//   |       callTarget         |
4734514f5e3Sopenharmony_ci//   |          vregs           |
4744514f5e3Sopenharmony_ci//   |---------------------------
4754514f5e3Sopenharmony_ci//   |       ASM Interpreter    |
4764514f5e3Sopenharmony_ci//   +--------------------------+ --------------> end(n)
4774514f5e3Sopenharmony_ci//   |        outputcounts      |          outputcounts = end(n) - start(n)
4784514f5e3Sopenharmony_ci//   |--------------------------| --------------> start(n-1)
4794514f5e3Sopenharmony_ci//   |          args            |
4804514f5e3Sopenharmony_ci//   |          this            |
4814514f5e3Sopenharmony_ci//   |        newTarget         |
4824514f5e3Sopenharmony_ci//   |       callTarget         |
4834514f5e3Sopenharmony_ci//   |          vregs           |
4844514f5e3Sopenharmony_ci//   |-------------------------------------------
4854514f5e3Sopenharmony_ci//   |       ASM Interpreter    |
4864514f5e3Sopenharmony_ci//   +--------------------------+ --------------> end(n-1)
4874514f5e3Sopenharmony_ci//   |        outputcounts      |           outputcounts = end(n-1) - start(n-1)
4884514f5e3Sopenharmony_ci//   |--------------------------| --------------> start(n-1)
4894514f5e3Sopenharmony_ci//   |       ......             |
4904514f5e3Sopenharmony_ci//   +--------------------------+ ---------------
4914514f5e3Sopenharmony_ci//   |        callerFp_         |               ^
4924514f5e3Sopenharmony_ci//   |       returnAddr_        |          stackContext
4934514f5e3Sopenharmony_ci//   |      callFrameTop_       |               |
4944514f5e3Sopenharmony_ci//   |       inlineDepth        |               v
4954514f5e3Sopenharmony_ci//   |--------------------------| ---------------
4964514f5e3Sopenharmony_ci
4974514f5e3Sopenharmony_ciJSTaggedType Deoptimizier::ConstructAsmInterpretFrame()
4984514f5e3Sopenharmony_ci{
4994514f5e3Sopenharmony_ci    FrameWriter frameWriter(this);
5004514f5e3Sopenharmony_ci    // Push asm interpreter frame
5014514f5e3Sopenharmony_ci    for (int32_t curDepth = static_cast<int32_t>(inlineDepth_); curDepth >= 0; curDepth--) {
5024514f5e3Sopenharmony_ci        auto start = frameWriter.GetTop();
5034514f5e3Sopenharmony_ci        JSTaggedValue callTarget = GetDeoptValue(curDepth, static_cast<int32_t>(SpecVregIndex::FUNC_INDEX));
5044514f5e3Sopenharmony_ci        auto method = GetMethod(callTarget);
5054514f5e3Sopenharmony_ci        if (!CollectVirtualRegisters(callTarget, method, &frameWriter, curDepth)) {
5064514f5e3Sopenharmony_ci            return JSTaggedValue::Exception().GetRawData();
5074514f5e3Sopenharmony_ci        }
5084514f5e3Sopenharmony_ci        AsmInterpretedFrame *statePtr = frameWriter.ReserveAsmInterpretedFrame();
5094514f5e3Sopenharmony_ci        const uint8_t *resumePc = method->GetBytecodeArray() + pc_.at(curDepth);
5104514f5e3Sopenharmony_ci        JSTaggedValue thisObj = GetDeoptValue(curDepth, static_cast<int32_t>(SpecVregIndex::THIS_OBJECT_INDEX));
5114514f5e3Sopenharmony_ci        auto acc = GetDeoptValue(curDepth, static_cast<int32_t>(SpecVregIndex::ACC_INDEX));
5124514f5e3Sopenharmony_ci        statePtr->function = callTarget;
5134514f5e3Sopenharmony_ci        statePtr->acc = acc;
5144514f5e3Sopenharmony_ci        statePtr->env = GetDeoptValue(curDepth, static_cast<int32_t>(SpecVregIndex::ENV_INDEX));
5154514f5e3Sopenharmony_ci        statePtr->callSize = GetCallSize(curDepth, resumePc);
5164514f5e3Sopenharmony_ci        statePtr->fp = 0;  // need update
5174514f5e3Sopenharmony_ci        statePtr->thisObj = thisObj;
5184514f5e3Sopenharmony_ci        statePtr->pc = resumePc;
5194514f5e3Sopenharmony_ci        // -uintptr_t skip lr
5204514f5e3Sopenharmony_ci        if (curDepth == 0) {
5214514f5e3Sopenharmony_ci            statePtr->base.prev = reinterpret_cast<JSTaggedType *>(stackContext_.callFrameTop_ - sizeof(uintptr_t));
5224514f5e3Sopenharmony_ci        } else {
5234514f5e3Sopenharmony_ci            statePtr->base.prev = 0; // need update
5244514f5e3Sopenharmony_ci        }
5254514f5e3Sopenharmony_ci
5264514f5e3Sopenharmony_ci        statePtr->base.type = FrameType::ASM_INTERPRETER_FRAME;
5274514f5e3Sopenharmony_ci
5284514f5e3Sopenharmony_ci        // construct stack context
5294514f5e3Sopenharmony_ci        auto end = frameWriter.GetTop();
5304514f5e3Sopenharmony_ci        auto outputCount = start - end;
5314514f5e3Sopenharmony_ci        frameWriter.PushRawValue(outputCount);
5324514f5e3Sopenharmony_ci    }
5334514f5e3Sopenharmony_ci
5344514f5e3Sopenharmony_ci    RelocateCalleeSave();
5354514f5e3Sopenharmony_ci
5364514f5e3Sopenharmony_ci    frameWriter.PushRawValue(stackContext_.callerFp_);
5374514f5e3Sopenharmony_ci    frameWriter.PushRawValue(stackContext_.returnAddr_);
5384514f5e3Sopenharmony_ci    frameWriter.PushRawValue(stackContext_.callFrameTop_);
5394514f5e3Sopenharmony_ci    frameWriter.PushRawValue(inlineDepth_);
5404514f5e3Sopenharmony_ci    return reinterpret_cast<JSTaggedType>(frameWriter.GetTop());
5414514f5e3Sopenharmony_ci}
5424514f5e3Sopenharmony_ci
5434514f5e3Sopenharmony_civoid Deoptimizier::ResetJitHotness(JSFunction *jsFunc) const
5444514f5e3Sopenharmony_ci{
5454514f5e3Sopenharmony_ci    if (jsFunc->GetMachineCode().IsMachineCodeObject()) {
5464514f5e3Sopenharmony_ci        JSTaggedValue profileTypeInfoVal = jsFunc->GetProfileTypeInfo();
5474514f5e3Sopenharmony_ci        if (!profileTypeInfoVal.IsUndefined()) {
5484514f5e3Sopenharmony_ci            ProfileTypeInfo *profileTypeInfo = ProfileTypeInfo::Cast(profileTypeInfoVal.GetTaggedObject());
5494514f5e3Sopenharmony_ci            profileTypeInfo->SetJitHotnessCnt(0);
5504514f5e3Sopenharmony_ci            constexpr uint16_t thresholdStep = 4;
5514514f5e3Sopenharmony_ci            constexpr uint16_t thresholdLimit = ProfileTypeInfo::JIT_DISABLE_FLAG / thresholdStep;
5524514f5e3Sopenharmony_ci            uint16_t threshold = profileTypeInfo->GetJitHotnessThreshold();
5534514f5e3Sopenharmony_ci            threshold = threshold >= thresholdLimit ? ProfileTypeInfo::JIT_DISABLE_FLAG : threshold * thresholdStep;
5544514f5e3Sopenharmony_ci            profileTypeInfo->SetJitHotnessThreshold(threshold);
5554514f5e3Sopenharmony_ci            ProfileTypeInfoCell::Cast(jsFunc->GetRawProfileTypeInfo())->SetMachineCode(thread_, JSTaggedValue::Hole());
5564514f5e3Sopenharmony_ci            Method *method = Method::Cast(jsFunc->GetMethod().GetTaggedObject());
5574514f5e3Sopenharmony_ci            LOG_JIT(DEBUG) << "reset jit hotness for func: " << method->GetMethodName() << ", threshold:" << threshold;
5584514f5e3Sopenharmony_ci        }
5594514f5e3Sopenharmony_ci    }
5604514f5e3Sopenharmony_ci}
5614514f5e3Sopenharmony_ci
5624514f5e3Sopenharmony_civoid Deoptimizier::ClearCompiledCodeStatusWhenDeopt(JSFunction *func, Method *method)
5634514f5e3Sopenharmony_ci{
5644514f5e3Sopenharmony_ci    if (func->GetMachineCode().IsMachineCodeObject()) {
5654514f5e3Sopenharmony_ci        Jit::GetInstance()->GetJitDfx()->SetJitDeoptCount();
5664514f5e3Sopenharmony_ci    }
5674514f5e3Sopenharmony_ci    if (func->IsCompiledCode()) {
5684514f5e3Sopenharmony_ci        bool isFastCall = func->IsCompiledFastCall();  // get this flag before clear it
5694514f5e3Sopenharmony_ci        uintptr_t entry =
5704514f5e3Sopenharmony_ci            isFastCall ? thread_->GetRTInterface(kungfu::RuntimeStubCSigns::ID_FastCallToAsmInterBridge)
5714514f5e3Sopenharmony_ci                       : thread_->GetRTInterface(kungfu::RuntimeStubCSigns::ID_AOTCallToAsmInterBridge);
5724514f5e3Sopenharmony_ci        func->SetCodeEntry(entry);
5734514f5e3Sopenharmony_ci        method->ClearAOTStatusWhenDeopt(entry);
5744514f5e3Sopenharmony_ci        func->ClearCompiledCodeFlags();
5754514f5e3Sopenharmony_ci        ResetJitHotness(func);
5764514f5e3Sopenharmony_ci        func->ClearMachineCode(thread_);
5774514f5e3Sopenharmony_ci    }  // Do not change the func code entry if the method is not aot or deopt has happened already
5784514f5e3Sopenharmony_ci}
5794514f5e3Sopenharmony_ci
5804514f5e3Sopenharmony_civoid Deoptimizier::UpdateAndDumpDeoptInfo(kungfu::DeoptType type)
5814514f5e3Sopenharmony_ci{
5824514f5e3Sopenharmony_ci    // depth records the number of layers of nested calls when deopt occurs
5834514f5e3Sopenharmony_ci    for (size_t i = 0; i <= inlineDepth_; i++) {
5844514f5e3Sopenharmony_ci        JSTaggedValue callTarget = GetDeoptValue(i, static_cast<int32_t>(SpecVregIndex::FUNC_INDEX));
5854514f5e3Sopenharmony_ci        auto func = JSFunction::Cast(callTarget.GetTaggedObject());
5864514f5e3Sopenharmony_ci        if (func->GetMachineCode().IsMachineCodeObject()) {
5874514f5e3Sopenharmony_ci            MachineCode *machineCode = MachineCode::Cast(func->GetMachineCode().GetTaggedObject());
5884514f5e3Sopenharmony_ci            if (type != kungfu::DeoptType::OSRLOOPEXIT &&
5894514f5e3Sopenharmony_ci                machineCode->GetOSROffset() != MachineCode::INVALID_OSR_OFFSET) {
5904514f5e3Sopenharmony_ci                machineCode->SetOsrDeoptFlag(true);
5914514f5e3Sopenharmony_ci            }
5924514f5e3Sopenharmony_ci        }
5934514f5e3Sopenharmony_ci        auto method = GetMethod(callTarget);
5944514f5e3Sopenharmony_ci        if (i == inlineDepth_) {
5954514f5e3Sopenharmony_ci            Dump(callTarget, type, i);
5964514f5e3Sopenharmony_ci        }
5974514f5e3Sopenharmony_ci        ASSERT(thread_ != nullptr);
5984514f5e3Sopenharmony_ci        uint8_t deoptThreshold = method->GetDeoptThreshold();
5994514f5e3Sopenharmony_ci        if (deoptThreshold > 0) {
6004514f5e3Sopenharmony_ci            method->SetDeoptType(type);
6014514f5e3Sopenharmony_ci            method->SetDeoptThreshold(--deoptThreshold);
6024514f5e3Sopenharmony_ci        } else {
6034514f5e3Sopenharmony_ci            ClearCompiledCodeStatusWhenDeopt(func, method);
6044514f5e3Sopenharmony_ci        }
6054514f5e3Sopenharmony_ci    }
6064514f5e3Sopenharmony_ci}
6074514f5e3Sopenharmony_ci
6084514f5e3Sopenharmony_ci// call instructions need compute jumpSize
6094514f5e3Sopenharmony_cisize_t Deoptimizier::GetCallSize(size_t curDepth, const uint8_t *resumePc)
6104514f5e3Sopenharmony_ci{
6114514f5e3Sopenharmony_ci    if (inlineDepth_ > 0 && curDepth != inlineDepth_) {
6124514f5e3Sopenharmony_ci        auto op = BytecodeInstruction(resumePc).GetOpcode();
6134514f5e3Sopenharmony_ci        size_t jumpSize = BytecodeInstruction::Size(op);
6144514f5e3Sopenharmony_ci        return jumpSize;
6154514f5e3Sopenharmony_ci    }
6164514f5e3Sopenharmony_ci    return 0;
6174514f5e3Sopenharmony_ci}
6184514f5e3Sopenharmony_ci
6194514f5e3Sopenharmony_ciint32_t Deoptimizier::EncodeDeoptVregIndex(int32_t index, size_t depth, size_t shift)
6204514f5e3Sopenharmony_ci{
6214514f5e3Sopenharmony_ci    if (index >= 0) {
6224514f5e3Sopenharmony_ci        return (index << shift) | depth;
6234514f5e3Sopenharmony_ci    }
6244514f5e3Sopenharmony_ci    return -((-index << shift) | depth);
6254514f5e3Sopenharmony_ci}
6264514f5e3Sopenharmony_ci
6274514f5e3Sopenharmony_cisize_t Deoptimizier::ComputeShift(size_t depth)
6284514f5e3Sopenharmony_ci{
6294514f5e3Sopenharmony_ci    size_t shift = 0;
6304514f5e3Sopenharmony_ci    if (depth != 0) {
6314514f5e3Sopenharmony_ci        shift = std::floor(std::log2(depth)) + 1;
6324514f5e3Sopenharmony_ci    }
6334514f5e3Sopenharmony_ci    return shift;
6344514f5e3Sopenharmony_ci}
6354514f5e3Sopenharmony_ci
6364514f5e3Sopenharmony_ciint32_t Deoptimizier::DecodeVregIndex(OffsetType id, size_t shift)
6374514f5e3Sopenharmony_ci{
6384514f5e3Sopenharmony_ci    if (id >= 0) {
6394514f5e3Sopenharmony_ci        return id >> shift;
6404514f5e3Sopenharmony_ci    }
6414514f5e3Sopenharmony_ci    return -((-id) >> shift);
6424514f5e3Sopenharmony_ci}
6434514f5e3Sopenharmony_ci
6444514f5e3Sopenharmony_cisize_t Deoptimizier::DecodeDeoptDepth(OffsetType id, size_t shift)
6454514f5e3Sopenharmony_ci{
6464514f5e3Sopenharmony_ci    size_t mask = (1 << shift) - 1;
6474514f5e3Sopenharmony_ci    if (id >= 0) {
6484514f5e3Sopenharmony_ci        return id & mask;
6494514f5e3Sopenharmony_ci    }
6504514f5e3Sopenharmony_ci    return (-id) & mask;
6514514f5e3Sopenharmony_ci}
6524514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
653