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_ECMA_RUNTIM_CALL_INFO_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_ECMA_RUNTIM_CALL_INFO_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include <algorithm> 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_ci#include "ecmascript/common.h" 224514f5e3Sopenharmony_ci#include "ecmascript/js_handle.h" 234514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value.h" 244514f5e3Sopenharmony_ci#include "ecmascript/tagged_array.h" 254514f5e3Sopenharmony_ci 264514f5e3Sopenharmony_cinamespace panda::ecmascript { 274514f5e3Sopenharmony_cistruct EcmaRuntimeCallInfo; 284514f5e3Sopenharmony_ciclass JSThread; 294514f5e3Sopenharmony_ciusing EcmaEntrypoint = JSTaggedValue (*)(EcmaRuntimeCallInfo *); 304514f5e3Sopenharmony_ci 314514f5e3Sopenharmony_cistruct EcmaRuntimeCallInfo : public base::AlignedStruct<base::AlignedPointer::Size(), 324514f5e3Sopenharmony_ci base::AlignedPointer, 334514f5e3Sopenharmony_ci base::AlignedPointer, 344514f5e3Sopenharmony_ci base::AlignedPointer> { 354514f5e3Sopenharmony_ci enum class Index : size_t { 364514f5e3Sopenharmony_ci ThreadIndex = 0, 374514f5e3Sopenharmony_ci NumArgsIndex, 384514f5e3Sopenharmony_ci StackArgsIndex, 394514f5e3Sopenharmony_ci NumOfMembers 404514f5e3Sopenharmony_ci }; 414514f5e3Sopenharmony_ci static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes); 424514f5e3Sopenharmony_ci 434514f5e3Sopenharmony_cipublic: 444514f5e3Sopenharmony_ci inline JSThread *GetThread() const 454514f5e3Sopenharmony_ci { 464514f5e3Sopenharmony_ci return thread_; 474514f5e3Sopenharmony_ci } 484514f5e3Sopenharmony_ci 494514f5e3Sopenharmony_ci static size_t GetThreadOffset(bool isArch32) 504514f5e3Sopenharmony_ci { 514514f5e3Sopenharmony_ci return GetOffset<static_cast<size_t>(Index::ThreadIndex)>(isArch32); 524514f5e3Sopenharmony_ci } 534514f5e3Sopenharmony_ci 544514f5e3Sopenharmony_ci static size_t GetNumArgsOffset(bool isArch32) 554514f5e3Sopenharmony_ci { 564514f5e3Sopenharmony_ci return GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32); 574514f5e3Sopenharmony_ci } 584514f5e3Sopenharmony_ci 594514f5e3Sopenharmony_ci static size_t GetStackArgsOffset(bool isArch32) 604514f5e3Sopenharmony_ci { 614514f5e3Sopenharmony_ci return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32); 624514f5e3Sopenharmony_ci } 634514f5e3Sopenharmony_ci 644514f5e3Sopenharmony_ci static size_t GetNewTargetOffset(bool isArch32) 654514f5e3Sopenharmony_ci { 664514f5e3Sopenharmony_ci return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32) + 674514f5e3Sopenharmony_ci NEW_TARGET_INDEX * sizeof(JSTaggedType); 684514f5e3Sopenharmony_ci } 694514f5e3Sopenharmony_ci 704514f5e3Sopenharmony_ci static size_t GetThisOffset(bool isArch32) 714514f5e3Sopenharmony_ci { 724514f5e3Sopenharmony_ci return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32) + 734514f5e3Sopenharmony_ci THIS_INDEX * sizeof(JSTaggedType); 744514f5e3Sopenharmony_ci } 754514f5e3Sopenharmony_ci 764514f5e3Sopenharmony_ci static size_t GetCallArgOffset(bool isArch32) 774514f5e3Sopenharmony_ci { 784514f5e3Sopenharmony_ci return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32) + 794514f5e3Sopenharmony_ci FIRST_ARGS_INDEX * sizeof(JSTaggedType); 804514f5e3Sopenharmony_ci } 814514f5e3Sopenharmony_ci 824514f5e3Sopenharmony_ci inline void SetNewTarget(const JSTaggedValue tagged) 834514f5e3Sopenharmony_ci { 844514f5e3Sopenharmony_ci SetArg(NEW_TARGET_INDEX, tagged); 854514f5e3Sopenharmony_ci } 864514f5e3Sopenharmony_ci 874514f5e3Sopenharmony_ci inline void SetFunction(const JSTaggedValue tagged) 884514f5e3Sopenharmony_ci { 894514f5e3Sopenharmony_ci SetArg(FUNC_INDEX, tagged); 904514f5e3Sopenharmony_ci } 914514f5e3Sopenharmony_ci 924514f5e3Sopenharmony_ci inline void SetThis(const JSTaggedValue tagged) 934514f5e3Sopenharmony_ci { 944514f5e3Sopenharmony_ci SetArg(THIS_INDEX, tagged); 954514f5e3Sopenharmony_ci } 964514f5e3Sopenharmony_ci 974514f5e3Sopenharmony_ci inline void SetCallArg(uint32_t idx, const JSTaggedValue tagged) 984514f5e3Sopenharmony_ci { 994514f5e3Sopenharmony_ci ASSERT_PRINT(idx < GetArgsNumber(), "Can not set values out of index range"); 1004514f5e3Sopenharmony_ci SetArg(idx + FIRST_ARGS_INDEX, tagged); 1014514f5e3Sopenharmony_ci } 1024514f5e3Sopenharmony_ci 1034514f5e3Sopenharmony_ci inline void SetCallArg(const JSTaggedValue arg) 1044514f5e3Sopenharmony_ci { 1054514f5e3Sopenharmony_ci ASSERT_PRINT(GetArgsNumber() == 1, "args number is not 1"); 1064514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX, arg); 1074514f5e3Sopenharmony_ci } 1084514f5e3Sopenharmony_ci 1094514f5e3Sopenharmony_ci inline void SetCallArg(const JSTaggedValue arg0, const JSTaggedValue arg1) 1104514f5e3Sopenharmony_ci { 1114514f5e3Sopenharmony_ci ASSERT_PRINT(GetArgsNumber() == 2, "args number is not 2"); // 2: args number 1124514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX, arg0); 1134514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX + 1, arg1); 1144514f5e3Sopenharmony_ci } 1154514f5e3Sopenharmony_ci 1164514f5e3Sopenharmony_ci inline void SetCallArg(const JSTaggedValue arg0, const JSTaggedValue arg1, const JSTaggedValue arg2) 1174514f5e3Sopenharmony_ci { 1184514f5e3Sopenharmony_ci ASSERT_PRINT(GetArgsNumber() == 3, "args number is not 3"); // 3: args number 1194514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX, arg0); 1204514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX + 1, arg1); 1214514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX + 2, arg2); // 2: second index 1224514f5e3Sopenharmony_ci } 1234514f5e3Sopenharmony_ci 1244514f5e3Sopenharmony_ci inline void SetCallArg(const JSTaggedValue arg0, const JSTaggedValue arg1, const JSTaggedValue arg2, 1254514f5e3Sopenharmony_ci const JSTaggedValue arg3) 1264514f5e3Sopenharmony_ci { 1274514f5e3Sopenharmony_ci ASSERT_PRINT(GetArgsNumber() == 4, "args number is not 4"); // 4: args number 1284514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX, arg0); 1294514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX + 1, arg1); 1304514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX + 2, arg2); // 2: second index 1314514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX + 3, arg3); // 3: third index 1324514f5e3Sopenharmony_ci } 1334514f5e3Sopenharmony_ci 1344514f5e3Sopenharmony_ci inline void SetCallArg(const JSTaggedValue arg0, const JSTaggedValue arg1, const JSTaggedValue arg2, 1354514f5e3Sopenharmony_ci const JSTaggedValue arg3, const JSTaggedValue arg4) 1364514f5e3Sopenharmony_ci { 1374514f5e3Sopenharmony_ci ASSERT_PRINT(GetArgsNumber() == 5, "args number is not 5"); // 5: args number 1384514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX, arg0); 1394514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX + 1, arg1); 1404514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX + 2, arg2); // 2: second index 1414514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX + 3, arg3); // 3: third index 1424514f5e3Sopenharmony_ci SetArg(FIRST_ARGS_INDEX + 4, arg4); // 4: fourth index 1434514f5e3Sopenharmony_ci } 1444514f5e3Sopenharmony_ci 1454514f5e3Sopenharmony_ci inline void SetCallArg(int32_t argc, const JSTaggedType argv[]) 1464514f5e3Sopenharmony_ci { 1474514f5e3Sopenharmony_ci for (int32_t i = 0; i < argc; i++) { 1484514f5e3Sopenharmony_ci SetCallArg(i, JSTaggedValue(argv[i])); 1494514f5e3Sopenharmony_ci } 1504514f5e3Sopenharmony_ci } 1514514f5e3Sopenharmony_ci 1524514f5e3Sopenharmony_ci inline void SetCallArg(uint32_t argsLength, const JSHandle<TaggedArray> args) 1534514f5e3Sopenharmony_ci { 1544514f5e3Sopenharmony_ci for (uint32_t i = 0; i < argsLength; i++) { 1554514f5e3Sopenharmony_ci SetCallArg(i, args->Get(GetThread(), i)); 1564514f5e3Sopenharmony_ci } 1574514f5e3Sopenharmony_ci } 1584514f5e3Sopenharmony_ci 1594514f5e3Sopenharmony_ci inline void SetCallArg(uint32_t argsLength, const TaggedArray* args) 1604514f5e3Sopenharmony_ci { 1614514f5e3Sopenharmony_ci for (uint32_t i = 0; i < argsLength; i++) { 1624514f5e3Sopenharmony_ci SetCallArg(i, args->Get(GetThread(), i)); 1634514f5e3Sopenharmony_ci } 1644514f5e3Sopenharmony_ci } 1654514f5e3Sopenharmony_ci 1664514f5e3Sopenharmony_ci inline void SetCallArg(uint32_t argsLength, uint32_t startIndex, const EcmaRuntimeCallInfo* argv, int32_t offset) 1674514f5e3Sopenharmony_ci { 1684514f5e3Sopenharmony_ci for (uint32_t i = startIndex; i < argsLength; i++) { 1694514f5e3Sopenharmony_ci SetCallArg(i, argv->GetCallArgValue(i - startIndex + offset)); 1704514f5e3Sopenharmony_ci } 1714514f5e3Sopenharmony_ci } 1724514f5e3Sopenharmony_ci 1734514f5e3Sopenharmony_ci inline JSHandle<JSTaggedValue> GetFunction() const 1744514f5e3Sopenharmony_ci { 1754514f5e3Sopenharmony_ci return GetArg(FUNC_INDEX); 1764514f5e3Sopenharmony_ci } 1774514f5e3Sopenharmony_ci 1784514f5e3Sopenharmony_ci inline JSHandle<JSTaggedValue> GetNewTarget() const 1794514f5e3Sopenharmony_ci { 1804514f5e3Sopenharmony_ci return GetArg(NEW_TARGET_INDEX); 1814514f5e3Sopenharmony_ci } 1824514f5e3Sopenharmony_ci 1834514f5e3Sopenharmony_ci inline JSHandle<JSTaggedValue> GetThis() const 1844514f5e3Sopenharmony_ci { 1854514f5e3Sopenharmony_ci return GetArg(THIS_INDEX); 1864514f5e3Sopenharmony_ci } 1874514f5e3Sopenharmony_ci 1884514f5e3Sopenharmony_ci inline JSHandle<JSTaggedValue> GetCallArg(uint32_t idx) const 1894514f5e3Sopenharmony_ci { 1904514f5e3Sopenharmony_ci return GetArg(idx + FIRST_ARGS_INDEX); 1914514f5e3Sopenharmony_ci } 1924514f5e3Sopenharmony_ci 1934514f5e3Sopenharmony_ci inline JSTaggedValue GetFunctionValue() const 1944514f5e3Sopenharmony_ci { 1954514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> func = GetFunction(); 1964514f5e3Sopenharmony_ci return func.GetTaggedValue(); 1974514f5e3Sopenharmony_ci } 1984514f5e3Sopenharmony_ci 1994514f5e3Sopenharmony_ci inline JSTaggedValue GetNewTargetValue() const 2004514f5e3Sopenharmony_ci { 2014514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> newTarget = GetNewTarget(); 2024514f5e3Sopenharmony_ci return newTarget.GetTaggedValue(); 2034514f5e3Sopenharmony_ci } 2044514f5e3Sopenharmony_ci 2054514f5e3Sopenharmony_ci inline JSTaggedValue GetThisValue() const 2064514f5e3Sopenharmony_ci { 2074514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> thisObj = GetThis(); 2084514f5e3Sopenharmony_ci return thisObj.GetTaggedValue(); 2094514f5e3Sopenharmony_ci } 2104514f5e3Sopenharmony_ci 2114514f5e3Sopenharmony_ci inline JSTaggedValue GetCallArgValue(uint32_t idx) const 2124514f5e3Sopenharmony_ci { 2134514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> arg = GetCallArg(idx); 2144514f5e3Sopenharmony_ci return arg.GetTaggedValue(); 2154514f5e3Sopenharmony_ci } 2164514f5e3Sopenharmony_ci 2174514f5e3Sopenharmony_ci /* 2184514f5e3Sopenharmony_ci * The number of arguments pairs excluding the 'func', 'new.target' and 'this'. For instance: 2194514f5e3Sopenharmony_ci * for code fragment: " foo(v1); ", GetArgsNumber() returns 1 2204514f5e3Sopenharmony_ci */ 2214514f5e3Sopenharmony_ci inline uint32_t GetArgsNumber() const 2224514f5e3Sopenharmony_ci { 2234514f5e3Sopenharmony_ci return numArgs_ - NUM_MANDATORY_JSFUNC_ARGS; 2244514f5e3Sopenharmony_ci } 2254514f5e3Sopenharmony_ci 2264514f5e3Sopenharmony_ci inline JSTaggedType *GetArgs() 2274514f5e3Sopenharmony_ci { 2284514f5e3Sopenharmony_ci return stackArgs_; 2294514f5e3Sopenharmony_ci } 2304514f5e3Sopenharmony_ci 2314514f5e3Sopenharmony_ciprivate: 2324514f5e3Sopenharmony_ci enum ArgsIndex : uint8_t { FUNC_INDEX = 0, NEW_TARGET_INDEX, THIS_INDEX, FIRST_ARGS_INDEX }; 2334514f5e3Sopenharmony_ci 2344514f5e3Sopenharmony_ci inline uintptr_t GetArgAddress(uint32_t idx) const 2354514f5e3Sopenharmony_ci { 2364514f5e3Sopenharmony_ci if (idx < GetArgsNumber() + NUM_MANDATORY_JSFUNC_ARGS) { 2374514f5e3Sopenharmony_ci return reinterpret_cast<uintptr_t>(&stackArgs_[idx]); 2384514f5e3Sopenharmony_ci } 2394514f5e3Sopenharmony_ci return 0U; 2404514f5e3Sopenharmony_ci } 2414514f5e3Sopenharmony_ci 2424514f5e3Sopenharmony_ci inline void SetArg(uint32_t idx, const JSTaggedValue tagged) 2434514f5e3Sopenharmony_ci { 2444514f5e3Sopenharmony_ci uintptr_t addr = GetArgAddress(idx); 2454514f5e3Sopenharmony_ci if (addr != 0U) { 2464514f5e3Sopenharmony_ci *reinterpret_cast<JSTaggedValue *>(addr) = tagged; 2474514f5e3Sopenharmony_ci } 2484514f5e3Sopenharmony_ci } 2494514f5e3Sopenharmony_ci 2504514f5e3Sopenharmony_ci inline JSHandle<JSTaggedValue> GetArg(uint32_t idx) const 2514514f5e3Sopenharmony_ci { 2524514f5e3Sopenharmony_ci return JSHandle<JSTaggedValue>(GetArgAddress(idx)); 2534514f5e3Sopenharmony_ci } 2544514f5e3Sopenharmony_ci 2554514f5e3Sopenharmony_ciprivate: 2564514f5e3Sopenharmony_ci alignas(sizeof(JSTaggedType)) JSThread *thread_ {nullptr}; 2574514f5e3Sopenharmony_ci alignas(sizeof(JSTaggedType)) uint32_t numArgs_ {0}; // include func, newTarget, this, equal to stackArgs size. 2584514f5e3Sopenharmony_ci __extension__ alignas(sizeof(JSTaggedType)) JSTaggedType stackArgs_[0]; // NOLINT(modernize-avoid-c-arrays) 2594514f5e3Sopenharmony_ci}; 2604514f5e3Sopenharmony_ci} // namespace panda::ecmascript 2614514f5e3Sopenharmony_ci 2624514f5e3Sopenharmony_ci#endif // ECMASCRIPT_ECMA_RUNTIM_CALL_INFO_H 263