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