• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/common.h"
22 #include "ecmascript/js_handle.h"
23 #include "ecmascript/js_tagged_value.h"
24 #include "ecmascript/js_thread.h"
25 #include "ecmascript/tagged_array.h"
26 
27 namespace panda::ecmascript {
28 struct EcmaRuntimeCallInfo;
29 using EcmaEntrypoint = JSTaggedValue (*)(EcmaRuntimeCallInfo *);
30 
31 struct EcmaRuntimeCallInfo : public base::AlignedStruct<base::AlignedPointer::Size(),
32                                                         base::AlignedPointer,
33                                                         base::AlignedPointer,
34                                                         base::AlignedPointer> {
35     enum class Index : size_t {
36         ThreadIndex = 0,
37         NumArgsIndex,
38         StackArgsIndex,
39         NumOfMembers
40     };
41     static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
42 
43 public:
GetThreadEcmaRuntimeCallInfo44     inline JSThread *GetThread() const
45     {
46         return thread_;
47     }
48 
GetThreadOffsetEcmaRuntimeCallInfo49     static size_t GetThreadOffset(bool isArch32)
50     {
51         return GetOffset<static_cast<size_t>(Index::ThreadIndex)>(isArch32);
52     }
53 
GetNumArgsOffsetEcmaRuntimeCallInfo54     static size_t GetNumArgsOffset(bool isArch32)
55     {
56         return GetOffset<static_cast<size_t>(Index::NumArgsIndex)>(isArch32);
57     }
58 
GetStackArgsOffsetEcmaRuntimeCallInfo59     static size_t GetStackArgsOffset(bool isArch32)
60     {
61         return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32);
62     }
63 
GetNewTargetOffsetEcmaRuntimeCallInfo64     static size_t GetNewTargetOffset(bool isArch32)
65     {
66         return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32) +
67             NEW_TARGET_INDEX * sizeof(JSTaggedType);
68     }
69 
GetThisOffsetEcmaRuntimeCallInfo70     static size_t GetThisOffset(bool isArch32)
71     {
72         return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32) +
73             THIS_INDEX * sizeof(JSTaggedType);
74     }
75 
GetCallArgOffsetEcmaRuntimeCallInfo76     static size_t GetCallArgOffset(bool isArch32)
77     {
78         return GetOffset<static_cast<size_t>(Index::StackArgsIndex)>(isArch32) +
79             FIRST_ARGS_INDEX * sizeof(JSTaggedType);
80     }
81 
SetNewTargetEcmaRuntimeCallInfo82     inline void SetNewTarget(const JSTaggedValue tagged)
83     {
84         SetArg(NEW_TARGET_INDEX, tagged);
85     }
86 
SetFunctionEcmaRuntimeCallInfo87     inline void SetFunction(const JSTaggedValue tagged)
88     {
89         SetArg(FUNC_INDEX, tagged);
90     }
91 
SetThisEcmaRuntimeCallInfo92     inline void SetThis(const JSTaggedValue tagged)
93     {
94         SetArg(THIS_INDEX, tagged);
95     }
96 
SetCallArgEcmaRuntimeCallInfo97     inline void SetCallArg(uint32_t idx, const JSTaggedValue tagged)
98     {
99         ASSERT_PRINT(idx < GetArgsNumber(), "Can not set values out of index range");
100         SetArg(idx + FIRST_ARGS_INDEX, tagged);
101     }
102 
SetCallArgEcmaRuntimeCallInfo103     inline void SetCallArg(const JSTaggedValue arg)
104     {
105         ASSERT_PRINT(GetArgsNumber() == 1, "args number is not 1");
106         SetArg(FIRST_ARGS_INDEX, arg);
107     }
108 
SetCallArgEcmaRuntimeCallInfo109     inline void SetCallArg(const JSTaggedValue arg0, const JSTaggedValue arg1)
110     {
111         ASSERT_PRINT(GetArgsNumber() == 2, "args number is not 2");  // 2: args number
112         SetArg(FIRST_ARGS_INDEX, arg0);
113         SetArg(FIRST_ARGS_INDEX + 1, arg1);
114     }
115 
SetCallArgEcmaRuntimeCallInfo116     inline void SetCallArg(const JSTaggedValue arg0, const JSTaggedValue arg1, const JSTaggedValue arg2)
117     {
118         ASSERT_PRINT(GetArgsNumber() == 3, "args number is not 3");  // 3: args number
119         SetArg(FIRST_ARGS_INDEX, arg0);
120         SetArg(FIRST_ARGS_INDEX + 1, arg1);
121         SetArg(FIRST_ARGS_INDEX + 2, arg2);  // 2: second index
122     }
123 
SetCallArgEcmaRuntimeCallInfo124     inline void SetCallArg(const JSTaggedValue arg0, const JSTaggedValue arg1, const JSTaggedValue arg2,
125                            const JSTaggedValue arg3)
126     {
127         ASSERT_PRINT(GetArgsNumber() == 4, "args number is not 4");  // 4: args number
128         SetArg(FIRST_ARGS_INDEX, arg0);
129         SetArg(FIRST_ARGS_INDEX + 1, arg1);
130         SetArg(FIRST_ARGS_INDEX + 2, arg2);  // 2: second index
131         SetArg(FIRST_ARGS_INDEX + 3, arg3);  // 3: third index
132     }
133 
SetCallArgEcmaRuntimeCallInfo134     inline void SetCallArg(const JSTaggedValue arg0, const JSTaggedValue arg1, const JSTaggedValue arg2,
135                            const JSTaggedValue arg3, const JSTaggedValue arg4)
136     {
137         ASSERT_PRINT(GetArgsNumber() == 5, "args number is not 5");  // 5: args number
138         SetArg(FIRST_ARGS_INDEX, arg0);
139         SetArg(FIRST_ARGS_INDEX + 1, arg1);
140         SetArg(FIRST_ARGS_INDEX + 2, arg2);  // 2: second index
141         SetArg(FIRST_ARGS_INDEX + 3, arg3);  // 3: third index
142         SetArg(FIRST_ARGS_INDEX + 4, arg4);  // 4: fourth index
143     }
144 
SetCallArgEcmaRuntimeCallInfo145     inline void SetCallArg(int32_t argc, const JSTaggedType argv[])
146     {
147         for (int32_t i = 0; i < argc; i++) {
148             SetCallArg(i, JSTaggedValue(argv[i]));
149         }
150     }
151 
SetCallArgEcmaRuntimeCallInfo152     inline void SetCallArg(uint32_t argsLength, const JSHandle<TaggedArray> args)
153     {
154         for (uint32_t i = 0; i < argsLength; i++) {
155             SetCallArg(i, args->Get(GetThread(), i));
156         }
157     }
158 
SetCallArgEcmaRuntimeCallInfo159     inline void SetCallArg(uint32_t argsLength, const TaggedArray* args)
160     {
161         for (uint32_t i = 0; i < argsLength; i++) {
162             SetCallArg(i, args->Get(GetThread(), i));
163         }
164     }
165 
SetCallArgEcmaRuntimeCallInfo166     inline void SetCallArg(uint32_t argsLength, uint32_t startIndex, const EcmaRuntimeCallInfo* argv, int32_t offset)
167     {
168         for (uint32_t i = startIndex; i < argsLength; i++) {
169             SetCallArg(i, argv->GetCallArgValue(i - startIndex + offset));
170         }
171     }
172 
GetFunctionEcmaRuntimeCallInfo173     inline JSHandle<JSTaggedValue> GetFunction() const
174     {
175         return GetArg(FUNC_INDEX);
176     }
177 
GetNewTargetEcmaRuntimeCallInfo178     inline JSHandle<JSTaggedValue> GetNewTarget() const
179     {
180         return GetArg(NEW_TARGET_INDEX);
181     }
182 
GetThisEcmaRuntimeCallInfo183     inline JSHandle<JSTaggedValue> GetThis() const
184     {
185         return GetArg(THIS_INDEX);
186     }
187 
GetCallArgEcmaRuntimeCallInfo188     inline JSHandle<JSTaggedValue> GetCallArg(uint32_t idx) const
189     {
190         return GetArg(idx + FIRST_ARGS_INDEX);
191     }
192 
GetFunctionValueEcmaRuntimeCallInfo193     inline JSTaggedValue GetFunctionValue() const
194     {
195         JSHandle<JSTaggedValue> func = GetFunction();
196         return func.GetTaggedValue();
197     }
198 
GetNewTargetValueEcmaRuntimeCallInfo199     inline JSTaggedValue GetNewTargetValue() const
200     {
201         JSHandle<JSTaggedValue> newTarget = GetNewTarget();
202         return newTarget.GetTaggedValue();
203     }
204 
GetThisValueEcmaRuntimeCallInfo205     inline JSTaggedValue GetThisValue() const
206     {
207         JSHandle<JSTaggedValue> thisObj = GetThis();
208         return thisObj.GetTaggedValue();
209     }
210 
GetCallArgValueEcmaRuntimeCallInfo211     inline JSTaggedValue GetCallArgValue(uint32_t idx) const
212     {
213         JSHandle<JSTaggedValue> arg = GetCallArg(idx);
214         return arg.GetTaggedValue();
215     }
216 
217     /*
218      * The number of arguments pairs excluding the 'func', 'new.target' and 'this'. For instance:
219      * for code fragment: " foo(v1); ", GetArgsNumber() returns 1
220      */
GetArgsNumberEcmaRuntimeCallInfo221     inline uint32_t GetArgsNumber() const
222     {
223         return numArgs_ - NUM_MANDATORY_JSFUNC_ARGS;
224     }
225 
GetArgsEcmaRuntimeCallInfo226     inline JSTaggedType *GetArgs()
227     {
228         return stackArgs_;
229     }
230 
231 private:
232     enum ArgsIndex : uint8_t { FUNC_INDEX = 0, NEW_TARGET_INDEX, THIS_INDEX, FIRST_ARGS_INDEX };
233 
GetArgAddressEcmaRuntimeCallInfo234     inline uintptr_t GetArgAddress(uint32_t idx) const
235     {
236         if (idx < GetArgsNumber() + NUM_MANDATORY_JSFUNC_ARGS) {
237             return reinterpret_cast<uintptr_t>(&stackArgs_[idx]);
238         }
239         return 0U;
240     }
241 
SetArgEcmaRuntimeCallInfo242     inline void SetArg(uint32_t idx, const JSTaggedValue tagged)
243     {
244         uintptr_t addr = GetArgAddress(idx);
245         if (addr != 0U) {
246             *reinterpret_cast<JSTaggedValue *>(addr) = tagged;
247         }
248     }
249 
GetArgEcmaRuntimeCallInfo250     inline JSHandle<JSTaggedValue> GetArg(uint32_t idx) const
251     {
252         return JSHandle<JSTaggedValue>(GetArgAddress(idx));
253     }
254 
255 private:
256     alignas(sizeof(JSTaggedType)) JSThread *thread_ {nullptr};
257     alignas(sizeof(JSTaggedType)) uint32_t numArgs_ {0};  // include func, newTarget, this, equal to stackArgs size.
258     __extension__ alignas(sizeof(JSTaggedType)) JSTaggedType stackArgs_[0];  // NOLINT(modernize-avoid-c-arrays)
259 };
260 }  // namespace panda::ecmascript
261 
262 #endif  // ECMASCRIPT_ECMA_RUNTIM_CALL_INFO_H
263