• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_JS_METHOD_H
17 #define ECMASCRIPT_JS_METHOD_H
18 
19 #include "ecmascript/ecma_macros.h"
20 #include "ecmascript/jspandafile/method_literal.h"
21 #include "ecmascript/js_tagged_value.h"
22 #include "ecmascript/mem/barriers.h"
23 #include "ecmascript/mem/c_string.h"
24 #include "ecmascript/mem/visitor.h"
25 
26 #include "libpandafile/file.h"
27 
28 namespace panda::ecmascript {
29 class JSPandaFile;
30 using EntityId = panda_file::File::EntityId;
31 class Method : public TaggedObject {
32 public:
33     CAST_CHECK(Method, IsMethod);
34 
SetNumArgsWithCallField(uint64_t callField,uint32_t numargs)35     uint64_t SetNumArgsWithCallField(uint64_t callField, uint32_t numargs)
36     {
37         return NumArgsBits::Update(callField, numargs);
38     }
39 
SetNativeBit(uint64_t callField,bool isNative)40     uint64_t SetNativeBit(uint64_t callField, bool isNative)
41     {
42         return IsNativeBit::Update(callField, isNative);
43     }
44 
SetAotCodeBit(uint64_t callField,bool isCompiled)45     uint64_t SetAotCodeBit(uint64_t callField, bool isCompiled)
46     {
47         return IsAotCodeBit::Update(callField, isCompiled);
48     }
49 
SetFastBuiltinBit(uint64_t callField,bool isFastBuiltin)50     uint64_t SetFastBuiltinBit(uint64_t callField, bool isFastBuiltin)
51     {
52         return IsFastBuiltinBit::Update(callField, isFastBuiltin);
53     }
54 
HaveThisWithCallField(uint64_t callField)55     bool HaveThisWithCallField(uint64_t callField) const
56     {
57         return HaveThisBit::Decode(callField);
58     }
59 
HaveNewTargetWithCallField(uint64_t callField)60     bool HaveNewTargetWithCallField(uint64_t callField) const
61     {
62         return HaveNewTargetBit::Decode(callField);
63     }
64 
HaveExtraWithCallField(uint64_t callField)65     bool HaveExtraWithCallField(uint64_t callField)
66     {
67         return HaveExtraBit::Decode(callField);
68     }
69 
HaveFuncWithCallField(uint64_t callField)70     bool HaveFuncWithCallField(uint64_t callField) const
71     {
72         return HaveFuncBit::Decode(callField);
73     }
74 
IsNativeWithCallField(uint64_t callField)75     bool IsNativeWithCallField(uint64_t callField) const
76     {
77         return IsNativeBit::Decode(callField);
78     }
79 
IsAotWithCallField(uint64_t callField)80     bool IsAotWithCallField(uint64_t callField) const
81     {
82         return IsAotCodeBit::Decode(callField);
83     }
84 
OnlyHaveThisWithCallField(uint64_t callField)85     bool OnlyHaveThisWithCallField(uint64_t callField) const
86     {
87         return (callField & CALL_TYPE_MASK) == 1;  // 1: the first bit of callFiled is HaveThisBit
88     }
89 
OnlyHaveNewTagetAndThisWithCallField(uint64_t callField)90     bool OnlyHaveNewTagetAndThisWithCallField(uint64_t callField) const
91     {
92         return (callField & CALL_TYPE_MASK) == 0b11;  // the first two bit of callFiled is `This` and `NewTarget`
93     }
94 
GetNumArgsWithCallField(uint64_t callField)95     static uint32_t GetNumArgsWithCallField(uint64_t callField)
96     {
97         return NumArgsBits::Decode(callField);
98     }
99 
SetCallNapi(uint64_t callField,bool isCallNapi)100     static uint64_t SetCallNapi(uint64_t callField, bool isCallNapi)
101     {
102         return IsCallNapiBit::Update(callField, isCallNapi);
103     }
104 
IsCallNapi(uint64_t callField)105     static bool IsCallNapi(uint64_t callField)
106     {
107         return IsCallNapiBit::Decode(callField);
108     }
109 
SetNumArgsWithCallField(uint32_t numargs)110     void SetNumArgsWithCallField(uint32_t numargs)
111     {
112         uint64_t callField = GetCallField();
113         uint64_t newValue = SetNumArgsWithCallField(callField, numargs);
114         SetCallField(newValue);
115     }
116 
SetNativeBit(bool isNative)117     void SetNativeBit(bool isNative)
118     {
119         uint64_t callField = GetCallField();
120         uint64_t newValue = SetNativeBit(callField, isNative);
121         SetCallField(newValue);
122     }
123 
SetAotCodeBit(bool isCompiled)124     void SetAotCodeBit(bool isCompiled)
125     {
126         uint64_t callField = GetCallField();
127         uint64_t newValue = SetAotCodeBit(callField, isCompiled);
128         SetCallField(newValue);
129     }
130 
SetFastBuiltinBit(bool isFastBuiltin)131     void SetFastBuiltinBit(bool isFastBuiltin)
132     {
133         uint64_t callField = GetCallField();
134         uint64_t newValue = SetFastBuiltinBit(callField, isFastBuiltin);
135         SetCallField(newValue);
136     }
137 
HaveThisWithCallField()138     bool HaveThisWithCallField() const
139     {
140         uint64_t callField = GetCallField();
141         return HaveThisWithCallField(callField);
142     }
143 
HaveNewTargetWithCallField()144     bool HaveNewTargetWithCallField() const
145     {
146         uint64_t callField = GetCallField();
147         return HaveNewTargetWithCallField(callField);
148     }
149 
HaveExtraWithCallField()150     bool HaveExtraWithCallField()
151     {
152         uint64_t callField = GetCallField();
153         return HaveExtraWithCallField(callField);
154     }
155 
HaveFuncWithCallField()156     bool HaveFuncWithCallField() const
157     {
158         uint64_t callField = GetCallField();
159         return HaveFuncWithCallField(callField);
160     }
161 
IsNativeWithCallField()162     bool IsNativeWithCallField() const
163     {
164         uint64_t callField = GetCallField();
165         return IsNativeWithCallField(callField);
166     }
167 
IsAotWithCallField()168     bool IsAotWithCallField() const
169     {
170         uint64_t callField = GetCallField();
171         return MethodLiteral::IsAotWithCallField(callField);
172     }
173 
OnlyHaveThisWithCallField()174     bool OnlyHaveThisWithCallField() const
175     {
176         uint64_t callField = GetCallField();
177         return MethodLiteral::OnlyHaveThisWithCallField(callField);
178     }
179 
OnlyHaveNewTagetAndThisWithCallField()180     bool OnlyHaveNewTagetAndThisWithCallField() const
181     {
182         uint64_t callField = GetCallField();
183         return MethodLiteral::OnlyHaveNewTagetAndThisWithCallField(callField);
184     }
185 
GetNumVregsWithCallField(uint64_t callField)186     uint32_t GetNumVregsWithCallField(uint64_t callField) const
187     {
188         return NumVregsBits::Decode(callField);
189     }
190 
GetNumVregsWithCallField()191     uint32_t GetNumVregsWithCallField() const
192     {
193         uint64_t callField = GetCallField();
194         return GetNumVregsWithCallField(callField);
195     }
196 
GetNumArgsWithCallField()197     uint32_t GetNumArgsWithCallField() const
198     {
199         uint64_t callField = GetCallField();
200         return MethodLiteral::GetNumArgsWithCallField(callField);
201     }
202 
GetNumArgs()203     uint32_t GetNumArgs() const
204     {
205         return GetNumArgsWithCallField() + GetNumRevervedArgs();
206     }
207 
GetNumRevervedArgs()208     uint32_t GetNumRevervedArgs() const
209     {
210         return HaveFuncWithCallField() +
211             HaveNewTargetWithCallField() + HaveThisWithCallField();
212     }
213 
GetNumberVRegs()214     uint32_t GetNumberVRegs() const
215     {
216         return GetNumVregsWithCallField() + GetNumArgs();
217     }
218 
GetHotnessCounter()219     inline int16_t GetHotnessCounter() const
220     {
221         uint64_t literalInfo = GetLiteralInfo();
222         return MethodLiteral::GetHotnessCounter(literalInfo);
223     }
224 
SetHotnessCounter(int16_t counter)225     inline NO_THREAD_SANITIZE void SetHotnessCounter(int16_t counter)
226     {
227         uint64_t literalInfo = GetLiteralInfo();
228         uint64_t newValue = MethodLiteral::SetHotnessCounter(literalInfo, counter);
229         SetLiteralInfo(newValue);
230     }
231 
GetMethodId()232     EntityId GetMethodId() const
233     {
234         uint64_t literalInfo = GetLiteralInfo();
235         return MethodLiteral::GetMethodId(literalInfo);
236     }
237 
GetSlotSize()238     uint16_t GetSlotSize() const
239     {
240         uint64_t literalInfo = GetLiteralInfo();
241         return MethodLiteral::GetSlotSize(literalInfo);
242     }
243 
GetBuiltinId(uint64_t literalInfo)244     uint8_t GetBuiltinId(uint64_t literalInfo) const
245     {
246         return BuiltinIdBits::Decode(literalInfo);
247     }
248 
SetBuiltinId(uint64_t literalInfo,uint8_t id)249     uint64_t SetBuiltinId(uint64_t literalInfo, uint8_t id)
250     {
251         return BuiltinIdBits::Update(literalInfo, id);
252     }
253 
SetFunctionKind(uint64_t extraLiteralInfo,FunctionKind kind)254     uint64_t SetFunctionKind(uint64_t extraLiteralInfo, FunctionKind kind)
255     {
256         return FunctionKindBits::Update(extraLiteralInfo, kind);
257     }
258 
GetFunctionKind(uint64_t extraLiteralInfo)259     FunctionKind GetFunctionKind(uint64_t extraLiteralInfo) const
260     {
261         return static_cast<FunctionKind>(FunctionKindBits::Decode(extraLiteralInfo));
262     }
263 
SetDeoptThreshold(uint64_t literalInfo,uint8_t count)264     uint64_t SetDeoptThreshold(uint64_t literalInfo, uint8_t count)
265     {
266         return DeoptCountBits::Update(literalInfo, count);
267     }
268 
GetDeoptThreshold(uint64_t literalInfo)269     uint16_t GetDeoptThreshold(uint64_t literalInfo) const
270     {
271         return DeoptCountBits::Decode(literalInfo);
272     }
273 
SetDeoptType(uint64_t extraLiteralInfo,kungfu::DeoptType type)274     uint64_t SetDeoptType(uint64_t extraLiteralInfo, kungfu::DeoptType type)
275     {
276         return DeoptTypeBits::Update(extraLiteralInfo, type);
277     }
278 
SetDeoptType(kungfu::DeoptType type)279     void SetDeoptType(kungfu::DeoptType type)
280     {
281         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
282         uint64_t newValue = SetDeoptType(extraLiteralInfo, type);
283         SetExtraLiteralInfo(newValue);
284     }
285 
GetDeoptType(uint64_t extraLiteralInfo)286     kungfu::DeoptType GetDeoptType(uint64_t extraLiteralInfo) const
287     {
288         return static_cast<kungfu::DeoptType>(DeoptTypeBits::Decode(extraLiteralInfo));
289     }
290 
GetDeoptType()291     kungfu::DeoptType GetDeoptType() const
292     {
293         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
294         return GetDeoptType(extraLiteralInfo);
295     }
296 
SetFunctionKind(FunctionKind kind)297     void SetFunctionKind(FunctionKind kind)
298     {
299         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
300         uint64_t newValue = SetFunctionKind(extraLiteralInfo, kind);
301         SetExtraLiteralInfo(newValue);
302     }
303 
GetFunctionKind()304     FunctionKind GetFunctionKind() const
305     {
306         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
307         return GetFunctionKind(extraLiteralInfo);
308     }
309 
GetBuiltinId()310     uint8_t GetBuiltinId() const
311     {
312         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
313         return GetBuiltinId(extraLiteralInfo);
314     }
315 
SetCallNapi(bool isCallNapi)316     void SetCallNapi(bool isCallNapi)
317     {
318         uint64_t callField = GetCallField();
319         uint64_t newValue = MethodLiteral::SetCallNapi(callField, isCallNapi);
320         SetCallField(newValue);
321     }
322 
IsCallNapi()323     bool IsCallNapi() const
324     {
325         uint64_t callField = GetCallField();
326         return MethodLiteral::IsCallNapi(callField);
327     }
328 
SetBuiltinId(uint8_t id)329     void SetBuiltinId(uint8_t id)
330     {
331         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
332         uint64_t newValue = SetBuiltinId(extraLiteralInfo, id);
333         SetExtraLiteralInfo(newValue);
334     }
335 
SetDeoptThreshold(uint8_t count)336     void SetDeoptThreshold(uint8_t count)
337     {
338         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
339         uint64_t newValue = SetDeoptThreshold(extraLiteralInfo, count);
340         SetExtraLiteralInfo(newValue);
341     }
342 
GetDeoptThreshold()343     uint16_t GetDeoptThreshold() const
344     {
345         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
346         return GetDeoptThreshold(extraLiteralInfo);
347     }
348 
GetNativePointer()349     const void* GetNativePointer() const
350     {
351         return GetNativePointerOrBytecodeArray();
352     }
353 
SetNativePointer(void * nativePointer)354     void SetNativePointer(void *nativePointer)
355     {
356         SetNativePointerOrBytecodeArray(nativePointer);
357     }
358 
GetBytecodeArray()359     const uint8_t *GetBytecodeArray() const
360     {
361         return reinterpret_cast<const uint8_t *>(GetNativePointerOrBytecodeArray());
362     }
363 
364     // add for AOT
SetCodeEntryAndMarkAOT(uintptr_t codeEntry)365     void SetCodeEntryAndMarkAOT(uintptr_t codeEntry)
366     {
367         SetAotCodeBit(true);
368         SetNativeBit(false);
369         SetCodeEntryOrLiteral(codeEntry);
370     }
371 
Size()372     static constexpr size_t Size()
373     {
374         return sizeof(Method);
375     }
376 
377     const JSPandaFile *PUBLIC_API GetJSPandaFile() const;
378     const panda_file::File *GetPandaFile() const;
379     uint32_t GetCodeSize() const;
380     MethodLiteral *GetMethodLiteral() const;
381 
382     const char *PUBLIC_API GetMethodName() const;
383     const char *PUBLIC_API GetMethodName(const JSPandaFile* file) const;
384     std::string PUBLIC_API ParseFunctionName() const;
385     const CString GetRecordName() const;
386 
387     uint32_t FindCatchBlock(uint32_t pc) const;
388 
389     /* callfield */
390     static constexpr size_t VREGS_ARGS_NUM_BITS = 28; // 28: maximum 268,435,455
391     using HaveThisBit = BitField<bool, 0, 1>;  // offset 0
392     using HaveNewTargetBit = HaveThisBit::NextFlag;  // offset 1
393     using HaveExtraBit = HaveNewTargetBit::NextFlag;  // offset 2
394     using HaveFuncBit = HaveExtraBit::NextFlag;  // offset 3
395     using NumVregsBits = HaveFuncBit::NextField<uint32_t, VREGS_ARGS_NUM_BITS>;  // offset 4-31
396     using NumArgsBits = NumVregsBits::NextField<uint32_t, VREGS_ARGS_NUM_BITS>;  // offset 32-59
397     using IsNativeBit = NumArgsBits::NextFlag;  // offset 60
398     using IsAotCodeBit = IsNativeBit::NextFlag; // offset 61
399     using IsFastBuiltinBit = IsAotCodeBit::NextFlag; // offset 62
400     using IsCallNapiBit = IsFastBuiltinBit::NextFlag; // offset 63
401 
402     /*  ExtraLiteralInfo */
403     static constexpr size_t BUILTINID_NUM_BITS = 8;
404     static constexpr size_t FUNCTION_KIND_NUM_BITS = 4;
405     static constexpr size_t DEOPT_THRESHOLD_BITS = 8;
406     static constexpr size_t DEOPTTYPE_NUM_BITS = 8;
407     using BuiltinIdBits = BitField<uint8_t, 0, BUILTINID_NUM_BITS>; // offset 0-7
408     using FunctionKindBits = BuiltinIdBits::NextField<FunctionKind, FUNCTION_KIND_NUM_BITS>; // offset 8-11
409     using DeoptCountBits = FunctionKindBits::NextField<uint8_t, DEOPT_THRESHOLD_BITS>; // offset 12-19
410     using DeoptTypeBits = DeoptCountBits::NextField<kungfu::DeoptType, DEOPTTYPE_NUM_BITS>; // offset 20-27
411 
412     static constexpr size_t CONSTANT_POOL_OFFSET = TaggedObjectSize();
413     ACCESSORS(ConstantPool, CONSTANT_POOL_OFFSET, PROFILE_TYPE_INFO_OFFSET)
414     ACCESSORS(ProfileTypeInfo, PROFILE_TYPE_INFO_OFFSET, CALL_FIELD_OFFSET)
415     ACCESSORS_PRIMITIVE_FIELD(CallField, uint64_t, CALL_FIELD_OFFSET, NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET)
416     // Native method decides this filed is NativePointer or BytecodeArray pointer.
417     ACCESSORS_NATIVE_FIELD(
418         NativePointerOrBytecodeArray, void, NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET, CODE_ENTRY_OFFSET)
419     ACCESSORS_PRIMITIVE_FIELD(CodeEntryOrLiteral, uintptr_t, CODE_ENTRY_OFFSET, LITERAL_INFO_OFFSET)
420     // hotness counter is encoded in a js method field, the first uint16_t in a uint64_t.
421     ACCESSORS_PRIMITIVE_FIELD(LiteralInfo, uint64_t, LITERAL_INFO_OFFSET, EXTRA_LITERAL_INFO_OFFSET)
422     ACCESSORS_PRIMITIVE_FIELD(ExtraLiteralInfo, uint64_t, EXTRA_LITERAL_INFO_OFFSET, LAST_OFFSET)
423     DEFINE_ALIGN_SIZE(LAST_OFFSET);
424 
425     DECL_VISIT_OBJECT(CONSTANT_POOL_OFFSET, CALL_FIELD_OFFSET);
426 
427     DECL_DUMP()
428 };
429 }  // namespace panda::ecmascript
430 
431 #endif  // ECMASCRIPT_JS_METHOD_H
432