• 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_METHOD_H
17 #define ECMASCRIPT_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 extraLiteralInfo,bool isCallNapi)100     static uint64_t SetCallNapi(uint64_t extraLiteralInfo, bool isCallNapi)
101     {
102         return IsCallNapiBit::Update(extraLiteralInfo, isCallNapi);
103     }
104 
IsCallNapi(uint64_t extraLiteralInfo)105     static bool IsCallNapi(uint64_t extraLiteralInfo)
106     {
107         return IsCallNapiBit::Decode(extraLiteralInfo);
108     }
109 
SetIsFastCall(uint64_t callField,bool isFastCall)110     static uint64_t SetIsFastCall(uint64_t callField, bool isFastCall)
111     {
112         return IsFastCallBit::Update(callField, isFastCall);
113     }
114 
IsFastCall(uint64_t callField)115     static bool IsFastCall(uint64_t callField)
116     {
117         return IsFastCallBit::Decode(callField);
118     }
119 
SetNumArgsWithCallField(uint32_t numargs)120     void SetNumArgsWithCallField(uint32_t numargs)
121     {
122         uint64_t callField = GetCallField();
123         uint64_t newValue = SetNumArgsWithCallField(callField, numargs);
124         SetCallField(newValue);
125     }
126 
SetNativeBit(bool isNative)127     void SetNativeBit(bool isNative)
128     {
129         uint64_t callField = GetCallField();
130         uint64_t newValue = SetNativeBit(callField, isNative);
131         SetCallField(newValue);
132     }
133 
SetAotCodeBit(bool isCompiled)134     void SetAotCodeBit(bool isCompiled)
135     {
136         uint64_t callField = GetCallField();
137         uint64_t newValue = SetAotCodeBit(callField, isCompiled);
138         SetCallField(newValue);
139     }
140 
SetFastBuiltinBit(bool isFastBuiltin)141     void SetFastBuiltinBit(bool isFastBuiltin)
142     {
143         uint64_t callField = GetCallField();
144         uint64_t newValue = SetFastBuiltinBit(callField, isFastBuiltin);
145         SetCallField(newValue);
146     }
147 
HaveThisWithCallField()148     bool HaveThisWithCallField() const
149     {
150         uint64_t callField = GetCallField();
151         return HaveThisWithCallField(callField);
152     }
153 
HaveNewTargetWithCallField()154     bool HaveNewTargetWithCallField() const
155     {
156         uint64_t callField = GetCallField();
157         return HaveNewTargetWithCallField(callField);
158     }
159 
HaveExtraWithCallField()160     bool HaveExtraWithCallField()
161     {
162         uint64_t callField = GetCallField();
163         return HaveExtraWithCallField(callField);
164     }
165 
HaveFuncWithCallField()166     bool HaveFuncWithCallField() const
167     {
168         uint64_t callField = GetCallField();
169         return HaveFuncWithCallField(callField);
170     }
171 
IsNativeWithCallField()172     bool IsNativeWithCallField() const
173     {
174         uint64_t callField = GetCallField();
175         return IsNativeWithCallField(callField);
176     }
177 
IsAotWithCallField()178     bool IsAotWithCallField() const
179     {
180         uint64_t callField = GetCallField();
181         return MethodLiteral::IsAotWithCallField(callField);
182     }
183 
OnlyHaveThisWithCallField()184     bool OnlyHaveThisWithCallField() const
185     {
186         uint64_t callField = GetCallField();
187         return MethodLiteral::OnlyHaveThisWithCallField(callField);
188     }
189 
OnlyHaveNewTagetAndThisWithCallField()190     bool OnlyHaveNewTagetAndThisWithCallField() const
191     {
192         uint64_t callField = GetCallField();
193         return MethodLiteral::OnlyHaveNewTagetAndThisWithCallField(callField);
194     }
195 
GetNumVregsWithCallField(uint64_t callField)196     uint32_t GetNumVregsWithCallField(uint64_t callField) const
197     {
198         return NumVregsBits::Decode(callField);
199     }
200 
GetNumVregsWithCallField()201     uint32_t GetNumVregsWithCallField() const
202     {
203         uint64_t callField = GetCallField();
204         return GetNumVregsWithCallField(callField);
205     }
206 
GetNumArgsWithCallField()207     uint32_t GetNumArgsWithCallField() const
208     {
209         uint64_t callField = GetCallField();
210         return MethodLiteral::GetNumArgsWithCallField(callField);
211     }
212 
GetNumArgs()213     uint32_t GetNumArgs() const
214     {
215         return GetNumArgsWithCallField() + GetNumRevervedArgs();
216     }
217 
GetNumRevervedArgs()218     uint32_t GetNumRevervedArgs() const
219     {
220         return HaveFuncWithCallField() +
221             HaveNewTargetWithCallField() + HaveThisWithCallField();
222     }
223 
GetNumberVRegs()224     uint32_t GetNumberVRegs() const
225     {
226         return GetNumVregsWithCallField() + GetNumArgs();
227     }
228 
GetHotnessCounter()229     inline int16_t GetHotnessCounter() const
230     {
231         uint64_t literalInfo = GetLiteralInfo();
232         return MethodLiteral::GetHotnessCounter(literalInfo);
233     }
234 
SetHotnessCounter(int16_t counter)235     inline NO_THREAD_SANITIZE void SetHotnessCounter(int16_t counter)
236     {
237         uint64_t literalInfo = GetLiteralInfo();
238         uint64_t newValue = MethodLiteral::SetHotnessCounter(literalInfo, counter);
239         SetLiteralInfo(newValue);
240     }
241 
GetMethodId()242     EntityId GetMethodId() const
243     {
244         uint64_t literalInfo = GetLiteralInfo();
245         return MethodLiteral::GetMethodId(literalInfo);
246     }
247 
GetSlotSize()248     uint16_t GetSlotSize() const
249     {
250         uint64_t literalInfo = GetLiteralInfo();
251         return MethodLiteral::GetSlotSize(literalInfo);
252     }
253 
GetBuiltinId(uint64_t literalInfo)254     uint8_t GetBuiltinId(uint64_t literalInfo) const
255     {
256         return BuiltinIdBits::Decode(literalInfo);
257     }
258 
SetBuiltinId(uint64_t literalInfo,uint8_t id)259     uint64_t SetBuiltinId(uint64_t literalInfo, uint8_t id)
260     {
261         return BuiltinIdBits::Update(literalInfo, id);
262     }
263 
SetFunctionKind(uint64_t extraLiteralInfo,FunctionKind kind)264     uint64_t SetFunctionKind(uint64_t extraLiteralInfo, FunctionKind kind)
265     {
266         return FunctionKindBits::Update(extraLiteralInfo, kind);
267     }
268 
GetFunctionKind(uint64_t extraLiteralInfo)269     FunctionKind GetFunctionKind(uint64_t extraLiteralInfo) const
270     {
271         return static_cast<FunctionKind>(FunctionKindBits::Decode(extraLiteralInfo));
272     }
273 
SetDeoptThreshold(uint64_t literalInfo,uint8_t count)274     uint64_t SetDeoptThreshold(uint64_t literalInfo, uint8_t count)
275     {
276         return DeoptCountBits::Update(literalInfo, count);
277     }
278 
GetDeoptThreshold(uint64_t literalInfo)279     uint16_t GetDeoptThreshold(uint64_t literalInfo) const
280     {
281         return DeoptCountBits::Decode(literalInfo);
282     }
283 
SetDeoptType(uint64_t extraLiteralInfo,kungfu::DeoptType type)284     uint64_t SetDeoptType(uint64_t extraLiteralInfo, kungfu::DeoptType type)
285     {
286         return DeoptTypeBits::Update(extraLiteralInfo, type);
287     }
288 
SetDeoptType(kungfu::DeoptType type)289     void SetDeoptType(kungfu::DeoptType type)
290     {
291         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
292         uint64_t newValue = SetDeoptType(extraLiteralInfo, type);
293         SetExtraLiteralInfo(newValue);
294     }
295 
GetDeoptType(uint64_t extraLiteralInfo)296     kungfu::DeoptType GetDeoptType(uint64_t extraLiteralInfo) const
297     {
298         return static_cast<kungfu::DeoptType>(DeoptTypeBits::Decode(extraLiteralInfo));
299     }
300 
GetDeoptType()301     kungfu::DeoptType GetDeoptType() const
302     {
303         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
304         return GetDeoptType(extraLiteralInfo);
305     }
306 
SetFunctionKind(FunctionKind kind)307     void SetFunctionKind(FunctionKind kind)
308     {
309         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
310         uint64_t newValue = SetFunctionKind(extraLiteralInfo, kind);
311         SetExtraLiteralInfo(newValue);
312     }
313 
GetFunctionKind()314     FunctionKind GetFunctionKind() const
315     {
316         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
317         return GetFunctionKind(extraLiteralInfo);
318     }
319 
GetBuiltinId()320     uint8_t GetBuiltinId() const
321     {
322         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
323         return GetBuiltinId(extraLiteralInfo);
324     }
325 
SetIsFastCall(bool isFastCall)326     void SetIsFastCall(bool isFastCall)
327     {
328         uint64_t callFiled = GetCallField();
329         uint64_t newValue = SetIsFastCall(callFiled, isFastCall);
330         SetCallField(newValue);
331     }
332 
IsFastCall()333     bool IsFastCall() const
334     {
335         uint64_t callFiled = GetCallField();
336         return IsFastCall(callFiled);
337     }
338 
SetCallNapi(bool isCallNapi)339     void SetCallNapi(bool isCallNapi)
340     {
341         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
342         uint64_t newValue = SetCallNapi(extraLiteralInfo, isCallNapi);
343         SetExtraLiteralInfo(newValue);
344     }
345 
IsCallNapi()346     bool IsCallNapi() const
347     {
348         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
349         return IsCallNapi(extraLiteralInfo);
350     }
351 
SetBuiltinId(uint8_t id)352     void SetBuiltinId(uint8_t id)
353     {
354         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
355         uint64_t newValue = SetBuiltinId(extraLiteralInfo, id);
356         SetExtraLiteralInfo(newValue);
357     }
358 
SetDeoptThreshold(uint8_t count)359     void SetDeoptThreshold(uint8_t count)
360     {
361         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
362         uint64_t newValue = SetDeoptThreshold(extraLiteralInfo, count);
363         SetExtraLiteralInfo(newValue);
364     }
365 
GetDeoptThreshold()366     uint16_t GetDeoptThreshold() const
367     {
368         uint64_t extraLiteralInfo = GetExtraLiteralInfo();
369         return GetDeoptThreshold(extraLiteralInfo);
370     }
371 
GetNativePointer()372     const void* GetNativePointer() const
373     {
374         return GetNativePointerOrBytecodeArray();
375     }
376 
SetNativePointer(void * nativePointer)377     void SetNativePointer(void *nativePointer)
378     {
379         SetNativePointerOrBytecodeArray(nativePointer);
380     }
381 
GetBytecodeArray()382     const uint8_t *GetBytecodeArray() const
383     {
384         return reinterpret_cast<const uint8_t *>(GetNativePointerOrBytecodeArray());
385     }
386 
387     // add for AOT
SetCodeEntryAndMarkAOT(uintptr_t codeEntry)388     void SetCodeEntryAndMarkAOT(uintptr_t codeEntry)
389     {
390         SetAotCodeBit(true);
391         SetNativeBit(false);
392         SetCodeEntryOrLiteral(codeEntry);
393     }
394 
ClearAOTFlags()395     void ClearAOTFlags()
396     {
397         SetAotCodeBit(false);
398         SetIsFastCall(false);
399         SetDeoptType(kungfu::DeoptType::NOTCHECK);
400         SetCodeEntryOrLiteral(reinterpret_cast<uintptr_t>(nullptr));
401     }
402 
Size()403     static constexpr size_t Size()
404     {
405         return sizeof(Method);
406     }
407 
408     const JSPandaFile *PUBLIC_API GetJSPandaFile() const;
409     uint32_t GetCodeSize() const;
410     MethodLiteral *GetMethodLiteral() const;
411 
412     const char *PUBLIC_API GetMethodName() const;
413     const char *PUBLIC_API GetMethodName(const JSPandaFile *file) const;
414     std::string PUBLIC_API ParseFunctionName() const;
415     const CString GetRecordName() const;
416 
417     uint32_t FindCatchBlock(uint32_t pc) const;
418 
419     /* callfield */
420     static constexpr size_t VREGS_ARGS_NUM_BITS = 28; // 28: maximum 268,435,455
421     static constexpr uint64_t AOT_FASTCALL_BITS = 0x5; // 0x5LU: aot and fastcall bit field
422     using HaveThisBit = BitField<bool, 0, 1>;  // offset 0
423     using HaveNewTargetBit = HaveThisBit::NextFlag;  // offset 1
424     using HaveExtraBit = HaveNewTargetBit::NextFlag;  // offset 2
425     using HaveFuncBit = HaveExtraBit::NextFlag;  // offset 3
426     using NumVregsBits = HaveFuncBit::NextField<uint32_t, VREGS_ARGS_NUM_BITS>;  // offset 4-31
427     using NumArgsBits = NumVregsBits::NextField<uint32_t, VREGS_ARGS_NUM_BITS>;  // offset 32-59
428     using IsNativeBit = NumArgsBits::NextFlag;  // offset 60
429     using IsAotCodeBit = IsNativeBit::NextFlag; // offset 61
430     using IsFastBuiltinBit = IsAotCodeBit::NextFlag; // offset 62
431     using IsFastCallBit = IsFastBuiltinBit::NextFlag; // offset 63
432 
433     /*  ExtraLiteralInfo */
434     static constexpr size_t BUILTINID_NUM_BITS = 8;
435     static constexpr size_t FUNCTION_KIND_NUM_BITS = 4;
436     static constexpr size_t DEOPT_THRESHOLD_BITS = 8;
437     static constexpr size_t DEOPTTYPE_NUM_BITS = 8;
438     using BuiltinIdBits = BitField<uint8_t, 0, BUILTINID_NUM_BITS>; // offset 0-7
439     using FunctionKindBits = BuiltinIdBits::NextField<FunctionKind, FUNCTION_KIND_NUM_BITS>; // offset 8-11
440     using DeoptCountBits = FunctionKindBits::NextField<uint8_t, DEOPT_THRESHOLD_BITS>; // offset 12-19
441     using DeoptTypeBits = DeoptCountBits::NextField<kungfu::DeoptType, DEOPTTYPE_NUM_BITS>; // offset 20-27
442     using IsCallNapiBit = DeoptTypeBits::NextFlag; // offset 28
443 
444     static constexpr size_t CONSTANT_POOL_OFFSET = TaggedObjectSize();
445     ACCESSORS(ConstantPool, CONSTANT_POOL_OFFSET, PROFILE_TYPE_INFO_OFFSET)
446     ACCESSORS(ProfileTypeInfo, PROFILE_TYPE_INFO_OFFSET, CALL_FIELD_OFFSET)
447     ACCESSORS_PRIMITIVE_FIELD(CallField, uint64_t, CALL_FIELD_OFFSET, NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET)
448     // Native method decides this filed is NativePointer or BytecodeArray pointer.
449     ACCESSORS_NATIVE_FIELD(
450         NativePointerOrBytecodeArray, void, NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET, CODE_ENTRY_OFFSET)
451     ACCESSORS_PRIMITIVE_FIELD(CodeEntryOrLiteral, uintptr_t, CODE_ENTRY_OFFSET, LITERAL_INFO_OFFSET)
452     // hotness counter is encoded in a js method field, the first uint16_t in a uint64_t.
453     ACCESSORS_PRIMITIVE_FIELD(LiteralInfo, uint64_t, LITERAL_INFO_OFFSET, EXTRA_LITERAL_INFO_OFFSET)
454     ACCESSORS_PRIMITIVE_FIELD(ExtraLiteralInfo, uint64_t, EXTRA_LITERAL_INFO_OFFSET, LAST_OFFSET)
455     DEFINE_ALIGN_SIZE(LAST_OFFSET);
456 
457     DECL_VISIT_OBJECT(CONSTANT_POOL_OFFSET, CALL_FIELD_OFFSET);
458 
459     DECL_DUMP()
460 
461 private:
462     static JSHandle<Method> Create(JSThread *thread, const JSPandaFile *jsPandaFile, MethodLiteral *methodLiteral);
463 
464     friend class ObjectFactory;
465 };
466 }  // namespace panda::ecmascript
467 
468 #endif  // ECMASCRIPT_METHOD_H
469