• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_ECMA_RUNTIM_CALL_INFO_H
17 #define ECMASCRIPT_ECMA_RUNTIM_CALL_INFO_H
18 
19 #include <algorithm>
20 
21 #include "ecmascript/base/aligned_struct.h"
22 #include "ecmascript/common.h"
23 #include "ecmascript/js_handle.h"
24 #include "ecmascript/js_tagged_value.h"
25 #include "ecmascript/tagged_array.h"
26 
27 namespace panda::ecmascript {
28 struct EcmaRuntimeCallInfo;
29 class JSThread;
30 using EcmaEntrypoint = JSTaggedValue (*)(EcmaRuntimeCallInfo *);
31 
32 struct EcmaRuntimeCallInfo : public base::AlignedStruct<base::AlignedPointer::Size(),
33                                                         base::AlignedPointer,
34                                                         base::AlignedPointer,
35                                                         base::AlignedPointer> {
36     enum class Index : size_t {
37         ThreadIndex = 0,
38         NumArgsIndex,
39         StackArgsIndex,
40         NumOfMembers
41     };
42     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
43 
44 public:
GetThreadEcmaRuntimeCallInfo45     inline JSThread *GetThread() const
46     {
47         return thread_;
48     }
49 
GetThreadOffsetEcmaRuntimeCallInfo50     static size_t GetThreadOffset(bool isArch32)
51     {
52         return GetOffset<static_cast<size_t>(Index::ThreadIndex)>(isArch32);
53     }
54 
GetNumArgsOffsetEcmaRuntimeCallInfo55     static size_t GetNumArgsOffset(bool isArch32)
56     {
57         return GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32);
58     }
59 
GetStackArgsOffsetEcmaRuntimeCallInfo60     static size_t GetStackArgsOffset(bool isArch32)
61     {
62         return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32);
63     }
64 
GetNewTargetOffsetEcmaRuntimeCallInfo65     static size_t GetNewTargetOffset(bool isArch32)
66     {
67         return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32) +
68             NEW_TARGET_INDEX * sizeof(JSTaggedType);
69     }
70 
GetThisOffsetEcmaRuntimeCallInfo71     static size_t GetThisOffset(bool isArch32)
72     {
73         return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32) +
74             THIS_INDEX * sizeof(JSTaggedType);
75     }
76 
GetCallArgOffsetEcmaRuntimeCallInfo77     static size_t GetCallArgOffset(bool isArch32)
78     {
79         return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32) +
80             FIRST_ARGS_INDEX * sizeof(JSTaggedType);
81     }
82 
SetNewTargetEcmaRuntimeCallInfo83     inline void SetNewTarget(const JSTaggedValue tagged)
84     {
85         SetArg(NEW_TARGET_INDEX, tagged);
86     }
87 
SetFunctionEcmaRuntimeCallInfo88     inline void SetFunction(const JSTaggedValue tagged)
89     {
90         SetArg(FUNC_INDEX, tagged);
91     }
92 
SetThisEcmaRuntimeCallInfo93     inline void SetThis(const JSTaggedValue tagged)
94     {
95         SetArg(THIS_INDEX, tagged);
96     }
97 
SetCallArgEcmaRuntimeCallInfo98     inline void SetCallArg(uint32_t idx, const JSTaggedValue tagged)
99     {
100         ASSERT_PRINT(idx < GetArgsNumber(), "Can not set values out of index range");
101         SetArg(idx + FIRST_ARGS_INDEX, tagged);
102     }
103 
SetCallArgEcmaRuntimeCallInfo104     inline void SetCallArg(const JSTaggedValue arg)
105     {
106         ASSERT_PRINT(GetArgsNumber() == 1, "args number is not 1");
107         SetArg(FIRST_ARGS_INDEX, arg);
108     }
109 
SetCallArgEcmaRuntimeCallInfo110     inline void SetCallArg(const JSTaggedValue arg0, const JSTaggedValue arg1)
111     {
112         ASSERT_PRINT(GetArgsNumber() == 2, "args number is not 2");  // 2: args number
113         SetArg(FIRST_ARGS_INDEX, arg0);
114         SetArg(FIRST_ARGS_INDEX + 1, arg1);
115     }
116 
SetCallArgEcmaRuntimeCallInfo117     inline void SetCallArg(const JSTaggedValue arg0, const JSTaggedValue arg1, const JSTaggedValue arg2)
118     {
119         ASSERT_PRINT(GetArgsNumber() == 3, "args number is not 3");  // 3: args number
120         SetArg(FIRST_ARGS_INDEX, arg0);
121         SetArg(FIRST_ARGS_INDEX + 1, arg1);
122         SetArg(FIRST_ARGS_INDEX + 2, arg2);  // 2: second index
123     }
124 
SetCallArgEcmaRuntimeCallInfo125     inline void SetCallArg(const JSTaggedValue arg0, const JSTaggedValue arg1, const JSTaggedValue arg2,
126                            const JSTaggedValue arg3)
127     {
128         ASSERT_PRINT(GetArgsNumber() == 4, "args number is not 4");  // 4: args number
129         SetArg(FIRST_ARGS_INDEX, arg0);
130         SetArg(FIRST_ARGS_INDEX + 1, arg1);
131         SetArg(FIRST_ARGS_INDEX + 2, arg2);  // 2: second index
132         SetArg(FIRST_ARGS_INDEX + 3, arg3);  // 3: third index
133     }
134 
SetCallArgEcmaRuntimeCallInfo135     inline void SetCallArg(const JSTaggedValue arg0, const JSTaggedValue arg1, const JSTaggedValue arg2,
136                            const JSTaggedValue arg3, const JSTaggedValue arg4)
137     {
138         ASSERT_PRINT(GetArgsNumber() == 5, "args number is not 5");  // 5: args number
139         SetArg(FIRST_ARGS_INDEX, arg0);
140         SetArg(FIRST_ARGS_INDEX + 1, arg1);
141         SetArg(FIRST_ARGS_INDEX + 2, arg2);  // 2: second index
142         SetArg(FIRST_ARGS_INDEX + 3, arg3);  // 3: third index
143         SetArg(FIRST_ARGS_INDEX + 4, arg4);  // 4: fourth index
144     }
145 
SetCallArgEcmaRuntimeCallInfo146     inline void SetCallArg(int32_t argc, const JSTaggedType argv[])
147     {
148         for (int32_t i = 0; i < argc; i++) {
149             SetCallArg(i, JSTaggedValue(argv[i]));
150         }
151     }
152 
SetCallArgEcmaRuntimeCallInfo153     inline void SetCallArg(uint32_t argsLength, const JSHandle<TaggedArray> args)
154     {
155         for (uint32_t i = 0; i < argsLength; i++) {
156             SetCallArg(i, args->Get(GetThread(), i));
157         }
158     }
159 
SetCallArgEcmaRuntimeCallInfo160     inline void SetCallArg(uint32_t argsLength, const TaggedArray* args)
161     {
162         for (uint32_t i = 0; i < argsLength; i++) {
163             SetCallArg(i, args->Get(GetThread(), i));
164         }
165     }
166 
SetCallArgEcmaRuntimeCallInfo167     inline void SetCallArg(uint32_t argsLength, uint32_t startIndex, const EcmaRuntimeCallInfo* argv, int32_t offset)
168     {
169         for (uint32_t i = startIndex; i < argsLength; i++) {
170             SetCallArg(i, argv->GetCallArgValue(i - startIndex + offset));
171         }
172     }
173 
GetFunctionEcmaRuntimeCallInfo174     inline JSHandle<JSTaggedValue> GetFunction() const
175     {
176         return GetArg(FUNC_INDEX);
177     }
178 
GetNewTargetEcmaRuntimeCallInfo179     inline JSHandle<JSTaggedValue> GetNewTarget() const
180     {
181         return GetArg(NEW_TARGET_INDEX);
182     }
183 
GetThisEcmaRuntimeCallInfo184     inline JSHandle<JSTaggedValue> GetThis() const
185     {
186         return GetArg(THIS_INDEX);
187     }
188 
GetCallArgEcmaRuntimeCallInfo189     inline JSHandle<JSTaggedValue> GetCallArg(uint32_t idx) const
190     {
191         return GetArg(idx + FIRST_ARGS_INDEX);
192     }
193 
GetFunctionValueEcmaRuntimeCallInfo194     inline JSTaggedValue GetFunctionValue() const
195     {
196         JSHandle<JSTaggedValue> func = GetFunction();
197         return func.GetTaggedValue();
198     }
199 
GetNewTargetValueEcmaRuntimeCallInfo200     inline JSTaggedValue GetNewTargetValue() const
201     {
202         JSHandle<JSTaggedValue> newTarget = GetNewTarget();
203         return newTarget.GetTaggedValue();
204     }
205 
GetThisValueEcmaRuntimeCallInfo206     inline JSTaggedValue GetThisValue() const
207     {
208         JSHandle<JSTaggedValue> thisObj = GetThis();
209         return thisObj.GetTaggedValue();
210     }
211 
GetCallArgValueEcmaRuntimeCallInfo212     inline JSTaggedValue GetCallArgValue(uint32_t idx) const
213     {
214         JSHandle<JSTaggedValue> arg = GetCallArg(idx);
215         return arg.GetTaggedValue();
216     }
217 
218     /*
219      * The number of arguments pairs excluding the 'func', 'new.target' and 'this'. For instance:
220      * for code fragment: " foo(v1); ", GetArgsNumber() returns 1
221      */
GetArgsNumberEcmaRuntimeCallInfo222     inline uint32_t GetArgsNumber() const
223     {
224         return numArgs_ - NUM_MANDATORY_JSFUNC_ARGS;
225     }
226 
GetArgsEcmaRuntimeCallInfo227     inline JSTaggedType *GetArgs()
228     {
229         return stackArgs_;
230     }
231 
232 private:
233     enum ArgsIndex : uint8_t { FUNC_INDEX = 0, NEW_TARGET_INDEX, THIS_INDEX, FIRST_ARGS_INDEX };
234 
GetArgAddressEcmaRuntimeCallInfo235     inline uintptr_t GetArgAddress(uint32_t idx) const
236     {
237         if (idx < GetArgsNumber() + NUM_MANDATORY_JSFUNC_ARGS) {
238             return reinterpret_cast<uintptr_t>(&stackArgs_[idx]);
239         }
240         return 0U;
241     }
242 
SetArgEcmaRuntimeCallInfo243     inline void SetArg(uint32_t idx, const JSTaggedValue tagged)
244     {
245         uintptr_t addr = GetArgAddress(idx);
246         if (addr != 0U) {
247             *reinterpret_cast<JSTaggedValue *>(addr) = tagged;
248         }
249     }
250 
GetArgEcmaRuntimeCallInfo251     inline JSHandle<JSTaggedValue> GetArg(uint32_t idx) const
252     {
253         return JSHandle<JSTaggedValue>(GetArgAddress(idx));
254     }
255 
256 private:
257     alignas(sizeof(JSTaggedType)) JSThread *thread_ {nullptr};
258     alignas(sizeof(JSTaggedType)) uint32_t numArgs_ {0};  // include func, newTarget, this, equal to stackArgs size.
259     __extension__ alignas(sizeof(JSTaggedType)) JSTaggedType stackArgs_[0];  // NOLINT(modernize-avoid-c-arrays)
260 };
261 }  // namespace panda::ecmascript
262 
263 #endif  // ECMASCRIPT_ECMA_RUNTIM_CALL_INFO_H
264