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