14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021 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#include "ecmascript/interpreter/interpreter-inl.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_cinamespace panda::ecmascript {
194514f5e3Sopenharmony_ci// make EcmaRuntimeCallInfo in stack pointer as fallows:
204514f5e3Sopenharmony_ci//   +----------------------+   —
214514f5e3Sopenharmony_ci//   |        args...       |   ^
224514f5e3Sopenharmony_ci//   |----------------------|   |
234514f5e3Sopenharmony_ci//   |        numArgs       |   |
244514f5e3Sopenharmony_ci//   |----------------------|   |
254514f5e3Sopenharmony_ci//   |        this          |   |
264514f5e3Sopenharmony_ci//   |----------------------| EcmaRuntimeCallInfo
274514f5e3Sopenharmony_ci//   |       newTarget      |   |
284514f5e3Sopenharmony_ci//   |----------------------|   |
294514f5e3Sopenharmony_ci//   |        func          |   v
304514f5e3Sopenharmony_ci//   +----------------------+   —
314514f5e3Sopenharmony_ci//   |      base.type       |   ^
324514f5e3Sopenharmony_ci//   |----------------------|   |
334514f5e3Sopenharmony_ci//   |      base.prev       | InterpretedEntryFrame
344514f5e3Sopenharmony_ci//   |----------------------|   |
354514f5e3Sopenharmony_ci//   |          pc          |   v
364514f5e3Sopenharmony_ci//   +--------------------------+
374514f5e3Sopenharmony_ciEcmaRuntimeCallInfo* EcmaInterpreter::NewRuntimeCallInfoBase(
384514f5e3Sopenharmony_ci    JSThread *thread, JSTaggedType func, JSTaggedType thisObj, JSTaggedType newTarget,
394514f5e3Sopenharmony_ci    uint32_t numArgs, StackCheck needCheckStack)
404514f5e3Sopenharmony_ci{
414514f5e3Sopenharmony_ci    JSTaggedType *prevSp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame());
424514f5e3Sopenharmony_ci    JSTaggedType *newSp = GetInterpreterFrameEnd(thread, prevSp);
434514f5e3Sopenharmony_ci    if (needCheckStack == StackCheck::YES &&
444514f5e3Sopenharmony_ci        UNLIKELY(thread->DoStackOverflowCheck(newSp - numArgs - NUM_MANDATORY_JSFUNC_ARGS))) {
454514f5e3Sopenharmony_ci        return nullptr;
464514f5e3Sopenharmony_ci    }
474514f5e3Sopenharmony_ci
484514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < numArgs; i++) {
494514f5e3Sopenharmony_ci        *(--newSp) = JSTaggedValue::VALUE_UNDEFINED;
504514f5e3Sopenharmony_ci    }
514514f5e3Sopenharmony_ci    *(--newSp) = thisObj;
524514f5e3Sopenharmony_ci    *(--newSp) = newTarget;
534514f5e3Sopenharmony_ci    *(--newSp) = func;
544514f5e3Sopenharmony_ci    *(--newSp) = numArgs + NUM_MANDATORY_JSFUNC_ARGS;
554514f5e3Sopenharmony_ci    *(--newSp) = ToUintPtr(thread);
564514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *ecmaRuntimeCallInfo = reinterpret_cast<EcmaRuntimeCallInfo *>(newSp);
574514f5e3Sopenharmony_ci
584514f5e3Sopenharmony_ci    // create entry frame.
594514f5e3Sopenharmony_ci    InterpretedEntryFrame *entryState = InterpretedEntryFrame::GetFrameFromSp(newSp);
604514f5e3Sopenharmony_ci    entryState->base.type = FrameType::INTERPRETER_ENTRY_FRAME;
614514f5e3Sopenharmony_ci    entryState->base.prev = prevSp;
624514f5e3Sopenharmony_ci    entryState->pc = nullptr;
634514f5e3Sopenharmony_ci
644514f5e3Sopenharmony_ci    thread->SetCurrentSPFrame(newSp);
654514f5e3Sopenharmony_ci    return ecmaRuntimeCallInfo;
664514f5e3Sopenharmony_ci}
674514f5e3Sopenharmony_ci
684514f5e3Sopenharmony_ciEcmaRuntimeCallInfo* EcmaInterpreter::NewRuntimeCallInfo(
694514f5e3Sopenharmony_ci    JSThread *thread, JSTaggedValue func, JSTaggedValue thisObj, JSTaggedValue newTarget,
704514f5e3Sopenharmony_ci    uint32_t numArgs, StackCheck needCheckStack)
714514f5e3Sopenharmony_ci{
724514f5e3Sopenharmony_ci    return NewRuntimeCallInfoBase(thread, func.GetRawData(), thisObj.GetRawData(), newTarget.GetRawData(),
734514f5e3Sopenharmony_ci        numArgs, needCheckStack);
744514f5e3Sopenharmony_ci}
754514f5e3Sopenharmony_ci
764514f5e3Sopenharmony_ciEcmaRuntimeCallInfo* EcmaInterpreter::NewRuntimeCallInfo(
774514f5e3Sopenharmony_ci    JSThread *thread, JSHandle<JSTaggedValue> func, JSHandle<JSTaggedValue> thisObj,
784514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> newTarget, uint32_t numArgs, StackCheck needCheckStack)
794514f5e3Sopenharmony_ci{
804514f5e3Sopenharmony_ci    return NewRuntimeCallInfoBase(thread, func.GetTaggedType(), thisObj.GetTaggedType(), newTarget.GetTaggedType(),
814514f5e3Sopenharmony_ci        numArgs, needCheckStack);
824514f5e3Sopenharmony_ci}
834514f5e3Sopenharmony_ci
844514f5e3Sopenharmony_ciEcmaRuntimeCallInfo* EcmaInterpreter::ReBuildRuntimeCallInfo(JSThread *thread, EcmaRuntimeCallInfo* info,
854514f5e3Sopenharmony_ci    int numArgs, StackCheck needCheckStack)
864514f5e3Sopenharmony_ci{
874514f5e3Sopenharmony_ci    JSTaggedValue func = info->GetFunctionValue();
884514f5e3Sopenharmony_ci    JSTaggedValue newTarget = info->GetNewTargetValue();
894514f5e3Sopenharmony_ci    JSTaggedValue thisObj = info->GetThisValue();
904514f5e3Sopenharmony_ci    JSTaggedType *currentSp = reinterpret_cast<JSTaggedType *>(info);
914514f5e3Sopenharmony_ci
924514f5e3Sopenharmony_ci    InterpretedEntryFrame *currentEntryState = InterpretedEntryFrame::GetFrameFromSp(currentSp);
934514f5e3Sopenharmony_ci    JSTaggedType *prevSp = currentEntryState->base.prev;
944514f5e3Sopenharmony_ci
954514f5e3Sopenharmony_ci    int actualArgc = static_cast<int>(info->GetArgsNumber());
964514f5e3Sopenharmony_ci    std::vector<JSTaggedType> args(actualArgc);
974514f5e3Sopenharmony_ci    for (int i = 0; i < actualArgc; i++) {
984514f5e3Sopenharmony_ci        args[i] = info->GetCallArgValue(actualArgc - i - 1).GetRawData();
994514f5e3Sopenharmony_ci    }
1004514f5e3Sopenharmony_ci    currentSp += (info->GetArgsNumber() + NUM_MANDATORY_JSFUNC_ARGS + 2); // 2: include thread_ and numArgs_
1014514f5e3Sopenharmony_ci    if (needCheckStack == StackCheck::YES &&
1024514f5e3Sopenharmony_ci        UNLIKELY(thread->DoStackOverflowCheck(currentSp - numArgs - NUM_MANDATORY_JSFUNC_ARGS))) {
1034514f5e3Sopenharmony_ci        return nullptr;
1044514f5e3Sopenharmony_ci    }
1054514f5e3Sopenharmony_ci    ASSERT(numArgs != actualArgc);
1064514f5e3Sopenharmony_ci    for (int i = 0; i < (numArgs - actualArgc); i++) {
1074514f5e3Sopenharmony_ci        *(--currentSp) = JSTaggedValue::VALUE_UNDEFINED;
1084514f5e3Sopenharmony_ci    }
1094514f5e3Sopenharmony_ci    for (int i = 0; i < actualArgc; i++) {
1104514f5e3Sopenharmony_ci        *(--currentSp) = args[i];
1114514f5e3Sopenharmony_ci    }
1124514f5e3Sopenharmony_ci    *(--currentSp) = thisObj.GetRawData();
1134514f5e3Sopenharmony_ci    *(--currentSp) = newTarget.GetRawData();
1144514f5e3Sopenharmony_ci    *(--currentSp) = func.GetRawData();
1154514f5e3Sopenharmony_ci    *(--currentSp) = numArgs + static_cast<int>(NUM_MANDATORY_JSFUNC_ARGS);
1164514f5e3Sopenharmony_ci    *(--currentSp) = ToUintPtr(thread);
1174514f5e3Sopenharmony_ci    EcmaRuntimeCallInfo *ecmaRuntimeCallInfo = reinterpret_cast<EcmaRuntimeCallInfo *>(currentSp);
1184514f5e3Sopenharmony_ci
1194514f5e3Sopenharmony_ci    InterpretedEntryFrame *entryState = InterpretedEntryFrame::GetFrameFromSp(currentSp);
1204514f5e3Sopenharmony_ci    entryState->base.type = FrameType::INTERPRETER_ENTRY_FRAME;
1214514f5e3Sopenharmony_ci    entryState->base.prev = prevSp;
1224514f5e3Sopenharmony_ci    entryState->pc = nullptr;
1234514f5e3Sopenharmony_ci
1244514f5e3Sopenharmony_ci    thread->SetCurrentSPFrame(currentSp);
1254514f5e3Sopenharmony_ci    return ecmaRuntimeCallInfo;
1264514f5e3Sopenharmony_ci}
1274514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
128