• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #include "ecmascript/jit/jit_profiler.h"
16 
17 
18 #include "ecmascript/compiler/jit_compilation_env.h"
19 #include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
20 #include "ecmascript/enum_conversion.h"
21 #include "ecmascript/interpreter/interpreter-inl.h"
22 
23 namespace panda::ecmascript {
24 using namespace pgo;
JITProfiler(EcmaVM * vm)25 JITProfiler::JITProfiler(EcmaVM *vm) : vm_(vm)
26 {
27 }
28 
ProfileBytecode(JSThread * thread,const JSHandle<ProfileTypeInfo> & profileTypeInfo,ProfileTypeInfo * rawProfileTypeInfo,EntityId methodId,ApEntityId abcId,const uint8_t * pcStart,uint32_t codeSize,const panda_file::File::Header * header,bool useRawProfileTypeInfo)29 void JITProfiler::ProfileBytecode(JSThread *thread, const JSHandle<ProfileTypeInfo> &profileTypeInfo,
30                                   ProfileTypeInfo *rawProfileTypeInfo,
31                                   EntityId methodId, ApEntityId abcId, const uint8_t *pcStart, uint32_t codeSize,
32                                   [[maybe_unused]]const panda_file::File::Header *header, bool useRawProfileTypeInfo)
33 {
34     Clear();
35     if (useRawProfileTypeInfo) {
36         profileTypeInfo_ = rawProfileTypeInfo;
37     }
38     abcId_ = abcId;
39     methodId_ = methodId;
40     BytecodeInstruction bcIns(pcStart);
41     auto bcInsLast = bcIns.JumpTo(codeSize);
42 
43     while (bcIns.GetAddress() != bcInsLast.GetAddress()) {
44         auto opcode = bcIns.GetOpcode();
45         auto bcOffset = bcIns.GetAddress() - pcStart;
46         auto pc = bcIns.GetAddress();
47         // Assuming that the assembly interpreter has executed all bytecode.
48         SetBcOffsetBool(bcOffset);
49         switch (opcode) {
50             case EcmaOpcode::LDTHISBYNAME_IMM8_ID16:
51             case EcmaOpcode::LDOBJBYNAME_IMM8_ID16: {
52                 Jit::JitLockHolder lock(thread);
53                 if (!useRawProfileTypeInfo) {
54                     profileTypeInfo_ = *profileTypeInfo;
55                 }
56                 uint8_t slotId = READ_INST_8_0();
57                 CHECK_SLOTID_BREAK(slotId);
58                 ConvertICByName(bcOffset, slotId, BCType::LOAD);
59                 break;
60             }
61             case EcmaOpcode::LDTHISBYNAME_IMM16_ID16:
62             case EcmaOpcode::LDOBJBYNAME_IMM16_ID16: {
63                 Jit::JitLockHolder lock(thread);
64                 if (!useRawProfileTypeInfo) {
65                     profileTypeInfo_ = *profileTypeInfo;
66                 }
67                 uint16_t slotId = READ_INST_16_0();
68                 ConvertICByName(bcOffset, slotId, BCType::LOAD);
69                 break;
70             }
71             case EcmaOpcode::LDOBJBYVALUE_IMM8_V8:
72             case EcmaOpcode::LDTHISBYVALUE_IMM8: {
73                 Jit::JitLockHolder lock(thread);
74                 if (!useRawProfileTypeInfo) {
75                     profileTypeInfo_ = *profileTypeInfo;
76                 }
77                 uint8_t slotId = READ_INST_8_0();
78                 CHECK_SLOTID_BREAK(slotId);
79                 ConvertICByValue(bcOffset, slotId, BCType::LOAD);
80                 break;
81             }
82             case EcmaOpcode::LDOBJBYVALUE_IMM16_V8:
83             case EcmaOpcode::LDTHISBYVALUE_IMM16: {
84                 Jit::JitLockHolder lock(thread);
85                 if (!useRawProfileTypeInfo) {
86                     profileTypeInfo_ = *profileTypeInfo;
87                 }
88                 uint16_t slotId = READ_INST_16_0();
89                 ConvertICByValue(bcOffset, slotId, BCType::LOAD);
90                 break;
91             }
92             case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
93             case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
94             case EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8:
95             case EcmaOpcode::STPRIVATEPROPERTY_IMM8_IMM16_IMM16_V8: {
96                 Jit::JitLockHolder lock(thread);
97                 if (!useRawProfileTypeInfo) {
98                     profileTypeInfo_ = *profileTypeInfo;
99                 }
100                 uint8_t slotId = READ_INST_8_0();
101                 CHECK_SLOTID_BREAK(slotId);
102                 ConvertICByName(bcOffset, slotId, BCType::STORE);
103                 break;
104             }
105             case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
106             case EcmaOpcode::STTHISBYNAME_IMM16_ID16: {
107                 Jit::JitLockHolder lock(thread);
108                 if (!useRawProfileTypeInfo) {
109                     profileTypeInfo_ = *profileTypeInfo;
110                 }
111                 uint16_t slotId = READ_INST_16_0();
112                 ConvertICByName(bcOffset, slotId, BCType::STORE);
113                 break;
114             }
115             case EcmaOpcode::STOBJBYVALUE_IMM8_V8_V8:
116             case EcmaOpcode::STOWNBYINDEX_IMM8_V8_IMM16:
117             case EcmaOpcode::STTHISBYVALUE_IMM8_V8: {
118                 Jit::JitLockHolder lock(thread);
119                 if (!useRawProfileTypeInfo) {
120                     profileTypeInfo_ = *profileTypeInfo;
121                 }
122                 uint8_t slotId = READ_INST_8_0();
123                 CHECK_SLOTID_BREAK(slotId);
124                 ConvertICByValue(bcOffset, slotId, BCType::STORE);
125                 break;
126             }
127             case EcmaOpcode::STOBJBYVALUE_IMM16_V8_V8:
128             case EcmaOpcode::STOWNBYINDEX_IMM16_V8_IMM16:
129             case EcmaOpcode::STTHISBYVALUE_IMM16_V8: {
130                 Jit::JitLockHolder lock(thread);
131                 if (!useRawProfileTypeInfo) {
132                     profileTypeInfo_ = *profileTypeInfo;
133                 }
134                 uint16_t slotId = READ_INST_16_0();
135                 ConvertICByValue(bcOffset, slotId, BCType::STORE);
136                 break;
137             }
138             // Op
139             case EcmaOpcode::ADD2_IMM8_V8:
140             case EcmaOpcode::SUB2_IMM8_V8:
141             case EcmaOpcode::MUL2_IMM8_V8:
142             case EcmaOpcode::DIV2_IMM8_V8:
143             case EcmaOpcode::MOD2_IMM8_V8:
144             case EcmaOpcode::SHL2_IMM8_V8:
145             case EcmaOpcode::SHR2_IMM8_V8:
146             case EcmaOpcode::AND2_IMM8_V8:
147             case EcmaOpcode::OR2_IMM8_V8:
148             case EcmaOpcode::XOR2_IMM8_V8:
149             case EcmaOpcode::ASHR2_IMM8_V8:
150             case EcmaOpcode::NEG_IMM8:
151             case EcmaOpcode::NOT_IMM8:
152             case EcmaOpcode::INC_IMM8:
153             case EcmaOpcode::DEC_IMM8:
154             case EcmaOpcode::EQ_IMM8_V8:
155             case EcmaOpcode::NOTEQ_IMM8_V8:
156             case EcmaOpcode::LESS_IMM8_V8:
157             case EcmaOpcode::LESSEQ_IMM8_V8:
158             case EcmaOpcode::GREATER_IMM8_V8:
159             case EcmaOpcode::GREATEREQ_IMM8_V8: {
160                 Jit::JitLockHolder lock(thread);
161                 if (!useRawProfileTypeInfo) {
162                     profileTypeInfo_ = *profileTypeInfo;
163                 }
164                 uint8_t slotId = READ_INST_8_0();
165                 CHECK_SLOTID_BREAK(slotId);
166                 ConvertOpType(slotId, bcOffset);
167                 UpdateBcOffsetBool(bcOffset, slotId);
168                 break;
169             }
170             case EcmaOpcode::EXP_IMM8_V8:
171             case EcmaOpcode::STRICTNOTEQ_IMM8_V8:
172             case EcmaOpcode::STRICTEQ_IMM8_V8:
173             case EcmaOpcode::TONUMERIC_IMM8: {
174                 Jit::JitLockHolder lock(thread);
175                 if (!useRawProfileTypeInfo) {
176                     profileTypeInfo_ = *profileTypeInfo;
177                 }
178                 uint8_t slotId = READ_INST_8_0();
179                 CHECK_SLOTID_BREAK(slotId);
180                 ConvertOpType(slotId, bcOffset);
181                 break;
182             }
183             // Call
184             case EcmaOpcode::CALLARG0_IMM8:
185             case EcmaOpcode::CALLARG1_IMM8_V8:
186             case EcmaOpcode::CALLARGS2_IMM8_V8_V8:
187             case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8:
188             case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8:
189             case EcmaOpcode::CALLTHIS0_IMM8_V8:
190             case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
191             case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
192             case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
193             case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: {
194                 Jit::JitLockHolder lock(thread);
195                 if (!useRawProfileTypeInfo) {
196                     profileTypeInfo_ = *profileTypeInfo;
197                 }
198                 uint8_t slotId = READ_INST_8_0();
199                 CHECK_SLOTID_BREAK(slotId);
200                 ConvertCall(slotId, bcOffset);
201                 UpdateBcOffsetBool(bcOffset, slotId);
202                 break;
203             }
204             case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8: {
205                 Jit::JitLockHolder lock(thread);
206                 if (!useRawProfileTypeInfo) {
207                     profileTypeInfo_ = *profileTypeInfo;
208                 }
209                 uint8_t slotId = READ_INST_8_1();
210                 CHECK_SLOTID_BREAK(slotId);
211                 ConvertCall(slotId, bcOffset);
212                 break;
213             }
214             case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8:
215             case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: {
216                 // no ic slot
217                 break;
218             }
219             case EcmaOpcode::NEWOBJRANGE_IMM8_IMM8_V8: {
220                 Jit::JitLockHolder lock(thread);
221                 if (!useRawProfileTypeInfo) {
222                     profileTypeInfo_ = *profileTypeInfo;
223                 }
224                 uint8_t slotId = READ_INST_8_0();
225                 CHECK_SLOTID_BREAK(slotId);
226                 ConvertNewObjRange(slotId, bcOffset);
227                 break;
228             }
229             case EcmaOpcode::NEWOBJRANGE_IMM16_IMM8_V8: {
230                 Jit::JitLockHolder lock(thread);
231                 if (!useRawProfileTypeInfo) {
232                     profileTypeInfo_ = *profileTypeInfo;
233                 }
234                 uint16_t slotId = READ_INST_16_0();
235                 ConvertNewObjRange(slotId, bcOffset);
236                 break;
237             }
238             case EcmaOpcode::WIDE_NEWOBJRANGE_PREF_IMM16_V8: {
239                 break;
240             }
241             // Create object
242             case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: {
243                 uint8_t slotId = READ_INST_8_0();
244                 CHECK_SLOTID_BREAK(slotId);
245                 (void) slotId;
246                 break;
247             }
248             case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: {
249                 uint16_t slotId = READ_INST_16_0();
250                 (void) slotId;
251                 break;
252             }
253             case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8: {
254                 uint8_t slotId = READ_INST_8_0();
255                 CHECK_SLOTID_BREAK(slotId);
256                 break;
257             }
258             case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8: {
259                 uint16_t slotId = READ_INST_16_0();
260                 (void) slotId;
261                 break;
262             }
263             case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16:
264             case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
265             case EcmaOpcode::CREATEEMPTYARRAY_IMM8: {
266                 Jit::JitLockHolder lock(thread);
267                 if (!useRawProfileTypeInfo) {
268                     profileTypeInfo_ = *profileTypeInfo;
269                 }
270                 auto traceId =
271                     static_cast<int32_t>(reinterpret_cast<uintptr_t>(pc) - reinterpret_cast<uintptr_t>(header));
272                 uint8_t slotId = READ_INST_8_0();
273                 CHECK_SLOTID_BREAK(slotId);
274                 ConvertCreateObject(slotId, bcOffset, traceId);
275                 UpdateBcOffsetBool(bcOffset, slotId);
276                 break;
277             }
278             case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16:
279             case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16:
280             case EcmaOpcode::CREATEEMPTYARRAY_IMM16: {
281                 Jit::JitLockHolder lock(thread);
282                 if (!useRawProfileTypeInfo) {
283                     profileTypeInfo_ = *profileTypeInfo;
284                 }
285                 auto traceId =
286                     static_cast<int32_t>(reinterpret_cast<uintptr_t>(pc) - reinterpret_cast<uintptr_t>(header));
287                 uint16_t slotId = READ_INST_16_0();
288                 ConvertCreateObject(slotId, bcOffset, traceId);
289                 UpdateBcOffsetBool(bcOffset, slotId);
290                 break;
291             }
292             case EcmaOpcode::GETITERATOR_IMM8: {
293                 Jit::JitLockHolder lock(thread);
294                 if (!useRawProfileTypeInfo) {
295                     profileTypeInfo_ = *profileTypeInfo;
296                 }
297                 uint8_t slotId = READ_INST_8_0();
298                 CHECK_SLOTID_BREAK(slotId);
299                 ConvertGetIterator(slotId, bcOffset);
300                 break;
301             }
302             case EcmaOpcode::GETITERATOR_IMM16: {
303                 Jit::JitLockHolder lock(thread);
304                 if (!useRawProfileTypeInfo) {
305                     profileTypeInfo_ = *profileTypeInfo;
306                 }
307                 uint16_t slotId = READ_INST_16_0();
308                 ConvertGetIterator(slotId, bcOffset);
309                 break;
310             }
311             // Others
312             case EcmaOpcode::INSTANCEOF_IMM8_V8: {
313                 Jit::JitLockHolder lock(thread);
314                 if (!useRawProfileTypeInfo) {
315                     profileTypeInfo_ = *profileTypeInfo;
316                 }
317                 uint8_t slotId = READ_INST_8_0();
318                 CHECK_SLOTID_BREAK(slotId);
319                 ConvertInstanceof(bcOffset, slotId);
320                 break;
321             }
322             case EcmaOpcode::DEFINEGETTERSETTERBYVALUE_V8_V8_V8_V8:
323             default:
324                 break;
325         }
326         bcIns = bcIns.GetNext();
327     }
328 }
329 
330 // PGOSampleType
ConvertOpType(uint32_t slotId,long bcOffset)331 void JITProfiler::ConvertOpType(uint32_t slotId, long bcOffset)
332 {
333     JSTaggedValue slotValue = profileTypeInfo_->Get(slotId);
334     if (slotValue.IsInt()) {
335         auto type = slotValue.GetInt();
336         UpdatePGOType(bcOffset, chunk_->New<PGOSampleType>(type));
337     }
338 }
339 
ConvertCall(uint32_t slotId,long bcOffset)340 void JITProfiler::ConvertCall(uint32_t slotId, long bcOffset)
341 {
342     JSTaggedValue slotValue = profileTypeInfo_->Get(slotId);
343     ProfileType::Kind kind;
344     int calleeMethodId = 0;
345     ApEntityId calleeAbcId = 0;
346     if (slotValue.IsInt()) {
347         calleeMethodId = slotValue.GetInt();
348         if (calleeMethodId == 0) {
349             return;
350         }
351         calleeAbcId = abcId_;
352         ASSERT(calleeMethodId <= 0);
353         kind = ProfileType::Kind::BuiltinFunctionId;
354     }  else if (slotValue.IsJSFunction()) {
355         JSFunction *callee = JSFunction::Cast(slotValue);
356         Method *calleeMethod = Method::Cast(callee->GetMethod());
357         calleeMethodId = static_cast<int>(calleeMethod->GetMethodId().GetOffset());
358         calleeAbcId = PGOProfiler::GetMethodAbcId(callee);
359         static_cast<JitCompilationEnv *>(compilationEnv_)
360             ->UpdateFuncSlotIdMap(calleeMethodId, methodId_.GetOffset(), slotId);
361         kind = ProfileType::Kind::MethodId;
362     } else {
363         return;
364     }
365     PGOSampleType* type = chunk_->New<PGOSampleType>(ProfileType(abcId_, std::abs(calleeMethodId), kind));
366     UpdatePGOType(bcOffset, type);
367 }
368 
ConvertNewObjRange(uint32_t slotId,long bcOffset)369 void JITProfiler::ConvertNewObjRange(uint32_t slotId, long bcOffset)
370 {
371     JSTaggedValue slotValue = profileTypeInfo_->Get(slotId);
372     int ctorMethodId = 0;
373     JSHClass* hclass = nullptr;
374     if (slotValue.IsInt()) {
375         ctorMethodId = slotValue.GetInt();
376         // JIT cannot optimize this scenario because it doesn't know the hclass
377         if (ctorMethodId > 0) {
378             return;
379         }
380     } else if (slotValue.IsJSFunction()) {
381         JSFunction *callee = JSFunction::Cast(slotValue);
382         Method *calleeMethod = Method::Cast(callee->GetMethod());
383         ctorMethodId = static_cast<int>(calleeMethod->GetMethodId().GetOffset());
384         JSTaggedValue protoOrHClass = callee->GetProtoOrHClass();
385         if (protoOrHClass.IsJSHClass()) {
386             hclass = JSHClass::Cast(protoOrHClass.GetTaggedObject());
387         } else {
388             return;
389         }
390     } else {
391         return;
392     }
393     if (ctorMethodId > 0) {
394         ptManager_->RecordAndGetHclassIndexForJIT(hclass);
395         auto pt = ProfileType(abcId_, std::abs(ctorMethodId), ProfileType::Kind::JITClassId, true);
396         PGODefineOpType* type = chunk_->New<PGODefineOpType>(pt, hclass);
397         UpdatePGOType(bcOffset, type);
398     } else {
399         auto kind = ProfileType::Kind::BuiltinFunctionId;
400         auto type = chunk_->New<PGOSampleType>(ProfileType(abcId_, std::abs(ctorMethodId), kind));
401         UpdatePGOType(bcOffset, type);
402     }
403 }
404 
ConvertGetIterator(uint32_t slotId,long bcOffset)405 void JITProfiler::ConvertGetIterator(uint32_t slotId, long bcOffset)
406 {
407     if (mainThread_->GetEnableLazyBuiltins()) {
408         return;
409     }
410     JSTaggedValue value = profileTypeInfo_->Get(slotId);
411     if (!value.IsInt()) {
412         return;
413     }
414     int iterKind = value.GetInt();
415     ASSERT(iterKind <= 0);
416     ProfileType::Kind pgoKind = ProfileType::Kind::BuiltinFunctionId;
417     auto type = chunk_->New<PGOSampleType>(ProfileType(abcId_, std::abs(iterKind), pgoKind));
418     UpdatePGOType(bcOffset, type);
419 }
420 
ConvertCreateObject(uint32_t slotId,long bcOffset,int32_t traceId)421 void JITProfiler::ConvertCreateObject(uint32_t slotId, long bcOffset, [[maybe_unused]]int32_t traceId)
422 {
423     JSTaggedValue slotValue = profileTypeInfo_->Get(slotId);
424     if (!slotValue.IsHeapObject()) {
425         return;
426     }
427     if (slotValue.IsWeak()) {
428         auto object = slotValue.GetWeakReferentUnChecked();
429         if (object->GetClass()->IsHClass()) {
430             auto newHClass = JSHClass::Cast(object);
431             PGODefineOpType* objDefType = chunk_->New<PGODefineOpType>(ProfileType::CreateJITType(), newHClass);
432             ptManager_->RecordAndGetHclassIndexForJIT(newHClass);
433             UpdatePGOType(bcOffset, objDefType);
434         }
435     } else if (slotValue.IsTrackInfoObject()) {
436         TrackInfo *trackInfo = TrackInfo::Cast(slotValue.GetTaggedObject());
437         auto hclass = JSHClass::Cast(trackInfo->GetCachedHClass().GetTaggedObject());
438         PGODefineOpType* objDefType = chunk_->New<PGODefineOpType>(ProfileType::CreateJITType(), hclass);
439         ptManager_->RecordAndGetHclassIndexForJIT(hclass);
440         auto elementsKind = trackInfo->GetElementsKind();
441         objDefType->SetElementsKind(elementsKind);
442         objDefType->SetElementsLength(trackInfo->GetArrayLength());
443         objDefType->SetSpaceFlag(trackInfo->GetSpaceFlag());
444         UpdatePGOType(bcOffset, objDefType);
445     }
446 }
447 
ConvertICByName(int32_t bcOffset,uint32_t slotId,BCType type)448 void JITProfiler::ConvertICByName(int32_t bcOffset, uint32_t slotId, BCType type)
449 {
450     ProfileTypeAccessorLockScope accessorLockScope(vm_->GetJSThreadNoCheck());
451     JSTaggedValue firstValue = profileTypeInfo_->Get(slotId);
452     if (!firstValue.IsHeapObject()) {
453         JSTaggedValue secondValue = profileTypeInfo_->Get(slotId + 1);
454         if (firstValue.IsHole() && secondValue.IsString()) {
455             // Mega state
456             AddObjectInfoWithMega(bcOffset);
457         }
458         return;
459     }
460     if (firstValue.IsWeak()) {
461         TaggedObject *object = firstValue.GetWeakReferentUnChecked();
462         if (object->GetClass()->IsHClass()) {
463             JSTaggedValue secondValue = profileTypeInfo_->Get(slotId + 1);
464             JSHClass *hclass = JSHClass::Cast(object);
465             ConvertICByNameWithHandler(abcId_, bcOffset, hclass, secondValue, type, slotId + 1);
466         }
467         return;
468     }
469     ConvertICByNameWithPoly(abcId_, bcOffset, firstValue, type, slotId);
470 }
471 
ConvertICByNameWithHandler(ApEntityId abcId,int32_t bcOffset,JSHClass * hclass,JSTaggedValue secondValue,BCType type,uint32_t slotId)472 void JITProfiler::ConvertICByNameWithHandler(ApEntityId abcId, int32_t bcOffset,
473                                              JSHClass *hclass,
474                                              JSTaggedValue secondValue, BCType type, uint32_t slotId)
475 {
476     if (type == BCType::LOAD) {
477         HandleLoadType(abcId, bcOffset, hclass, secondValue, slotId);
478         // LoadGlobal
479         return;
480     }
481     HandleOtherTypes(abcId, bcOffset, hclass, secondValue, slotId);
482 }
483 
HandleLoadType(ApEntityId & abcId,int32_t & bcOffset,JSHClass * hclass,JSTaggedValue & secondValue,uint32_t slotId)484 void JITProfiler::HandleLoadType(ApEntityId &abcId, int32_t &bcOffset,
485                                  JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId)
486 {
487     if (secondValue.IsInt()) {
488         HandleLoadTypeInt(abcId, bcOffset, hclass, secondValue);
489     } else if (secondValue.IsPrototypeHandler()) {
490         HandleLoadTypePrototypeHandler(abcId, bcOffset, hclass, secondValue, slotId);
491     }
492 }
493 
HandleLoadTypeInt(ApEntityId & abcId,int32_t & bcOffset,JSHClass * hclass,JSTaggedValue & secondValue)494 void JITProfiler::HandleLoadTypeInt(ApEntityId &abcId, int32_t &bcOffset,
495                                     JSHClass *hclass, JSTaggedValue &secondValue)
496 {
497     auto handlerInfo = static_cast<uint32_t>(secondValue.GetInt());
498     if (HandlerBase::IsNonExist(handlerInfo)) {
499         return;
500     }
501     if (AddBuiltinsInfoByNameInInstance(abcId, bcOffset, hclass)) {
502         return;
503     }
504     if (HandlerBase::IsField(handlerInfo) || HandlerBase::IsAccessor(handlerInfo)) {
505         AddObjectInfo(abcId, bcOffset, hclass, hclass, hclass);
506     }
507 }
508 
HandleLoadTypePrototypeHandler(ApEntityId & abcId,int32_t & bcOffset,JSHClass * hclass,JSTaggedValue & secondValue,uint32_t slotId)509 void JITProfiler::HandleLoadTypePrototypeHandler(ApEntityId &abcId, int32_t &bcOffset,
510                                                  JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId)
511 {
512     auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject());
513     auto cellValue = prototypeHandler->GetProtoCell();
514     if (cellValue.IsUndefined()) {
515         return;
516     }
517     ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
518     if (cell->GetHasChanged()) {
519         return;
520     }
521     JSTaggedValue handlerInfoVal = prototypeHandler->GetHandlerInfo();
522     auto accessorMethodId = prototypeHandler->GetAccessorMethodId();
523     auto accessor = prototypeHandler->GetAccessorJSFunction();
524     if (!handlerInfoVal.IsInt()) {
525         return;
526     }
527     auto handlerInfo = static_cast<uint32_t>(handlerInfoVal.GetInt());
528     if (HandlerBase::IsNonExist(handlerInfo)) {
529         return;
530     }
531     auto holder = prototypeHandler->GetHolder();
532     auto holderHClass = holder.GetTaggedObject()->GetClass();
533     if (accessor.IsJSFunction()) {
534         auto accessorFunction = JSFunction::Cast(accessor);
535         auto methodId = Method::Cast(accessorFunction->GetMethod())->GetMethodId().GetOffset();
536         ASSERT(accessorMethodId == methodId);
537         accessorMethodId = methodId;
538         static_cast<JitCompilationEnv *>(compilationEnv_)
539             ->UpdateFuncSlotIdMap(accessorMethodId, methodId_.GetOffset(), slotId);
540     }
541     if (AddBuiltinsInfoByNameInProt(abcId, bcOffset, hclass, holderHClass)) {
542         return ;
543     }
544     AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId);
545 }
546 
HandleOtherTypes(ApEntityId & abcId,int32_t & bcOffset,JSHClass * hclass,JSTaggedValue & secondValue,uint32_t slotId)547 void JITProfiler::HandleOtherTypes(ApEntityId &abcId, int32_t &bcOffset,
548                                    JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId)
549 {
550     if (secondValue.IsInt()) {
551         AddObjectInfo(abcId, bcOffset, hclass, hclass, hclass);
552     } else if (secondValue.IsTransitionHandler()) {
553         HandleTransitionHandler(abcId, bcOffset, hclass, secondValue);
554     } else if (secondValue.IsTransWithProtoHandler()) {
555         HandleTransWithProtoHandler(abcId, bcOffset, hclass, secondValue);
556     } else if (secondValue.IsPrototypeHandler()) {
557         HandleOtherTypesPrototypeHandler(abcId, bcOffset, hclass, secondValue, slotId);
558     } else if (secondValue.IsPropertyBox()) {
559         // StoreGlobal
560     } else if (secondValue.IsStoreAOTHandler()) {
561         HandleStoreAOTHandler(abcId, bcOffset, hclass, secondValue);
562     }
563 }
564 
HandleTransitionHandler(ApEntityId & abcId,int32_t & bcOffset,JSHClass * hclass,JSTaggedValue & secondValue)565 void JITProfiler::HandleTransitionHandler(ApEntityId &abcId, int32_t &bcOffset,
566                                           JSHClass *hclass, JSTaggedValue &secondValue)
567 {
568     auto transitionHandler = TransitionHandler::Cast(secondValue.GetTaggedObject());
569     auto transitionHClassVal = transitionHandler->GetTransitionHClass();
570     if (transitionHClassVal.IsJSHClass()) {
571         auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
572         AddObjectInfo(abcId, bcOffset, hclass, hclass, transitionHClass);
573     }
574 }
575 
HandleTransWithProtoHandler(ApEntityId & abcId,int32_t & bcOffset,JSHClass * hclass,JSTaggedValue & secondValue)576 void JITProfiler::HandleTransWithProtoHandler(ApEntityId &abcId, int32_t &bcOffset,
577                                               JSHClass *hclass, JSTaggedValue &secondValue)
578 {
579     auto transWithProtoHandler = TransWithProtoHandler::Cast(secondValue.GetTaggedObject());
580     auto cellValue = transWithProtoHandler->GetProtoCell();
581     ASSERT(cellValue.IsProtoChangeMarker());
582     ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
583     if (cell->GetHasChanged()) {
584         return;
585     }
586     auto transitionHClassVal = transWithProtoHandler->GetTransitionHClass();
587     if (transitionHClassVal.IsJSHClass()) {
588         auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
589         AddObjectInfo(abcId, bcOffset, hclass, hclass, transitionHClass);
590     }
591 }
592 
HandleOtherTypesPrototypeHandler(ApEntityId & abcId,int32_t & bcOffset,JSHClass * hclass,JSTaggedValue & secondValue,uint32_t slotId)593 void JITProfiler::HandleOtherTypesPrototypeHandler(ApEntityId &abcId, int32_t &bcOffset,
594                                                    JSHClass *hclass, JSTaggedValue &secondValue, uint32_t slotId)
595 {
596     auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject());
597     auto cellValue = prototypeHandler->GetProtoCell();
598     if (cellValue.IsUndefined()) {
599         return;
600     }
601     ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
602     if (cell->GetHasChanged()) {
603         return;
604     }
605     auto holder = prototypeHandler->GetHolder();
606     auto holderHClass = holder.GetTaggedObject()->GetClass();
607     auto accessorMethodId = prototypeHandler->GetAccessorMethodId();
608     auto accessor = prototypeHandler->GetAccessorJSFunction();
609     if (accessor.IsJSFunction()) {
610         auto accessorFunction = JSFunction::Cast(accessor);
611         auto methodId = Method::Cast(accessorFunction->GetMethod())->GetMethodId().GetOffset();
612         ASSERT(accessorMethodId == methodId);
613         accessorMethodId = methodId;
614         static_cast<JitCompilationEnv *>(compilationEnv_)
615             ->UpdateFuncSlotIdMap(accessorMethodId, methodId_.GetOffset(), slotId);
616     }
617     AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId);
618 }
619 
HandleStoreAOTHandler(ApEntityId & abcId,int32_t & bcOffset,JSHClass * hclass,JSTaggedValue & secondValue)620 void JITProfiler::HandleStoreAOTHandler(ApEntityId &abcId, int32_t &bcOffset,
621                                         JSHClass *hclass, JSTaggedValue &secondValue)
622 {
623     StoreAOTHandler *storeAOTHandler = StoreAOTHandler::Cast(secondValue.GetTaggedObject());
624     auto cellValue = storeAOTHandler->GetProtoCell();
625     ASSERT(cellValue.IsProtoChangeMarker());
626     ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
627     if (cell->GetHasChanged()) {
628         return;
629     }
630     auto holder = storeAOTHandler->GetHolder();
631     auto holderHClass = holder.GetTaggedObject()->GetClass();
632     AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass);
633 }
634 
ConvertICByNameWithPoly(ApEntityId abcId,int32_t bcOffset,JSTaggedValue cacheValue,BCType type,uint32_t slotId)635 void JITProfiler::ConvertICByNameWithPoly(ApEntityId abcId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type,
636                                           uint32_t slotId)
637 {
638     if (cacheValue.IsWeak()) {
639         return;
640     }
641     ASSERT(cacheValue.IsTaggedArray());
642     auto array = TaggedArray::Cast(cacheValue);
643     uint32_t length = array->GetLength();
644     for (uint32_t i = 0; i < length; i += 2) { // 2 means one ic, two slot
645         auto result = array->Get(i);
646         auto handler = array->Get(i + 1);
647         if (!result.IsHeapObject() || !result.IsWeak()) {
648             continue;
649         }
650         TaggedObject *object = result.GetWeakReferentUnChecked();
651         if (!object->GetClass()->IsHClass()) {
652             continue;
653         }
654         JSHClass *hclass = JSHClass::Cast(object);
655         ConvertICByNameWithHandler(abcId, bcOffset, hclass, handler, type, slotId);
656     }
657 }
658 
ConvertICByValue(int32_t bcOffset,uint32_t slotId,BCType type)659 void JITProfiler::ConvertICByValue(int32_t bcOffset, uint32_t slotId, BCType type)
660 {
661     ProfileTypeAccessorLockScope accessorLockScope(vm_->GetJSThreadNoCheck());
662     JSTaggedValue firstValue = profileTypeInfo_->Get(slotId);
663     if (!firstValue.IsHeapObject()) {
664         if (firstValue.IsHole()) {
665             // Mega state
666             AddObjectInfoWithMega(bcOffset);
667         }
668         return;
669     }
670     if (firstValue.IsWeak()) {
671         TaggedObject *object = firstValue.GetWeakReferentUnChecked();
672         if (object->GetClass()->IsHClass()) {
673             JSTaggedValue secondValue = profileTypeInfo_->Get(slotId + 1);
674             JSHClass *hclass = JSHClass::Cast(object);
675             ConvertICByValueWithHandler(abcId_, bcOffset, hclass, secondValue, type);
676         }
677         return;
678     }
679     // Check key
680     if ((firstValue.IsString() || firstValue.IsSymbol())) {
681         JSTaggedValue secondValue = profileTypeInfo_->Get(slotId + 1);
682         ConvertICByValueWithPoly(abcId_, bcOffset, secondValue, type);
683         return;
684     }
685     // Check without key
686     ConvertICByValueWithPoly(abcId_, bcOffset, firstValue, type);
687 }
688 
ConvertICByValueWithHandler(ApEntityId abcId,int32_t bcOffset,JSHClass * hclass,JSTaggedValue secondValue,BCType type)689 void JITProfiler::ConvertICByValueWithHandler(ApEntityId abcId, int32_t bcOffset,
690                                               JSHClass *hclass, JSTaggedValue secondValue,
691                                               BCType type)
692 {
693     if (type == BCType::LOAD) {
694         if (secondValue.IsInt()) {
695             auto handlerInfo = static_cast<uint32_t>(secondValue.GetInt());
696             if (HandlerBase::IsNormalElement(handlerInfo) || HandlerBase::IsStringElement(handlerInfo)) {
697                 if (HandlerBase::NeedSkipInPGODump(handlerInfo)) {
698                     return;
699                 }
700                 AddBuiltinsInfo(abcId, bcOffset, hclass, hclass);
701                 return;
702             }
703             if (HandlerBase::IsTypedArrayElement(handlerInfo)) {
704                 OnHeapMode onHeap =  HandlerBase::IsOnHeap(handlerInfo) ? OnHeapMode::ON_HEAP : OnHeapMode::NOT_ON_HEAP;
705                 AddBuiltinsInfo(abcId, bcOffset, hclass, hclass, onHeap);
706                 return;
707             }
708             AddObjectInfo(abcId, bcOffset, hclass, hclass, hclass);
709         }
710         return;
711     }
712     HandleStoreType(abcId, bcOffset, hclass, secondValue);
713 }
714 
HandleStoreType(ApEntityId & abcId,int32_t & bcOffset,JSHClass * hclass,JSTaggedValue & secondValue)715 void JITProfiler::HandleStoreType(ApEntityId &abcId, int32_t &bcOffset,
716                                   JSHClass *hclass, JSTaggedValue &secondValue)
717 {
718     if (secondValue.IsInt()) {
719         auto handlerInfo = static_cast<uint32_t>(secondValue.GetInt());
720         if (HandlerBase::IsNormalElement(handlerInfo) || HandlerBase::IsStringElement(handlerInfo)) {
721             AddBuiltinsInfo(abcId, bcOffset, hclass, hclass,
722                             OnHeapMode::NONE, HandlerBase::IsStoreOutOfBounds(handlerInfo));
723             return;
724         }
725         if (HandlerBase::IsTypedArrayElement(handlerInfo)) {
726             OnHeapMode onHeap = HandlerBase::IsOnHeap(handlerInfo) ? OnHeapMode::ON_HEAP : OnHeapMode::NOT_ON_HEAP;
727             AddBuiltinsInfo(abcId,  bcOffset, hclass, hclass, onHeap,
728                             HandlerBase::IsStoreOutOfBounds(handlerInfo));
729             return;
730         }
731         AddObjectInfo(abcId, bcOffset, hclass, hclass, hclass);
732     } else if (secondValue.IsTransitionHandler()) {
733         HandleTransition(abcId, bcOffset, hclass, secondValue);
734     } else if (secondValue.IsTransWithProtoHandler()) {
735         HandleTransWithProto(abcId, bcOffset, hclass, secondValue);
736     } else if (secondValue.IsPrototypeHandler()) {
737         HandlePrototypeHandler(abcId, bcOffset, hclass, secondValue);
738     }
739 }
740 
HandleTransition(ApEntityId & abcId,int32_t & bcOffset,JSHClass * hclass,JSTaggedValue & secondValue)741 void JITProfiler::HandleTransition(ApEntityId &abcId, int32_t &bcOffset,
742                                    JSHClass *hclass, JSTaggedValue &secondValue)
743 {
744     auto transitionHandler = TransitionHandler::Cast(secondValue.GetTaggedObject());
745     auto transitionHClassVal = transitionHandler->GetTransitionHClass();
746     if (!transitionHClassVal.IsJSHClass()) {
747         return ;
748     }
749     auto handlerInfoValue = transitionHandler->GetHandlerInfo();
750     auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
751     if (handlerInfoValue.IsInt()) {
752         auto handlerInfo = static_cast<uint32_t>(handlerInfoValue.GetInt());
753         if (HandlerBase::IsElement(handlerInfo)) {
754             AddBuiltinsInfo(abcId, bcOffset, hclass, transitionHClass,
755                             OnHeapMode::NONE, HandlerBase::IsStoreOutOfBounds(handlerInfo));
756             return;
757         }
758     }
759     AddObjectInfo(abcId, bcOffset, hclass, hclass, transitionHClass);
760 }
761 
HandleTransWithProto(ApEntityId & abcId,int32_t & bcOffset,JSHClass * hclass,JSTaggedValue & secondValue)762 void JITProfiler::HandleTransWithProto(ApEntityId &abcId, int32_t &bcOffset,
763                                        JSHClass *hclass, JSTaggedValue &secondValue)
764 {
765     auto transWithProtoHandler = TransWithProtoHandler::Cast(secondValue.GetTaggedObject());
766     auto transitionHClassVal = transWithProtoHandler->GetTransitionHClass();
767     if (!transitionHClassVal.IsJSHClass()) {
768         return ;
769     }
770     auto handlerInfoValue = transWithProtoHandler->GetHandlerInfo();
771     auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
772     if (handlerInfoValue.IsInt()) {
773         auto handlerInfo = static_cast<uint32_t>(handlerInfoValue.GetInt());
774         if (HandlerBase::IsElement(handlerInfo)) {
775             AddBuiltinsInfo(abcId, bcOffset, hclass, transitionHClass,
776                             OnHeapMode::NONE, HandlerBase::IsStoreOutOfBounds(handlerInfo));
777             return;
778         }
779     }
780     AddObjectInfo(abcId, bcOffset, hclass, hclass, transitionHClass);
781 }
782 
HandlePrototypeHandler(ApEntityId & abcId,int32_t & bcOffset,JSHClass * hclass,JSTaggedValue & secondValue)783 void JITProfiler::HandlePrototypeHandler(ApEntityId &abcId, int32_t &bcOffset,
784                                          JSHClass *hclass, JSTaggedValue &secondValue)
785 {
786     PrototypeHandler *prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject());
787     auto cellValue = prototypeHandler->GetProtoCell();
788     if (!cellValue.IsProtoChangeMarker()) {
789         return;
790     }
791     ASSERT(cellValue.IsProtoChangeMarker());
792     ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
793     if (cell->GetHasChanged()) {
794         return;
795     }
796     JSTaggedValue handlerInfoValue = prototypeHandler->GetHandlerInfo();
797     if (handlerInfoValue.IsInt()) {
798         auto handlerInfo = static_cast<uint32_t>(handlerInfoValue.GetInt());
799         if (HandlerBase::IsElement(handlerInfo)) {
800             AddBuiltinsInfo(abcId, bcOffset, hclass, hclass,
801                             OnHeapMode::NONE, HandlerBase::IsStoreOutOfBounds(handlerInfo));
802             return;
803         }
804     }
805     auto holder = prototypeHandler->GetHolder();
806     auto holderHClass = holder.GetTaggedObject()->GetClass();
807     AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass);
808 }
809 
ConvertICByValueWithPoly(ApEntityId abcId,int32_t bcOffset,JSTaggedValue cacheValue,BCType type)810 void JITProfiler::ConvertICByValueWithPoly(ApEntityId abcId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type)
811 {
812     if (cacheValue.IsWeak()) {
813         return;
814     }
815     // Check whether the cacheValue is TaggedArray
816     if (!cacheValue.IsTaggedArray()) {
817         return;
818     }
819     auto array = TaggedArray::Cast(cacheValue);
820     uint32_t length = array->GetLength();
821     for (uint32_t i = 0; i < length; i += 2) { // 2 means one ic, two slot
822         auto result = array->Get(i);
823         auto handler = array->Get(i + 1);
824         if (!result.IsHeapObject() || !result.IsWeak()) {
825             continue;
826         }
827         TaggedObject *object = result.GetWeakReferentUnChecked();
828         if (!object->GetClass()->IsHClass()) {
829             continue;
830         }
831         JSHClass *hclass = JSHClass::Cast(object);
832         ConvertICByValueWithHandler(abcId, bcOffset, hclass, handler, type);
833     }
834 }
835 
ConvertInstanceof(int32_t bcOffset,uint32_t slotId)836 void JITProfiler::ConvertInstanceof(int32_t bcOffset, uint32_t slotId)
837 {
838     JSTaggedValue firstValue = profileTypeInfo_->Get(slotId);
839     if (!firstValue.IsHeapObject()) {
840         if (firstValue.IsHole()) {
841             // Mega state
842             AddObjectInfoWithMega(bcOffset);
843         }
844         return;
845     }
846     if (firstValue.IsWeak()) {
847         TaggedObject *object = firstValue.GetWeakReferentUnChecked();
848         if (object->GetClass()->IsHClass()) {
849             JSHClass *hclass = JSHClass::Cast(object);
850             // Since pgo does not support symbol, we choose to return if hclass having @@hasInstance
851             JSHandle<GlobalEnv> env = vm_->GetGlobalEnv();
852             JSTaggedValue key = env->GetHasInstanceSymbol().GetTaggedValue();
853             JSHClass *functionPrototypeHC = JSObject::Cast(env->GetFunctionPrototype().GetTaggedValue())->GetClass();
854             JSTaggedValue foundHClass = TryFindKeyInPrototypeChain(object, hclass, key);
855             if (!foundHClass.IsUndefined() && JSHClass::Cast(foundHClass.GetTaggedObject()) != functionPrototypeHC) {
856                 return;
857             }
858             AddObjectInfo(abcId_, bcOffset, hclass, hclass, hclass);
859         }
860         return;
861     }
862     // Poly Not Consider now
863     return;
864 }
865 
TryFindKeyInPrototypeChain(TaggedObject * currObj,JSHClass * currHC,JSTaggedValue key)866 JSTaggedValue JITProfiler::TryFindKeyInPrototypeChain(TaggedObject *currObj, JSHClass *currHC, JSTaggedValue key)
867 {
868     // This is a temporary solution for Instanceof Only!
869     // Do NOT use this function for other purpose.
870     if (currHC->IsDictionaryMode()) {
871         return JSTaggedValue(currHC);
872     }
873     while (!JSTaggedValue(currHC).IsUndefinedOrNull()) {
874         if (LIKELY(!currHC->IsDictionaryMode())) {
875             int entry = JSHClass::FindPropertyEntry(mainThread_, currHC, key);
876             if (entry != -1) {
877                 return JSTaggedValue(currHC);
878             }
879         } else {
880             TaggedArray *array = TaggedArray::Cast(JSObject::Cast(currObj)->GetProperties().GetTaggedObject());
881             ASSERT(array->IsDictionaryMode());
882             NameDictionary *dict = NameDictionary::Cast(array);
883             int entry = dict->FindEntry(key);
884             if (entry != -1) {
885                 return JSTaggedValue(currHC);
886             }
887         }
888         auto proto = currHC->GetProto();
889         if (!proto.IsHeapObject()) {
890             return JSTaggedValue::Undefined();
891         }
892         currObj = proto.GetTaggedObject();
893         if (JSTaggedValue(currObj).IsUndefinedOrNull()) {
894             break;
895         }
896         currHC = currObj->GetClass();
897     }
898     return JSTaggedValue::Undefined();
899 }
900 
AddObjectInfoWithMega(int32_t bcOffset)901 void JITProfiler::AddObjectInfoWithMega(int32_t bcOffset)
902 {
903     auto megaType = ProfileType::CreateMegaType();
904     PGOObjectInfo info(megaType, megaType, megaType, megaType, megaType, megaType, PGOSampleType());
905     AddObjectInfoImplement(bcOffset, info);
906 }
907 
AddObjectInfoImplement(int32_t bcOffset,const PGOObjectInfo & info)908 void JITProfiler::AddObjectInfoImplement(int32_t bcOffset, const PGOObjectInfo &info)
909 {
910     PGORWOpType *cur = nullptr;
911     if (bcOffsetPGORwTypeMap_.find(bcOffset) == bcOffsetPGORwTypeMap_.end()) {
912         cur = chunk_->New<PGORWOpType>();
913         bcOffsetPGORwTypeMap_[bcOffset] = cur;
914     } else {
915         cur = const_cast<PGORWOpType*>(bcOffsetPGORwTypeMap_.at(bcOffset));
916     }
917     if (cur != nullptr) {
918         cur->AddObjectInfo(info);
919     }
920 }
921 
AddObjectInfo(ApEntityId abcId,int32_t bcOffset,JSHClass * receiver,JSHClass * hold,JSHClass * holdTra,uint32_t accessorMethodId)922 bool JITProfiler::AddObjectInfo(ApEntityId abcId, int32_t bcOffset,
923                                 JSHClass *receiver, JSHClass *hold, JSHClass *holdTra, uint32_t accessorMethodId)
924 {
925     PGOSampleType accessor = PGOSampleType::CreateProfileType(abcId, accessorMethodId, ProfileType::Kind::MethodId);
926     // case: obj = Object.create(null) => LowerProtoChangeMarkerCheck Crash
927     if (receiver->GetPrototype().IsNull()) {
928         return false;
929     }
930     return AddTranstionObjectInfo(bcOffset, receiver, hold, holdTra, accessor);
931 }
932 
AddTranstionObjectInfo(int32_t bcOffset,JSHClass * receiver,JSHClass * hold,JSHClass * holdTra,PGOSampleType accessorMethod)933 bool JITProfiler::AddTranstionObjectInfo(
934     int32_t bcOffset, JSHClass *receiver, JSHClass *hold, JSHClass *holdTra, PGOSampleType accessorMethod)
935 {
936     ptManager_->RecordAndGetHclassIndexForJIT(receiver);
937     ptManager_->RecordAndGetHclassIndexForJIT(hold);
938     ptManager_->RecordAndGetHclassIndexForJIT(holdTra);
939     PGOObjectInfo info(ProfileType::CreateJITType(), receiver, hold, holdTra, accessorMethod);
940     AddObjectInfoImplement(bcOffset, info);
941     return true;
942 }
943 
AddBuiltinsInfo(ApEntityId abcId,int32_t bcOffset,JSHClass * receiver,JSHClass * transitionHClass,OnHeapMode onHeap,bool everOutOfBounds)944 void JITProfiler::AddBuiltinsInfo(ApEntityId abcId, int32_t bcOffset, JSHClass *receiver,
945     JSHClass *transitionHClass, OnHeapMode onHeap, bool everOutOfBounds)
946 {
947     if (receiver->IsJSArray()) {
948         auto type = receiver->GetObjectType();
949         auto elementsKind = receiver->GetElementsKind();
950         auto transitionElementsKind = transitionHClass->GetElementsKind();
951         auto profileType = ProfileType::CreateBuiltinsArray(abcId, type, elementsKind, transitionElementsKind,
952                                                             everOutOfBounds);
953         PGOObjectInfo info(profileType);
954         AddObjectInfoImplement(bcOffset, info);
955     } else if (receiver->IsTypedArray()) {
956         JSType jsType = receiver->GetObjectType();
957         auto profileType = ProfileType::CreateBuiltinsTypedArray(abcId, jsType, onHeap, everOutOfBounds);
958         PGOObjectInfo info(profileType);
959         AddObjectInfoImplement(bcOffset, info);
960     } else {
961         auto type = receiver->GetObjectType();
962         PGOObjectInfo info(ProfileType::CreateBuiltins(abcId, type));
963         AddObjectInfoImplement(bcOffset, info);
964     }
965 }
966 
AddBuiltinsGlobalInfo(ApEntityId abcId,int32_t bcOffset,GlobalIndex globalsId)967 void JITProfiler::AddBuiltinsGlobalInfo(ApEntityId abcId, int32_t bcOffset, GlobalIndex globalsId)
968 {
969     PGOObjectInfo info(ProfileType::CreateGlobals(abcId, globalsId));
970     AddObjectInfoImplement(bcOffset, info);
971 }
972 
AddBuiltinsInfoByNameInInstance(ApEntityId abcId,int32_t bcOffset,JSHClass * receiver)973 bool JITProfiler::AddBuiltinsInfoByNameInInstance(ApEntityId abcId, int32_t bcOffset, JSHClass *receiver)
974 {
975     auto type = receiver->GetObjectType();
976     const auto &ctorEntries = mainThread_->GetCtorHclassEntries();
977     auto entry = ctorEntries.find(receiver);
978     if (entry != ctorEntries.end()) {
979         AddBuiltinsGlobalInfo(abcId, bcOffset, entry->second);
980         return true;
981     }
982 
983     auto builtinsId = ToBuiltinsTypeId(type);
984     if (!builtinsId.has_value()) {
985         return false;
986     }
987     JSHClass *exceptRecvHClass = nullptr;
988     if (builtinsId == BuiltinTypeId::ARRAY) {
989         bool receiverIsPrototype = receiver->IsPrototype();
990         exceptRecvHClass = mainThread_->GetArrayInstanceHClass(receiver->GetElementsKind(), receiverIsPrototype);
991     } else if (builtinsId == BuiltinTypeId::STRING) {
992         exceptRecvHClass = receiver;
993     } else {
994         exceptRecvHClass = mainThread_->GetBuiltinInstanceHClass(builtinsId.value());
995     }
996 
997     if (exceptRecvHClass != receiver) {
998         // When JSType cannot uniquely identify builtins object, it is necessary to
999         // query the receiver on the global constants.
1000         if (builtinsId == BuiltinTypeId::OBJECT) {
1001             exceptRecvHClass = JSHClass::Cast(
1002                 mainThread_->GlobalConstants()->GetIteratorResultClass().GetTaggedObject());
1003             if (exceptRecvHClass == receiver) {
1004                 GlobalIndex globalsId;
1005                 globalsId.UpdateGlobalConstId(static_cast<size_t>(ConstantIndex::ITERATOR_RESULT_CLASS));
1006                 AddBuiltinsGlobalInfo(abcId, bcOffset, globalsId);
1007                 return true;
1008             }
1009             return false;
1010         }
1011         return true;
1012     }
1013     AddBuiltinsInfo(abcId, bcOffset, receiver, receiver);
1014     return true;
1015 }
1016 
AddBuiltinsInfoByNameInProt(ApEntityId abcId,int32_t bcOffset,JSHClass * receiver,JSHClass * hold)1017 bool JITProfiler::AddBuiltinsInfoByNameInProt(ApEntityId abcId, int32_t bcOffset, JSHClass *receiver, JSHClass *hold)
1018 {
1019     auto type = receiver->GetObjectType();
1020     auto builtinsId = ToBuiltinsTypeId(type);
1021     if (!builtinsId.has_value()) {
1022         return false;
1023     }
1024     JSHClass *exceptRecvHClass = nullptr;
1025     if (builtinsId == BuiltinTypeId::ARRAY) {
1026         bool receiverIsPrototype = receiver->IsPrototype();
1027         exceptRecvHClass = mainThread_->GetArrayInstanceHClass(receiver->GetElementsKind(), receiverIsPrototype);
1028     } else if (builtinsId == BuiltinTypeId::STRING) {
1029         exceptRecvHClass = receiver;
1030     } else {
1031         exceptRecvHClass = mainThread_->GetBuiltinInstanceHClass(builtinsId.value());
1032     }
1033 
1034     auto exceptHoldHClass = mainThread_->GetBuiltinPrototypeHClass(builtinsId.value());
1035     auto exceptPrototypeOfPrototypeHClass =
1036         mainThread_->GetBuiltinPrototypeOfPrototypeHClass(builtinsId.value());
1037     // iterator needs to find two layers of prototype
1038     if (builtinsId == BuiltinTypeId::ARRAY_ITERATOR) {
1039         if ((exceptRecvHClass != receiver) ||
1040             (exceptHoldHClass != hold && exceptPrototypeOfPrototypeHClass != hold)) {
1041             return true;
1042         }
1043     } else if (IsTypedArrayType(builtinsId.value())) {
1044         auto exceptRecvHClassOnHeap = mainThread_->GetBuiltinExtraHClass(builtinsId.value());
1045         ASSERT_PRINT(exceptRecvHClassOnHeap == nullptr || exceptRecvHClassOnHeap->IsOnHeapFromBitField(),
1046                      "must be on heap");
1047         if (JITProfiler::IsJSHClassNotEqual(receiver, hold, exceptRecvHClass, exceptRecvHClassOnHeap, exceptHoldHClass,
1048                                             exceptPrototypeOfPrototypeHClass)) {
1049             return true;
1050         }
1051     } else if (exceptRecvHClass != receiver || exceptHoldHClass != hold) {
1052         if (builtinsId == BuiltinTypeId::OBJECT) {
1053             return false;
1054         } else {
1055             return true;
1056         }
1057     }
1058     AddBuiltinsInfo(abcId, bcOffset, receiver, receiver);
1059     return true;
1060 }
1061 
IsJSHClassNotEqual(JSHClass * receiver,JSHClass * hold,JSHClass * exceptRecvHClass,JSHClass * exceptRecvHClassOnHeap,JSHClass * exceptHoldHClass,JSHClass * exceptPrototypeOfPrototypeHClass)1062 bool JITProfiler::IsJSHClassNotEqual(JSHClass *receiver, JSHClass *hold, JSHClass *exceptRecvHClass,
1063                                      JSHClass *exceptRecvHClassOnHeap, JSHClass *exceptHoldHClass,
1064                                      JSHClass *exceptPrototypeOfPrototypeHClass)
1065 {
1066     //exceptRecvHClass = IHC, exceptRecvHClassOnHeap = IHC OnHeap
1067     //exceptHoldHClass = PHC, exceptPrototypeOfPrototypeHClass = HClass of X.prototype.prototype
1068     return ((exceptRecvHClass != receiver && exceptRecvHClassOnHeap != receiver) ||
1069             (exceptHoldHClass != hold && exceptPrototypeOfPrototypeHClass != hold));
1070 }
1071 
IsIncompleteProfileTypeInfo()1072 bool JITProfiler::IsIncompleteProfileTypeInfo()
1073 {
1074     if (profileTypeInfo_ == nullptr) {
1075         return true;
1076     }
1077     // We may receive an incomplete profile typeinfo. During the execution of a larger function, when the upper part of
1078     // the function is executed, profiltypeinfo has not yet been created. When profiltypeinfo is created and Jit is
1079     // triggered, the first half of profiltypeinfo becomes empty.
1080     return profileTypeInfo_->Get(0).IsUndefined();
1081 }
1082 
SlotValueIsUndefined(uint32_t slotId)1083 bool JITProfiler::SlotValueIsUndefined(uint32_t slotId)
1084 {
1085     return profileTypeInfo_->Get(slotId).IsUndefined();
1086 }
1087 
UpdateBcOffsetBool(uint32_t offset,uint32_t slotId)1088 void JITProfiler::UpdateBcOffsetBool(uint32_t offset, uint32_t slotId)
1089 {
1090     if (IsIncompleteProfileTypeInfo()) {
1091         return;
1092     }
1093     SetBcOffsetBool(offset, SlotValueIsUndefined(slotId));
1094 }
1095 
UpdateBcOffsetBoolWithNearSlotId(uint32_t offset,uint32_t slotId)1096 void JITProfiler::UpdateBcOffsetBoolWithNearSlotId(uint32_t offset, uint32_t slotId)
1097 {
1098     if (IsIncompleteProfileTypeInfo()) {
1099         return;
1100     }
1101     bool isInsufficientPGO = SlotValueIsUndefined(slotId) && SlotValueIsUndefined(slotId + 1);
1102     SetBcOffsetBool(offset, isInsufficientPGO);
1103 }
1104 
Clear()1105 void JITProfiler::Clear()
1106 {
1107     bcOffsetPGOOpTypeMap_.clear();
1108     bcOffsetPGODefOpTypeMap_.clear();
1109     bcOffsetPGORwTypeMap_.clear();
1110     bcOffsetBoolMap_.clear();
1111     abcId_ = 0;
1112     profileTypeInfo_ = nullptr;
1113     methodId_ = (EntityId)0;
1114 }
1115 
1116 
~JITProfiler()1117 JITProfiler::~JITProfiler()
1118 {
1119 }
1120 }
1121