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