• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/compiler/type_info_accessors.h"
17 
18 #include "ecmascript/compiler/bytecodes.h"
19 #include "ecmascript/global_env.h"
20 
21 namespace panda::ecmascript::kungfu {
PGOSampleTypeToParamType() const22 ParamType TypeInfoAccessor::PGOSampleTypeToParamType() const
23 {
24     if (pgoType_.IsPGOSampleType()) {
25         auto sample = pgoType_.GetPGOSampleType();
26         if (sample->IsInt()) {
27             return ParamType::IntType();
28         } else if (sample->IsIntOverFlow()) {
29             return ParamType::IntOverflowType();
30         } else if (sample->IsDouble()) {
31             return ParamType::DoubleType();
32         } else if (sample->IsString()) {
33             return ParamType::StringType();
34         } else if (sample->IsInternString()) {
35             return ParamType::InternStringType();
36         } else if (sample->IsBigInt()) {
37             return ParamType::BigIntType();
38         } else if (sample->IsBoolean()) {
39             return ParamType::BooleanType();
40         } else if (sample->IsNumber()) {
41             return ParamType::NumberType();
42         } else if (sample->IsNumberOrString()) {
43             return ParamType::StringType();
44         }
45     }
46     return ParamType::AnyType();
47 }
48 
PGOBuiltinTypeToParamType(ProfileType pgoType)49 ParamType TypeInfoAccessor::PGOBuiltinTypeToParamType(ProfileType pgoType)
50 {
51     if (pgoType.IsBuiltinsType()) {
52         return ParamType(static_cast<uint32_t>(pgoType.GetBuiltinsType()), true);
53     }
54     return ParamType::AnyType();
55 }
56 
57 // TypeTrusted means the type of gate is already PrimitiveTypeCheck-passed,
58 // or the gate is constant and no need to check.
IsTrustedBooleanType(GateAccessor acc,GateRef gate)59 bool TypeInfoAccessor::IsTrustedBooleanType(GateAccessor acc, GateRef gate)
60 {
61     if (acc.IsConstant(gate) && acc.GetGateType(gate).IsBooleanType()) {
62         return true;
63     }
64     auto op = acc.GetOpCode(gate);
65     if (op == OpCode::TYPED_BINARY_OP) {
66         return TypedBinaryAccessor(acc.TryGetValue(gate)).IsTrustedBooleanType();
67     }
68     if (op == OpCode::TYPED_UNARY_OP) {
69         return TypedUnaryAccessor(acc.TryGetValue(gate)).IsTrustedBooleanType();
70     }
71     if (op == OpCode::JS_BYTECODE) {
72         EcmaOpcode ecmaOpcode = acc.GetByteCodeOpcode(gate);
73         switch (ecmaOpcode) {
74             case EcmaOpcode::LESS_IMM8_V8:
75             case EcmaOpcode::LESSEQ_IMM8_V8:
76             case EcmaOpcode::GREATER_IMM8_V8:
77             case EcmaOpcode::GREATEREQ_IMM8_V8:
78             case EcmaOpcode::EQ_IMM8_V8:
79             case EcmaOpcode::NOTEQ_IMM8_V8:
80             case EcmaOpcode::STRICTEQ_IMM8_V8:
81             case EcmaOpcode::STRICTNOTEQ_IMM8_V8:
82             case EcmaOpcode::ISTRUE:
83             case EcmaOpcode::ISFALSE:
84             case EcmaOpcode::CALLRUNTIME_ISFALSE_PREF_IMM8:
85             case EcmaOpcode::CALLRUNTIME_ISTRUE_PREF_IMM8:
86                 return true;
87             default:
88                 break;
89         }
90     }
91     return false;
92 }
93 
IsTrustedNumberType(GateAccessor acc,GateRef gate)94 bool TypeInfoAccessor::IsTrustedNumberType(GateAccessor acc, GateRef gate)
95 {
96     if (acc.IsConstant(gate) && acc.GetGateType(gate).IsNumberType()) {
97         return true;
98     }
99     auto op = acc.GetOpCode(gate);
100     if (op == OpCode::TYPED_BINARY_OP) {
101         return TypedBinaryAccessor(acc.TryGetValue(gate)).IsTrustedNumberType();
102     }
103     if (op == OpCode::TYPED_UNARY_OP) {
104         return TypedUnaryAccessor(acc.TryGetValue(gate)).IsTrustedNumberType();
105     }
106     if (op == OpCode::TYPE_CONVERT) {
107         // typeconvert only use in tomumeric
108         return true;
109     }
110     if (op == OpCode::LOAD_ELEMENT) {
111         auto loadOp = acc.GetTypedLoadOp(gate);
112         switch (loadOp) {
113             case TypedLoadOp::INT8ARRAY_LOAD_ELEMENT:
114             case TypedLoadOp::UINT8ARRAY_LOAD_ELEMENT:
115             case TypedLoadOp::UINT8CLAMPEDARRAY_LOAD_ELEMENT:
116             case TypedLoadOp::INT16ARRAY_LOAD_ELEMENT:
117             case TypedLoadOp::UINT16ARRAY_LOAD_ELEMENT:
118             case TypedLoadOp::INT32ARRAY_LOAD_ELEMENT:
119             case TypedLoadOp::UINT32ARRAY_LOAD_ELEMENT:
120             case TypedLoadOp::FLOAT32ARRAY_LOAD_ELEMENT:
121             case TypedLoadOp::FLOAT64ARRAY_LOAD_ELEMENT:
122                 return true;
123             default:
124                 return false;
125         }
126     }
127 
128     if (op == OpCode::JS_BYTECODE) {
129         EcmaOpcode ecmaOpcode = acc.GetByteCodeOpcode(gate);
130         switch (ecmaOpcode) {
131             case EcmaOpcode::ADD2_IMM8_V8:
132             case EcmaOpcode::SUB2_IMM8_V8:
133             case EcmaOpcode::MUL2_IMM8_V8:
134             case EcmaOpcode::DIV2_IMM8_V8:
135             case EcmaOpcode::MOD2_IMM8_V8:
136             case EcmaOpcode::SHL2_IMM8_V8:
137             case EcmaOpcode::SHR2_IMM8_V8:
138             case EcmaOpcode::ASHR2_IMM8_V8:
139             case EcmaOpcode::AND2_IMM8_V8:
140             case EcmaOpcode::OR2_IMM8_V8:
141             case EcmaOpcode::XOR2_IMM8_V8:
142             case EcmaOpcode::INC_IMM8:
143             case EcmaOpcode::DEC_IMM8:
144             case EcmaOpcode::NEG_IMM8:
145             case EcmaOpcode::NOT_IMM8:
146                 return acc.TryGetPGOType(gate).GetPGOSampleType()->HasNumber();
147             default:
148                 break;
149         }
150     }
151     return false;
152 }
153 
IsTrustedStringType(const CompilationEnv * env,Circuit * circuit,Chunk * chunk,GateAccessor acc,GateRef gate)154 bool TypeInfoAccessor::IsTrustedStringType(
155     const CompilationEnv *env, Circuit *circuit, Chunk *chunk, GateAccessor acc, GateRef gate)
156 {
157     auto op = acc.GetOpCode(gate);
158     if (op == OpCode::LOAD_ELEMENT) {
159         return acc.GetTypedLoadOp(gate) == TypedLoadOp::STRING_LOAD_ELEMENT;
160     }
161     if (op == OpCode::NUMBER_TO_STRING) {
162         return true;
163     }
164     if (op == OpCode::TYPED_BINARY_OP) {
165         return TypedBinaryAccessor(acc.TryGetValue(gate)).IsTrustedStringType();
166     }
167 
168     if (op == OpCode::JS_BYTECODE) {
169         EcmaOpcode ecmaOpcode = acc.GetByteCodeOpcode(gate);
170         switch (ecmaOpcode) {
171             case EcmaOpcode::LDA_STR_ID16:
172                 return true;
173             case EcmaOpcode::LDOBJBYVALUE_IMM8_V8:
174             case EcmaOpcode::LDOBJBYVALUE_IMM16_V8: {
175                 LoadBuiltinObjTypeInfoAccessor tacc(env, circuit, gate, chunk);
176                 if (tacc.IsMono()) {
177                     return tacc.IsBuiltinsString();
178                 }
179                 break;
180             }
181             default:
182                 break;
183         }
184     }
185     return false;
186 }
187 
IsTrustedNotSameType(const CompilationEnv * env,Circuit * circuit,Chunk * chunk,GateAccessor acc,GateRef left,GateRef right)188 bool TypeInfoAccessor::IsTrustedNotSameType(const CompilationEnv *env, Circuit *circuit, Chunk *chunk,
189                                             GateAccessor acc, GateRef left, GateRef right)
190 {
191     bool leftIsBoolean = IsTrustedBooleanType(acc, left);
192     bool rightIsBoolean = IsTrustedBooleanType(acc, right);
193     bool leftIsNumber = IsTrustedNumberType(acc, left);
194     bool rightIsNumber = IsTrustedNumberType(acc, right);
195     bool leftIsString = IsTrustedStringType(env, circuit, chunk, acc, left);
196     bool rightIsString = IsTrustedStringType(env, circuit, chunk, acc, right);
197     if (leftIsBoolean) {
198         return rightIsNumber || rightIsString;
199     }
200 
201     if (leftIsNumber) {
202         return rightIsBoolean || rightIsString;
203     }
204 
205     if (leftIsString) {
206         return rightIsBoolean || rightIsNumber;
207     }
208 
209     return false;
210 }
211 
TryGetPGOBuiltinMethodId() const212 BuiltinsStubCSigns::ID TypeInfoAccessor::TryGetPGOBuiltinMethodId() const
213 {
214     PGOTypeRef sampleType = acc_.TryGetPGOType(gate_);
215     if (sampleType.GetPGOSampleType()->IsNone()) {
216         return BuiltinsStubCSigns::ID::NONE;
217     }
218     if (sampleType.GetPGOSampleType()->GetProfileType().IsBuiltinFunctionId()) {
219         return static_cast<BuiltinsStubCSigns::ID>(sampleType.GetPGOSampleType()->GetProfileType().GetId());
220     }
221     return BuiltinsStubCSigns::ID::NONE;
222 }
223 
FindHClass() const224 bool NewObjRangeTypeInfoAccessor::AotAccessorStrategy::FindHClass() const
225 {
226     auto sampleType = parent_.pgoType_.GetPGOSampleType();
227     if (!sampleType->IsProfileType()) {
228         return false;
229     }
230     ProfileType profileType = sampleType->GetProfileType();
231     auto type = std::make_pair(profileType, profileType);
232     parent_.hclassIndex_ = static_cast<int>(parent_.ptManager_->GetHClassIndexByProfileType(type));
233     if (parent_.hclassIndex_ == -1) {
234         return false;
235     }
236     profileType.UpdateKind(pgo::ProfileType::Kind::TransitionClassId);
237     auto transType = std::make_pair(profileType, profileType);
238     parent_.traHClassIndex_ = static_cast<int>(parent_.ptManager_->GetHClassIndexByProfileType(transType));
239     if (parent_.traHClassIndex_ == -1) {
240         return parent_.ptManager_->QueryHClass(type.first, type.second).IsJSHClass();
241     }
242     return parent_.ptManager_->QueryHClass(transType.first, transType.second).IsJSHClass();
243 }
244 
FindHClass() const245 bool NewObjRangeTypeInfoAccessor::JitAccessorStrategy::FindHClass() const
246 {
247     // For JIT, it handles Builtin using SampleType. For handling others, it uses DefType.
248     // Therefore, when it's SampleType, it can directly return.
249     if (parent_.pgoType_.IsPGOSampleType()) {
250         return false;
251     }
252     auto sampleType = parent_.pgoType_.GetPGODefineOpType();
253     if (sampleType->IsNone()) {
254         return false;
255     }
256     JSHClass *hclass = sampleType->GetReceiver();
257     bool result = hclass != nullptr;
258     if (result) {
259         parent_.hclassIndex_ = parent_.ptManager_->RecordAndGetHclassIndexForJIT(hclass);
260     }
261     return result;
262 }
263 
GetHClass() const264 JSTaggedValue NewObjRangeTypeInfoAccessor::AotAccessorStrategy::GetHClass() const
265 {
266     auto sampleType = parent_.pgoType_.GetPGOSampleType();
267     ASSERT(sampleType->IsProfileType());
268     ProfileType profileType = sampleType->GetProfileType();
269     auto type = std::make_pair(profileType, profileType);
270     parent_.hclassIndex_ = static_cast<int>(parent_.ptManager_->GetHClassIndexByProfileType(type));
271     ASSERT(parent_.hclassIndex_ != -1);
272     profileType.UpdateKind(pgo::ProfileType::Kind::TransitionClassId);
273     auto transType = std::make_pair(profileType, profileType);
274     parent_.traHClassIndex_ = static_cast<int>(parent_.ptManager_->GetHClassIndexByProfileType(transType));
275     if (parent_.traHClassIndex_ == -1) {
276         return parent_.ptManager_->QueryHClass(type.first, type.second);
277     }
278     return parent_.ptManager_->QueryHClass(transType.first, transType.second);
279 }
280 
GetHClass() const281 JSTaggedValue NewObjRangeTypeInfoAccessor::JitAccessorStrategy::GetHClass() const
282 {
283     auto sampleType = parent_.pgoType_.GetPGODefineOpType();
284     ASSERT(!sampleType->IsNone());
285     JSHClass *hclass = sampleType->GetReceiver();
286     parent_.hclassIndex_ = parent_.ptManager_->RecordAndGetHclassIndexForJIT(hclass);
287     return JSTaggedValue(sampleType->GetReceiver());
288 }
289 
IsIllegalType() const290 bool TypeOfTypeInfoAccessor::IsIllegalType() const
291 {
292     return true;
293 }
294 
SuperCallTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,const JSPandaFile * jsPandaFile,const CallMethodFlagMap * callMethodFlagMap)295 SuperCallTypeInfoAccessor::SuperCallTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate,
296                                                      const JSPandaFile *jsPandaFile,
297                                                      const CallMethodFlagMap *callMethodFlagMap)
298     : TypeInfoAccessor(env, circuit, gate), jsPandaFile_(jsPandaFile), callMethodFlagMap_(callMethodFlagMap)
299 {
300     ctor_ = circuit->GetArgumentAccessor()->GetFrameArgsIn(gate, FrameArgIdx::FUNC);
301 }
302 
GetIteratorTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,const JSPandaFile * jsPandaFile,const CallMethodFlagMap * callMethodFlagMap)303 GetIteratorTypeInfoAccessor::GetIteratorTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate,
304                                                          const JSPandaFile *jsPandaFile,
305                                                          const CallMethodFlagMap *callMethodFlagMap)
306     : CallTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap)
307 {
308     argc_ = 0; // 0: number of argc
309     func_ = acc_.GetValueIn(gate, 0); // 1: func
310 }
311 
CallArg0TypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,const JSPandaFile * jsPandaFile,const CallMethodFlagMap * callMethodFlagMap)312 CallArg0TypeInfoAccessor::CallArg0TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate,
313                                                    const JSPandaFile *jsPandaFile,
314                                                    const CallMethodFlagMap *callMethodFlagMap)
315     : CallTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap)
316 {
317     argc_ = 0; // 0: number of argc
318     func_ = acc_.GetValueIn(gate, 0); // 0: func
319 }
320 
CallArg1TypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,const JSPandaFile * jsPandaFile,const CallMethodFlagMap * callMethodFlagMap)321 CallArg1TypeInfoAccessor::CallArg1TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate,
322                                                    const JSPandaFile *jsPandaFile,
323                                                    const CallMethodFlagMap *callMethodFlagMap)
324     : CallTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap)
325 {
326     argc_ = 1; // 1: number of argc
327     value_ = acc_.GetValueIn(gate, 0); // 0: value
328     func_ = acc_.GetValueIn(gate, 1); // 1: func
329 }
330 
CallArg2TypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,const JSPandaFile * jsPandaFile,const CallMethodFlagMap * callMethodFlagMap)331 CallArg2TypeInfoAccessor::CallArg2TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate,
332                                                    const JSPandaFile *jsPandaFile,
333                                                    const CallMethodFlagMap *callMethodFlagMap)
334     : CallTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap)
335 {
336     argc_ = 2; // 2: number of argc
337     func_ = acc_.GetValueIn(gate, 2); // 2: func
338 }
339 
CallArg3TypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,const JSPandaFile * jsPandaFile,const CallMethodFlagMap * callMethodFlagMap)340 CallArg3TypeInfoAccessor::CallArg3TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate,
341                                                    const JSPandaFile *jsPandaFile,
342                                                    const CallMethodFlagMap *callMethodFlagMap)
343     : CallTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap)
344 {
345     argc_ = 3; // 3: number of argc
346     func_ = acc_.GetValueIn(gate, 3); // 3: func
347 }
348 
CallRangeTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,const JSPandaFile * jsPandaFile,const CallMethodFlagMap * callMethodFlagMap)349 CallRangeTypeInfoAccessor::CallRangeTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate,
350                                                      const JSPandaFile *jsPandaFile,
351                                                      const CallMethodFlagMap *callMethodFlagMap)
352     : CallTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap)
353 {
354     size_t numArgs = acc_.GetNumValueIn(gate);
355     constexpr size_t callTargetIndex = 1; // acc
356     ASSERT(numArgs > 0);
357     argc_ = numArgs - callTargetIndex;
358     func_ = acc_.GetValueIn(gate, argc_);
359 }
360 
CanOptimizeAsFastCall()361 bool CallThisTypeInfoAccessor::CanOptimizeAsFastCall()
362 {
363     auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType();
364     auto op = acc_.GetOpCode(func_);
365     if (!IsValidCallMethodId()) {
366         return false;
367     }
368     if (!profileType->IsNone()) {
369         if (profileType->IsProfileTypeNone() ||
370             (op != OpCode::LOAD_PROPERTY && op != OpCode::MONO_LOAD_PROPERTY_ON_PROTO)) {
371             return false;
372         }
373         return true;
374     }
375     return false;
376 }
377 
CallThis0TypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,const JSPandaFile * jsPandaFile,const CallMethodFlagMap * callMethodFlagMap)378 CallThis0TypeInfoAccessor::CallThis0TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate,
379                                                      const JSPandaFile *jsPandaFile,
380                                                      const CallMethodFlagMap *callMethodFlagMap)
381     : CallThisTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap)
382 {
383     argc_ = 0; // 0: number of argc
384     func_ = acc_.GetValueIn(gate, 1); // 1: func
385 }
386 
CallThis1TypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,const JSPandaFile * jsPandaFile,const CallMethodFlagMap * callMethodFlagMap)387 CallThis1TypeInfoAccessor::CallThis1TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate,
388                                                      const JSPandaFile *jsPandaFile,
389                                                      const CallMethodFlagMap *callMethodFlagMap)
390     : CallThisTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap)
391 {
392     argc_ = 1; // 1: number of argc
393     func_ = acc_.GetValueIn(gate, 2); // 2: func
394     a0_ = acc_.GetValueIn(gate, 1); // 1: arg0
395 }
396 
CallThis2TypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,const JSPandaFile * jsPandaFile,const CallMethodFlagMap * callMethodFlagMap)397 CallThis2TypeInfoAccessor::CallThis2TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate,
398                                                      const JSPandaFile *jsPandaFile,
399                                                      const CallMethodFlagMap *callMethodFlagMap)
400     : CallThisTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap)
401 {
402     argc_ = 2; // 2: number of argc
403     func_ = acc_.GetValueIn(gate, 3); // 3: func
404     a0_ = acc_.GetValueIn(gate, 1); // 1: arg0
405     a1_ = acc_.GetValueIn(gate, 2); // 2: arg1
406 }
407 
CallThis3TypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,const JSPandaFile * jsPandaFile,const CallMethodFlagMap * callMethodFlagMap)408 CallThis3TypeInfoAccessor::CallThis3TypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate,
409                                                      const JSPandaFile *jsPandaFile,
410                                                      const CallMethodFlagMap *callMethodFlagMap)
411     : CallThisTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap)
412 {
413     argc_ = 3; // 3: number of argc
414     func_ = acc_.GetValueIn(gate, 4); // 4: func
415     a0_ = acc_.GetValueIn(gate, 1); // 1: arg0
416     a1_ = acc_.GetValueIn(gate, 2); // 2: arg1
417     a2_ = acc_.GetValueIn(gate, 3); // 3: arg2
418 }
419 
CallThisRangeTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,const JSPandaFile * jsPandaFile,const CallMethodFlagMap * callMethodFlagMap)420 CallThisRangeTypeInfoAccessor::CallThisRangeTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate,
421                                                              const JSPandaFile *jsPandaFile,
422                                                              const CallMethodFlagMap *callMethodFlagMap)
423     : CallThisTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap)
424 {
425     constexpr size_t fixedInputsNum = 1;
426     constexpr size_t callTargetIndex = 1;  // 1: acc
427     size_t numIns = acc_.GetNumValueIn(gate);
428     ASSERT(numIns >= fixedInputsNum + callTargetIndex);
429     argc_ = numIns - callTargetIndex - fixedInputsNum;
430     func_ = acc_.GetValueIn(gate, numIns - callTargetIndex); // acc
431 }
432 
InlineTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,GateRef receiver,CallKind kind)433 InlineTypeInfoAccessor::InlineTypeInfoAccessor(
434     const CompilationEnv *env, Circuit *circuit, GateRef gate, GateRef receiver, CallKind kind)
435     : TypeInfoAccessor(env, circuit, gate), receiver_(receiver), kind_(kind)
436 {
437     if (IsCallAccessor()) {
438         if (IsAot()) {
439             plr_ = GetAccessorPlr();
440         } else {
441             plr_ = GetAccessorPlrInJIT();
442         }
443     }
444     thisObj_ = Circuit::NullGate();
445 }
InitPropAndCheck(JSTaggedValue & prop) const446 bool InlineTypeInfoAccessor::InitPropAndCheck(JSTaggedValue& prop) const
447 {
448     GateRef constData = acc_.GetValueIn(gate_, 1);
449     uint16_t propIndex = acc_.GetConstantValue(constData);
450     auto methodOffset = acc_.TryGetMethodOffset(gate_);
451     prop = compilationEnv_->GetStringFromConstantPool(methodOffset, propIndex);
452     if (prop.IsUndefined()) {
453         return false;
454     }
455     // PGO currently does not support call, so GT is still used to support inline operations.
456     // However, the original GT solution cannot support accessing the property of prototype, so it is filtered here
457     if (EcmaStringAccessor(prop).ToStdString(compilationEnv_->GetJSThread()) == "prototype") {
458         return false;
459     }
460     return true;
461 }
462 
GetAccessorPlr() const463 PropertyLookupResult InlineTypeInfoAccessor::GetAccessorPlr() const
464 {
465     JSTaggedValue prop = JSTaggedValue::Undefined();
466     if (!InitPropAndCheck(prop)) {
467         return PropertyLookupResult();
468     }
469 
470     const PGORWOpType *pgoTypes = acc_.TryGetPGOType(gate_).GetPGORWOpType();
471     if (pgoTypes->GetCount() != 1) {
472         return PropertyLookupResult();
473     }
474     auto pgoType = pgoTypes->GetObjectInfo(0);
475     ProfileTyper holderType = std::make_pair(pgoType.GetHoldRootType(), pgoType.GetHoldType());
476 
477     PGOTypeManager *ptManager = compilationEnv_->GetPTManager();
478 
479     int hclassIndex = static_cast<int>(ptManager->GetHClassIndexByProfileType(holderType));
480     if (hclassIndex == -1) {
481         return PropertyLookupResult();
482     }
483     JSTaggedValue hclass = ptManager->QueryHClass(holderType.first, holderType.second);
484     if (!hclass.IsJSHClass()) {
485         return PropertyLookupResult();
486     }
487 
488     PropertyLookupResult plr = JSHClass::LookupPropertyInPGOHClass(compilationEnv_->GetJSThread(),
489         JSHClass::Cast(hclass.GetTaggedObject()), prop);
490     return plr;
491 }
492 
493 
GetAccessorPlrInJIT() const494 PropertyLookupResult InlineTypeInfoAccessor::GetAccessorPlrInJIT() const
495 {
496     JSTaggedValue prop = JSTaggedValue::Undefined();
497     if (!InitPropAndCheck(prop)) {
498         return PropertyLookupResult();
499     }
500 
501     const PGORWOpType *pgoTypes = acc_.TryGetPGOType(gate_).GetPGORWOpType();
502     if (pgoTypes->GetCount() != 1) {
503         return PropertyLookupResult();
504     }
505     if (!pgoTypes->GetObjectInfo(0).IsJITClassType()) {
506         return PropertyLookupResult();
507     }
508     auto pgoType = pgoTypes->GetObjectInfo(0);
509     JSHClass* receiverType = pgoType.GetReceiverHclass();
510     JSHClass* holderType = pgoType.GetHolderHclass();
511     JSHClass *hclass = nullptr;
512     if (receiverType == holderType) {
513         hclass = receiverType;
514     } else {
515         hclass = holderType;
516     }
517 
518     PropertyLookupResult plr = JSHClass::LookupPropertyInPGOHClass(compilationEnv_->GetJSThread(), hclass, prop);
519     return plr;
520 }
521 
GetCallMethodId() const522 uint32_t InlineTypeInfoAccessor::GetCallMethodId() const
523 {
524     uint32_t methodOffset = 0;
525     if ((IsNormalCall() || IsSuperCall()) && IsValidCallMethodId()) {
526         methodOffset = GetFuncMethodOffsetFromPGO();
527     }
528     if (IsCallAccessor()) {
529         const PGORWOpType *pgoTypes = acc_.TryGetPGOType(gate_).GetPGORWOpType();
530         auto pgoType = pgoTypes->GetObjectInfo(0);
531         if (pgoType.GetAccessorMethod().GetProfileType().IsValidCallMethodId()) {
532             return pgoType.GetAccessorMethod().GetProfileType().GetCallMethodId();
533         }
534     }
535     return methodOffset;
536 }
537 
GetKeyTaggedValue() const538 JSTaggedValue ObjectAccessTypeInfoAccessor::GetKeyTaggedValue() const
539 {
540     uint16_t index = acc_.GetConstantValue(key_);
541     auto methodOffset = acc_.TryGetMethodOffset(GetGate());
542     return compilationEnv_->GetStringFromConstantPool(methodOffset, index);
543 }
544 
GeneratePlr(ProfileTyper type,ObjectAccessInfo & info,JSTaggedValue key) const545 bool ObjAccByNameTypeInfoAccessor::GeneratePlr(ProfileTyper type, ObjectAccessInfo &info, JSTaggedValue key) const
546 {
547     int hclassIndex = static_cast<int>(ptManager_->GetHClassIndexByProfileType(type));
548     if (hclassIndex == -1) {
549         return false;
550     }
551     JSTaggedValue hclass = ptManager_->QueryHClass(type.first, type.second);
552     if (!hclass.IsJSHClass()) {
553         return false;
554     }
555     PropertyLookupResult plr = JSHClass::LookupPropertyInPGOHClass(compilationEnv_->GetJSThread(),
556         JSHClass::Cast(hclass.GetTaggedObject()), key);
557     info.Set(hclassIndex, plr);
558 
559     if (mode_ == AccessMode::LOAD) {
560         return plr.IsFound();
561     }
562 
563     return (plr.IsFound() && !plr.IsFunction());
564 }
565 
GeneratePlrInJIT(JSHClass * hclass,ObjectAccessInfo & info,JSTaggedValue key) const566 bool ObjAccByNameTypeInfoAccessor::GeneratePlrInJIT(JSHClass* hclass, ObjectAccessInfo &info, JSTaggedValue key) const
567 {
568     PropertyLookupResult plr = JSHClass::LookupPropertyInPGOHClass(compilationEnv_->GetJSThread(), hclass, key);
569     int hclassIndex = ptManager_->RecordAndGetHclassIndexForJIT(hclass);
570     info.Set(hclassIndex, plr);
571 
572     if (mode_ == AccessMode::LOAD) {
573         // For not found ic
574         if (hclass == nullptr) {
575             return true;
576         }
577         return plr.IsFound();
578     }
579 
580     return (plr.IsFound() && !plr.IsFunction());
581 }
582 
FetchPGORWTypesDual()583 void StorePrivatePropertyTypeInfoAccessor::AotAccessorStrategy::FetchPGORWTypesDual()
584 {
585     const PGORWOpType *pgoTypes = parent_.acc_.TryGetPGOType(parent_.gate_).GetPGORWOpType();
586     if (IsMegaType(pgoTypes)) {
587         return;
588     }
589     for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) {
590         auto temp = pgoTypes->GetObjectInfo(i);
591         parent_.types_.emplace_back(std::make_tuple(std::make_pair(temp.GetReceiverRootType(), temp.GetReceiverType()),
592                                                     std::make_pair(temp.GetHoldRootType(), temp.GetHoldType()),
593                                                     std::make_pair(temp.GetHoldTraRootType(), temp.GetHoldTraType())));
594     }
595 }
596 
FetchPGORWTypesDual()597 void StorePrivatePropertyTypeInfoAccessor::JitAccessorStrategy::FetchPGORWTypesDual()
598 {
599     const PGORWOpType *pgoTypes = parent_.acc_.TryGetPGOType(parent_.gate_).GetPGORWOpType();
600     if (IsMegaType(pgoTypes)) {
601         return;
602     }
603     for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) {
604         auto temp = pgoTypes->GetObjectInfo(i);
605         if (temp.GetReceiverType().IsJITClassType()) {
606             parent_.jitTypes_.emplace_back(temp);
607         }
608     }
609 }
610 
GetKeyTaggedValue() const611 JSTaggedValue StorePrivatePropertyTypeInfoAccessor::GetKeyTaggedValue() const
612 {
613     if (types_.empty()) {
614         return JSTaggedValue::Hole();
615     }
616 
617     ProfileTyper receiverType = std::get<0>(types_.at(0));
618     auto slotIndex = acc_.GetConstantValue(slotIndex_);
619     ProfileTypeTuple type = std::make_tuple(receiverType.first, receiverType.second, slotIndex);
620     auto privateId = ptManager_->GetSymbolIdByProfileType(type);
621     if (!privateId) {
622         return JSTaggedValue::Hole();
623     }
624 
625     AOTSnapshot& snapshot = ptManager_->GetAOTSnapshot();
626     auto symbolInfo = snapshot.GetSymbolInfo();
627     auto symbol = ConstantPool::GetSymbolFromSymbolInfo(compilationEnv_->GetJSThread(), symbolInfo, *privateId);
628     return symbol;
629 }
630 
GenerateObjectAccessInfo()631 bool StorePrivatePropertyTypeInfoAccessor::AotAccessorStrategy::GenerateObjectAccessInfo()
632 {
633     JSTaggedValue key = parent_.GetKeyTaggedValue();
634     if (key.IsHole()) {
635         parent_.isAccessor_ = true;
636         return true;
637     }
638 
639     if (parent_.types_.size() == 0) {
640         return false;
641     }
642     ProfileTyper receiverType = std::get<0>(parent_.types_.at(0));
643     ProfileTyper holderType = std::get<1>(parent_.types_.at(0));
644     if (receiverType == holderType) {
645         ObjectAccessInfo receiverInfo;
646         if (!parent_.GeneratePlr(receiverType, receiverInfo, key)) {
647             return false;
648         }
649         parent_.accessInfos_.emplace_back(receiverInfo);
650         parent_.checkerInfos_.emplace_back(receiverInfo);
651     } else {
652         UNREACHABLE();
653     }
654 
655     return true;
656 }
657 
GenerateObjectAccessInfo()658 bool StorePrivatePropertyTypeInfoAccessor::JitAccessorStrategy::GenerateObjectAccessInfo()
659 {
660     JSTaggedValue key = parent_.GetKeyTaggedValue();
661     if (key.IsHole()) {
662         parent_.isAccessor_ = true;
663         return true;
664     }
665 
666     if (parent_.jitTypes_.size() == 0) {
667         return false;
668     }
669     JSHClass *receiverType = parent_.jitTypes_[0].GetReceiverHclass();
670     JSHClass *holderType = parent_.jitTypes_[0].GetHolderHclass();
671     if (receiverType->IsJsPrimitiveRef() || holderType->IsJsPrimitiveRef()) {
672         return false;
673     }
674 
675     if (receiverType == holderType) {
676         ObjectAccessInfo receiverInfo;
677         if (!parent_.GeneratePlrInJIT(receiverType, receiverInfo, key)) {
678             return false;
679         }
680         parent_.accessInfos_.emplace_back(receiverInfo);
681         parent_.checkerInfos_.emplace_back(receiverInfo);
682     } else {
683         UNREACHABLE();
684     }
685 
686     return true;
687 }
688 
FetchPGORWTypesDual()689 void LoadPrivatePropertyTypeInfoAccessor::AotAccessorStrategy::FetchPGORWTypesDual()
690 {
691     const PGORWOpType *pgoTypes = parent_.acc_.TryGetPGOType(parent_.gate_).GetPGORWOpType();
692     if (IsMegaType(pgoTypes)) {
693         return;
694     }
695     for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) {
696         auto temp = pgoTypes->GetObjectInfo(i);
697         parent_.types_.emplace_back(std::make_pair(std::make_pair(temp.GetReceiverRootType(), temp.GetReceiverType()),
698                                                    std::make_pair(temp.GetHoldRootType(), temp.GetHoldType())));
699     }
700 }
701 
FetchPGORWTypesDual()702 void LoadPrivatePropertyTypeInfoAccessor::JitAccessorStrategy::FetchPGORWTypesDual()
703 {
704     const PGORWOpType *pgoTypes = parent_.acc_.TryGetPGOType(parent_.gate_).GetPGORWOpType();
705     if (IsMegaType(pgoTypes)) {
706         return;
707     }
708     for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) {
709         auto temp = pgoTypes->GetObjectInfo(i);
710         if (temp.GetReceiverType().IsJITClassType()) {
711             parent_.jitTypes_.emplace_back(temp);
712         }
713     }
714 }
715 
716 
GetKeyTaggedValue() const717 JSTaggedValue LoadPrivatePropertyTypeInfoAccessor::GetKeyTaggedValue() const
718 {
719     if (types_.empty()) {
720         return JSTaggedValue::Hole();
721     }
722 
723     ProfileTyper receiverType = types_.at(0).first;
724     auto slotIndex = acc_.GetConstantValue(slotIndex_);
725     ProfileTypeTuple type = std::make_tuple(receiverType.first, receiverType.second, slotIndex);
726     auto privateId = ptManager_->GetSymbolIdByProfileType(type);
727     if (!privateId) {
728         return JSTaggedValue::Hole();
729     }
730 
731     AOTSnapshot& snapshot = ptManager_->GetAOTSnapshot();
732     auto symbolInfo = snapshot.GetSymbolInfo();
733     auto symbol = ConstantPool::GetSymbolFromSymbolInfo(compilationEnv_->GetJSThread(), symbolInfo, *privateId);
734     return symbol;
735 }
736 
GenerateObjectAccessInfo()737 bool LoadPrivatePropertyTypeInfoAccessor::AotAccessorStrategy::GenerateObjectAccessInfo()
738 {
739     JSTaggedValue key = parent_.GetKeyTaggedValue();
740     if (key.IsHole()) {
741         parent_.isAccessor_ = true;
742         return true;
743     }
744 
745     if (parent_.types_.size() == 0) {
746         return false;
747     }
748     ProfileTyper receiverType = parent_.types_.at(0).first;
749     ProfileTyper holderType = parent_.types_.at(0).second;
750     if (receiverType == holderType) {
751         ObjectAccessInfo receiverInfo;
752         if (!parent_.GeneratePlr(receiverType, receiverInfo, key)) {
753             return false;
754         }
755         parent_.accessInfos_.emplace_back(receiverInfo);
756         parent_.checkerInfos_.emplace_back(receiverInfo);
757     } else {
758         UNREACHABLE();
759     }
760 
761     return true;
762 }
763 
GenerateObjectAccessInfo()764 bool LoadPrivatePropertyTypeInfoAccessor::JitAccessorStrategy::GenerateObjectAccessInfo()
765 {
766     JSTaggedValue key = parent_.GetKeyTaggedValue();
767     if (key.IsHole()) {
768         parent_.isAccessor_ = true;
769         return true;
770     }
771 
772     if (parent_.jitTypes_.size() == 0) {
773         return false;
774     }
775     JSHClass *receiver = parent_.jitTypes_[0].GetReceiverHclass();
776     JSHClass *holder = parent_.jitTypes_[0].GetHolderHclass();
777     // case: r.toFixed() => HeapObjectCheck Deopt
778     if (receiver->IsJsPrimitiveRef() || holder->IsJsPrimitiveRef()) {
779         return false;
780     }
781 
782     if (receiver == holder) {
783         ObjectAccessInfo receiverInfo;
784         if (!parent_.GeneratePlrInJIT(receiver, receiverInfo, key)) {
785             return false;
786         }
787         parent_.accessInfos_.emplace_back(receiverInfo);
788         parent_.checkerInfos_.emplace_back(receiverInfo);
789     } else {
790         UNREACHABLE();
791     }
792 
793     return true;
794 }
795 
LoadObjPropertyTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,Chunk * chunk,bool isByValue)796 LoadObjPropertyTypeInfoAccessor::LoadObjPropertyTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit,
797                                                                  GateRef gate, Chunk *chunk, bool isByValue)
798     : ObjAccByNameTypeInfoAccessor(env, circuit, gate, chunk, AccessMode::LOAD), types_(chunk_), jitTypes_(chunk_),
799       isByValue_(isByValue)
800 {
801     if (isByValue_) {
802         receiver_ = acc_.GetValueIn(gate, 1); // 1: receiver
803         key_ = acc_.GetValueIn(gate, 2);      // 2: key
804         ASSERT(!IsAot());
805     } else {
806         key_ = acc_.GetValueIn(gate, 1);      // 1: key
807         receiver_ = acc_.GetValueIn(gate, 2); // 2: receiver
808     }
809     if (IsAot()) {
810         strategy_ = chunk_->New<AotAccessorStrategy>(*this);
811     } else {
812         strategy_ = chunk_->New<JitAccessorStrategy>(*this);
813     }
814     strategy_->FetchPGORWTypesDual();
815     hasIllegalType_ = !strategy_->GenerateObjectAccessInfo();
816 }
817 
FetchPGORWTypesDual()818 void LoadObjPropertyTypeInfoAccessor::AotAccessorStrategy::FetchPGORWTypesDual()
819 {
820     const PGORWOpType *pgoTypes = parent_.acc_.TryGetPGOType(parent_.gate_).GetPGORWOpType();
821     if (IsMegaType(pgoTypes)) {
822         return;
823     }
824     for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) {
825         auto temp = pgoTypes->GetObjectInfo(i);
826         if (temp.GetReceiverType().IsBuiltinsType()) {
827             continue;
828         }
829         parent_.types_.emplace_back(std::make_pair(std::make_pair(temp.GetReceiverRootType(), temp.GetReceiverType()),
830                                                    std::make_pair(temp.GetHoldRootType(), temp.GetHoldType())));
831     }
832 }
833 
FetchPGORWTypesDual()834 void LoadObjPropertyTypeInfoAccessor::JitAccessorStrategy::FetchPGORWTypesDual()
835 {
836     const PGORWOpType *pgoTypes = parent_.acc_.TryGetPGOType(parent_.gate_).GetPGORWOpType();
837     if (IsMegaType(pgoTypes)) {
838         return;
839     }
840     if (parent_.isByValue_) {
841         parent_.name_ = pgoTypes->GetName();
842         parent_.nameIdx_ = pgoTypes->GetNameIdx();
843     }
844     for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) {
845         auto temp = pgoTypes->GetObjectInfo(i);
846         if (temp.GetReceiverType().IsJITClassType()) {
847             parent_.jitTypes_.emplace_back(temp);
848         }
849     }
850 }
851 
GenerateObjectAccessInfo()852 bool LoadObjPropertyTypeInfoAccessor::AotAccessorStrategy::GenerateObjectAccessInfo()
853 {
854     JSTaggedValue key = JSTaggedValue::Undefined();
855     if (parent_.isByValue_) {
856         key = parent_.name_.GetTaggedValue();
857     } else {
858         key = parent_.GetKeyTaggedValue();
859     }
860     if (key.IsUndefined()) {
861         return false;
862     }
863     if (parent_.types_.size() == 0) {
864         return false;
865     }
866     for (size_t i = 0; i < parent_.types_.size(); ++i) {
867         ProfileTyper receiverType = parent_.types_[i].first;
868         ProfileTyper holderType = parent_.types_[i].second;
869         if (receiverType == holderType) {
870             ObjectAccessInfo info;
871             if (!parent_.GeneratePlr(receiverType, info, key)) {
872                 return false;
873             }
874             parent_.accessInfos_.emplace_back(info);
875             parent_.checkerInfos_.emplace_back(info);
876         } else {
877             ObjectAccessInfo accInfo;
878             if (!parent_.GeneratePlr(holderType, accInfo, key)) {
879                 return false;
880             }
881             parent_.accessInfos_.emplace_back(accInfo);
882             ObjectAccessInfo checkInfo;
883             parent_.GeneratePlr(receiverType, checkInfo, key);
884             if (checkInfo.HClassIndex() == -1) {
885                 return false;
886             }
887             parent_.checkerInfos_.emplace_back(checkInfo);
888         }
889     }
890     return true;
891 }
892 
GenerateObjectAccessInfo()893 bool LoadObjPropertyTypeInfoAccessor::JitAccessorStrategy::GenerateObjectAccessInfo()
894 {
895     JSTaggedValue key = JSTaggedValue::Undefined();
896     if (parent_.isByValue_) {
897         key = parent_.name_.GetTaggedValue();
898     } else {
899         key = parent_.GetKeyTaggedValue();
900     }
901     if (key.IsUndefined()) {
902         return false;
903     }
904     if (parent_.jitTypes_.size() == 0) {
905         return false;
906     }
907     for (size_t i = 0; i < parent_.jitTypes_.size(); ++i) {
908         JSHClass *receiver = parent_.jitTypes_[i].GetReceiverHclass();
909         JSHClass *holder = parent_.jitTypes_[i].GetHolderHclass();
910         PrimitiveType primitiveType = parent_.jitTypes_[i].GetPrimitiveType();
911         // case: r.toFixed() => HeapObjectCheck Deopt
912         ASSERT(receiver != nullptr);
913         if ((receiver->IsJsPrimitiveRef() ||
914             (holder != nullptr && holder->IsJsPrimitiveRef())) &&
915             !parent_.compilationEnv_->SupportHeapConstant()) {
916             return false;
917         }
918         if (receiver == holder) {
919             ObjectAccessInfo info;
920             if (!parent_.GeneratePlrInJIT(receiver, info, key)) {
921                 return false;
922             }
923             info.SetPrimitiveType(primitiveType);
924             parent_.accessInfos_.emplace_back(info);
925             parent_.checkerInfos_.emplace_back(info);
926         } else {
927             ObjectAccessInfo accInfo;
928             if (!parent_.GeneratePlrInJIT(holder, accInfo, key)) {
929                 return false;
930             }
931             accInfo.SetPrimitiveType(primitiveType);
932             parent_.accessInfos_.emplace_back(accInfo);
933             ObjectAccessInfo checkInfo;
934             parent_.GeneratePlrInJIT(receiver, checkInfo, key);
935             if (checkInfo.HClassIndex() == -1) {
936                 return false;
937             }
938             checkInfo.SetPrimitiveType(primitiveType);
939             parent_.checkerInfos_.emplace_back(checkInfo);
940         }
941         SetPlrIsLoadFromIterResult(parent_.accessInfos_.back().Plr(), parent_.jitTypes_[i].GetReceiverType());
942     }
943     return true;
944 }
945 
StoreObjByNameTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,Chunk * chunk)946 StoreObjByNameTypeInfoAccessor::StoreObjByNameTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit,
947                                                                GateRef gate, Chunk *chunk)
948     : ObjAccByNameTypeInfoAccessor(env, circuit, gate, chunk, AccessMode::STORE), types_(chunk_), jitTypes_(chunk)
949 {
950     EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
951     switch (ecmaOpcode) {
952         case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
953         case EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8:
954         case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
955         case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8: {
956             key_ = acc_.GetValueIn(gate, 1); // 1: key
957             receiver_ = acc_.GetValueIn(gate, 2); // 2: receiver
958             value_ = acc_.GetValueIn(gate, 3); // 3: value
959             break;
960         }
961         case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
962         case EcmaOpcode::STTHISBYNAME_IMM16_ID16: {
963             key_ = acc_.GetValueIn(gate, 1); // 1: key
964             receiver_ = circuit->GetArgumentAccessor()->GetFrameArgsIn(gate, FrameArgIdx::THIS_OBJECT);
965             value_ = acc_.GetValueIn(gate, 2); // 2: value
966             break;
967         }
968         case EcmaOpcode::STOWNBYNAME_IMM8_ID16_V8:
969         case EcmaOpcode::STOWNBYNAME_IMM16_ID16_V8: {
970             key_ = acc_.GetValueIn(gate, 0); // 0: key
971             receiver_ = acc_.GetValueIn(gate, 1); // 1: receiver
972             value_ = acc_.GetValueIn(gate, 2); // 2: value
973             break;
974         }
975         default:
976             UNREACHABLE();
977     }
978 
979     if (IsAot()) {
980         strategy_ = chunk_->New<AotAccessorStrategy>(*this);
981     } else {
982         strategy_ = chunk_->New<JitAccessorStrategy>(*this);
983     }
984     strategy_->FetchPGORWTypesDual();
985     hasIllegalType_ = !strategy_->GenerateObjectAccessInfo();
986 }
987 
FetchPGORWTypesDual()988 void StoreObjByNameTypeInfoAccessor::AotAccessorStrategy::FetchPGORWTypesDual()
989 {
990     const PGORWOpType *pgoTypes = parent_.acc_.TryGetPGOType(parent_.gate_).GetPGORWOpType();
991     if (IsMegaType(pgoTypes)) {
992         return;
993     }
994     for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) {
995         auto temp = pgoTypes->GetObjectInfo(i);
996         parent_.types_.emplace_back(std::make_tuple(
997             std::make_pair(temp.GetReceiverRootType(), temp.GetReceiverType()),
998             std::make_pair(temp.GetHoldRootType(), temp.GetHoldType()),
999             std::make_pair(temp.GetHoldTraRootType(), temp.GetHoldTraType())
1000         ));
1001     }
1002 }
1003 
FetchPGORWTypesDual()1004 void StoreObjByNameTypeInfoAccessor::JitAccessorStrategy::FetchPGORWTypesDual()
1005 {
1006     const PGORWOpType *pgoTypes = parent_.acc_.TryGetPGOType(parent_.gate_).GetPGORWOpType();
1007     if (IsMegaType(pgoTypes)) {
1008         return;
1009     }
1010     for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) {
1011         auto temp = pgoTypes->GetObjectInfo(i);
1012         if (temp.GetReceiverType().IsJITClassType()) {
1013             parent_.jitTypes_.emplace_back(temp);
1014         }
1015     }
1016 }
1017 
GenerateObjectAccessInfo()1018 bool StoreObjByNameTypeInfoAccessor::AotAccessorStrategy::GenerateObjectAccessInfo()
1019 {
1020     JSTaggedValue key = parent_.GetKeyTaggedValue();
1021     if (parent_.types_.size() == 0) {
1022         return false;
1023     }
1024     for (size_t i = 0; i < parent_.types_.size(); ++i) {
1025         ProfileTyper receiverType = std::get<0>(parent_.types_[i]);
1026         ProfileTyper holderType = std::get<1>(parent_.types_[i]);
1027         ProfileTyper newHolderType = std::get<2>(parent_.types_[i]);
1028 
1029         if (receiverType != newHolderType) {
1030             // transition happened ==> slowpath
1031             ObjectAccessInfo newHolderInfo;
1032             if (!parent_.GeneratePlr(newHolderType, newHolderInfo, key)) {
1033                 return false;
1034             }
1035             parent_.accessInfos_.emplace_back(newHolderInfo);
1036 
1037             ObjectAccessInfo receiverInfo;
1038             parent_.GeneratePlr(receiverType, receiverInfo, key);
1039             if (receiverInfo.HClassIndex() == -1) {
1040                 return false;
1041             }
1042             parent_.checkerInfos_.emplace_back(receiverInfo);
1043         } else if (receiverType == holderType) {
1044             ObjectAccessInfo receiverInfo;
1045             if (!parent_.GeneratePlr(receiverType, receiverInfo, key)) {
1046                 return false;
1047             }
1048             parent_.accessInfos_.emplace_back(receiverInfo);
1049             parent_.checkerInfos_.emplace_back(receiverInfo);
1050         } else {
1051             UNREACHABLE();
1052         }
1053     }
1054     return true;
1055 }
1056 
GenerateObjectAccessInfo()1057 bool StoreObjByNameTypeInfoAccessor::JitAccessorStrategy::GenerateObjectAccessInfo()
1058 {
1059     JSTaggedValue key = parent_.GetKeyTaggedValue();
1060     if (key.IsUndefined()) {
1061         return false;
1062     }
1063     if (parent_.jitTypes_.size() == 0) {
1064         return false;
1065     }
1066     for (size_t i = 0; i < parent_.jitTypes_.size(); ++i) {
1067         JSHClass* receiverType = parent_.jitTypes_[i].GetReceiverHclass();
1068         JSHClass* holderType = parent_.jitTypes_[i].GetHolderHclass();
1069         if (receiverType->IsJsPrimitiveRef() || holderType->IsJsPrimitiveRef()) {
1070             return false;
1071         }
1072         JSHClass* newHolderType = parent_.jitTypes_[i].GetHolderTraHclass();
1073 
1074         if (receiverType != newHolderType) {
1075             // transition happened ==> slowpath
1076             ObjectAccessInfo newHolderInfo;
1077             if (!parent_.GeneratePlrInJIT(newHolderType, newHolderInfo, key)) {
1078                 return false;
1079             }
1080             parent_.accessInfos_.emplace_back(newHolderInfo);
1081 
1082             ObjectAccessInfo receiverInfo;
1083             parent_.GeneratePlrInJIT(receiverType, receiverInfo, key);
1084             if (receiverInfo.HClassIndex() == -1) {
1085                 return false;
1086             }
1087             parent_.checkerInfos_.emplace_back(receiverInfo);
1088         } else if (receiverType == holderType) {
1089             ObjectAccessInfo receiverInfo;
1090             if (!parent_.GeneratePlrInJIT(receiverType, receiverInfo, key)) {
1091                 return false;
1092             }
1093             parent_.accessInfos_.emplace_back(receiverInfo);
1094             parent_.checkerInfos_.emplace_back(receiverInfo);
1095         } else {
1096             UNREACHABLE();
1097         }
1098     }
1099     return true;
1100 }
1101 
InstanceOfTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,Chunk * chunk)1102 InstanceOfTypeInfoAccessor::InstanceOfTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate,
1103                                                        Chunk *chunk)
1104     : ObjAccByNameTypeInfoAccessor(env, circuit, gate, chunk, AccessMode::LOAD), types_(chunk_), jitTypes_(chunk)
1105 {
1106     receiver_ = acc_.GetValueIn(gate, 1); // 2: receiver
1107     target_ = acc_.GetValueIn(gate, 2);   // 2: the third parameter
1108     if (IsAot()) {
1109         strategy_ = chunk_->New<AotAccessorStrategy>(*this);
1110     } else {
1111         strategy_ = chunk_->New<JitAccessorStrategy>(*this);
1112     }
1113     strategy_->FetchPGORWTypesDual();
1114     hasIllegalType_ = !strategy_->GenerateObjectAccessInfo();
1115 }
1116 
GetKeyTaggedValue() const1117 JSTaggedValue InstanceOfTypeInfoAccessor::GetKeyTaggedValue() const
1118 {
1119     JSHandle<GlobalEnv> globalEnv = compilationEnv_->GetGlobalEnv();
1120     auto hasInstanceEnvIndex = static_cast<size_t>(GlobalEnvField::HASINSTANCE_SYMBOL_INDEX);
1121     return globalEnv->GetGlobalEnvObjectByIndex(hasInstanceEnvIndex).GetTaggedValue();
1122 }
1123 
FetchPGORWTypesDual()1124 void InstanceOfTypeInfoAccessor::AotAccessorStrategy::FetchPGORWTypesDual()
1125 {
1126     const PGORWOpType *pgoTypes = parent_.acc_.TryGetPGOType(parent_.gate_).GetPGORWOpType();
1127     if (IsMegaType(pgoTypes)) {
1128         return;
1129     }
1130     for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) {
1131         auto temp = pgoTypes->GetObjectInfo(i);
1132         if (temp.GetReceiverType().IsBuiltinsType()) {
1133             continue;
1134         }
1135         parent_.types_.emplace_back(std::make_pair(std::make_pair(temp.GetReceiverRootType(), temp.GetReceiverType()),
1136                                                    std::make_pair(temp.GetHoldRootType(), temp.GetHoldType())));
1137     }
1138 }
1139 
FetchPGORWTypesDual()1140 void InstanceOfTypeInfoAccessor::JitAccessorStrategy::FetchPGORWTypesDual()
1141 {
1142     const PGORWOpType *pgoTypes = parent_.acc_.TryGetPGOType(parent_.gate_).GetPGORWOpType();
1143     if (IsMegaType(pgoTypes)) {
1144         return;
1145     }
1146     for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) {
1147         auto temp = pgoTypes->GetObjectInfo(i);
1148         if (temp.GetReceiverType().IsJITClassType()) {
1149             parent_.jitTypes_.emplace_back(temp);
1150         }
1151     }
1152 }
1153 
1154 
ClassInstanceIsCallable(ProfileTyper type) const1155 bool InstanceOfTypeInfoAccessor::AotAccessorStrategy::ClassInstanceIsCallable(ProfileTyper type) const
1156 {
1157     int hclassIndex = static_cast<int>(parent_.ptManager_->GetHClassIndexByProfileType(type));
1158     if (hclassIndex == -1) {
1159         return false;
1160     }
1161 
1162     JSTaggedValue hclass = parent_.ptManager_->QueryHClass(type.first, type.second);
1163     if (!hclass.IsJSHClass()) {
1164         return false;
1165     }
1166     return JSHClass::Cast(hclass.GetTaggedObject())->IsCallable();
1167 }
1168 
ClassInstanceIsCallable(JSHClass * hclass) const1169 bool InstanceOfTypeInfoAccessor::JitAccessorStrategy::ClassInstanceIsCallable(JSHClass *hclass) const
1170 {
1171     return hclass->IsCallable();
1172 }
1173 
1174 
GenerateObjectAccessInfo()1175 bool InstanceOfTypeInfoAccessor::AotAccessorStrategy::GenerateObjectAccessInfo()
1176 {
1177     // Instanceof does not support Poly for now
1178     if (!IsMono()) {
1179         return false;
1180     }
1181     if (parent_.types_.size() == 0) {
1182         return false;
1183     }
1184     JSTaggedValue key = parent_.GetKeyTaggedValue();
1185     for (size_t i = 0; i < parent_.types_.size(); ++i) {
1186         ProfileTyper targetPgoType = parent_.types_[i].first;
1187         ObjectAccessInfo targetInfo;
1188         // If @@hasInstance is found on prototype Chain of ctor -> slowpath
1189         // Future work: pgo support Symbol && Dump Object.defineProperty && FunctionPrototypeHclass
1190         // Current temporary solution:
1191         // Try searching @@hasInstance in pgo dump stage,
1192         // If found, pgo dump no types and we go slowpath in aot
1193         parent_.GeneratePlr(targetPgoType, targetInfo, key);
1194         if (targetInfo.HClassIndex() == -1 || !ClassInstanceIsCallable(targetPgoType)) {
1195             return false;
1196         }
1197         parent_.accessInfos_.emplace_back(targetInfo);
1198         parent_.checkerInfos_.emplace_back(targetInfo);
1199     }
1200     return true;
1201 }
1202 
GenerateObjectAccessInfo()1203 bool InstanceOfTypeInfoAccessor::JitAccessorStrategy::GenerateObjectAccessInfo()
1204 {
1205     // Instanceof does not support Poly for now
1206     if (!IsMono()) {
1207         return false;
1208     }
1209     JSTaggedValue key = parent_.GetKeyTaggedValue();
1210     if (key.IsUndefined()) {
1211         return false;
1212     }
1213     if (parent_.jitTypes_.size() == 0) {
1214         return false;
1215     }
1216     for (size_t i = 0; i < parent_.jitTypes_.size(); ++i) {
1217         JSHClass *receiver = parent_.jitTypes_[i].GetReceiverHclass();
1218         if (receiver->IsJsPrimitiveRef()) {
1219             return false;
1220         }
1221         ObjectAccessInfo targetInfo;
1222         // If @@hasInstance is found on prototype Chain of ctor -> slowpath
1223         // Future work: pgo support Symbol && Dump Object.defineProperty && FunctionPrototypeHclass
1224         // Current temporary solution:
1225         // Try searching @@hasInstance in pgo dump stage,
1226         // If found, pgo dump no types and we go slowpath in aot
1227         parent_.GeneratePlrInJIT(receiver, targetInfo, key);
1228         if (targetInfo.HClassIndex() == -1 || !ClassInstanceIsCallable(receiver)) {
1229             return false;
1230         }
1231         parent_.accessInfos_.emplace_back(targetInfo);
1232         parent_.checkerInfos_.emplace_back(targetInfo);
1233     }
1234     return true;
1235 }
1236 
FetchPGORWTypesDual()1237 void LoadBuiltinObjTypeInfoAccessor::AotAccessorStrategy::FetchPGORWTypesDual()
1238 {
1239 }
1240 
FetchPGORWTypesDual()1241 void LoadBuiltinObjTypeInfoAccessor::JitAccessorStrategy::FetchPGORWTypesDual()
1242 {
1243     const PGORWOpType *pgoTypes = parent_.acc_.TryGetPGOType(parent_.gate_).GetPGORWOpType();
1244     for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) {
1245         auto temp = pgoTypes->GetObjectInfo(i);
1246         if (temp.GetReceiverType().IsBuiltinsType()) {
1247             parent_.jitTypes_.emplace_back(temp);
1248         }
1249     }
1250 }
1251 
LoadBuiltinObjTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,Chunk * chunk)1252 LoadBuiltinObjTypeInfoAccessor::LoadBuiltinObjTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit,
1253                                                                GateRef gate, Chunk *chunk)
1254     : AccBuiltinObjTypeInfoAccessor(env, circuit, gate, chunk, AccessMode::LOAD), jitTypes_(chunk_)
1255 {
1256     EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
1257     switch (ecmaOpcode) {
1258         case EcmaOpcode::LDOBJBYVALUE_IMM8_V8:
1259         case EcmaOpcode::LDOBJBYVALUE_IMM16_V8: {
1260             receiver_ = acc_.GetValueIn(gate, 1); // 1: receiver
1261             key_ = acc_.GetValueIn(gate, 2);  // 2: key
1262             break;
1263         }
1264         case EcmaOpcode::LDTHISBYVALUE_IMM8:
1265         case EcmaOpcode::LDTHISBYVALUE_IMM16: {
1266             receiver_ = circuit->GetArgumentAccessor()->GetFrameArgsIn(gate, FrameArgIdx::THIS_OBJECT);
1267             key_ = acc_.GetValueIn(gate, 1); // 1: key
1268             break;
1269         }
1270         case EcmaOpcode::LDOBJBYNAME_IMM8_ID16:
1271         case EcmaOpcode::LDOBJBYNAME_IMM16_ID16: {
1272             key_ = acc_.GetValueIn(gate, 1); // 1: key
1273             receiver_ = acc_.GetValueIn(gate, 2); // 2: receiver
1274             break;
1275         }
1276         case EcmaOpcode::LDTHISBYNAME_IMM8_ID16:
1277         case EcmaOpcode::LDTHISBYNAME_IMM16_ID16: {
1278             key_ = acc_.GetValueIn(gate, 1); // 1: key
1279             receiver_ = circuit->GetArgumentAccessor()->GetFrameArgsIn(gate, FrameArgIdx::THIS_OBJECT);
1280             break;
1281         }
1282         case EcmaOpcode::LDOBJBYINDEX_IMM8_IMM16:
1283         case EcmaOpcode::LDOBJBYINDEX_IMM16_IMM16:
1284         case EcmaOpcode::WIDE_LDOBJBYINDEX_PREF_IMM32: {
1285             key_ = acc_.GetValueIn(gate, 0);
1286             receiver_ = acc_.GetValueIn(gate, 1);
1287             break;
1288         }
1289         default:
1290             UNREACHABLE();
1291     }
1292 
1293     if (IsAot()) {
1294         strategy_ = chunk_->New<AotAccessorStrategy>(*this);
1295     } else {
1296         strategy_ = chunk_->New<JitAccessorStrategy>(*this);
1297     }
1298     strategy_->FetchPGORWTypesDual();
1299     FetchBuiltinsTypes();
1300 }
1301 
IsStringMonoBuiltins() const1302 bool AccBuiltinObjTypeInfoAccessor::IsStringMonoBuiltins() const
1303 {
1304     for (auto type : types_) {
1305         if (!type.IsBuiltinsString()) {
1306             return false;
1307         }
1308     }
1309     return true;
1310 }
1311 
IsMonoBuiltins() const1312 bool AccBuiltinObjTypeInfoAccessor::IsMonoBuiltins() const
1313 {
1314     if (types_.size() == 0) {
1315         return false;
1316     }
1317 
1318     if (IsStringMonoBuiltins()) {
1319         return true;
1320     }
1321 
1322     for (size_t i = 0; i < types_.size(); i++) {
1323         if (!types_[i].IsBuiltinsType()) {
1324             return false;
1325         }
1326         if (types_[i].GetBuiltinsType() != types_[0].GetBuiltinsType()) {
1327             return false;
1328         }
1329     }
1330     return true;
1331 }
1332 
FetchBuiltinsTypes()1333 void AccBuiltinObjTypeInfoAccessor::FetchBuiltinsTypes()
1334 {
1335     const PGORWOpType *pgoTypes = acc_.TryGetPGOType(gate_).GetPGORWOpType();
1336     if (IsMegaType(pgoTypes)) {
1337         return;
1338     }
1339     for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) {
1340         auto temp = pgoTypes->GetObjectInfo(i);
1341         if (temp.GetReceiverType().IsBuiltinsType()) {
1342             if (CheckDuplicatedBuiltinType(temp.GetReceiverType())) {
1343                 continue;
1344             }
1345             types_.emplace_back(temp.GetReceiverType());
1346         } else if (temp.GetReceiverType().IsGlobalsType()) {
1347             types_.emplace_back(temp.GetReceiverType());
1348         } else if (temp.GetReceiverType().IsInvalidType()) {
1349             types_.emplace_back(temp.GetReceiverType());
1350         }
1351     }
1352 }
1353 
CheckDuplicatedBuiltinType(ProfileType newType) const1354 bool AccBuiltinObjTypeInfoAccessor::CheckDuplicatedBuiltinType(ProfileType newType) const
1355 {
1356     for (auto &type : types_) {
1357         if (type.IsBuiltinsType() && type.GetBuiltinsType() == newType.GetBuiltinsType()) {
1358             if (type.IsBuiltinsArray()) {
1359                 // When array elementsKind switch on, we should check elementsKind too.
1360                 return (type.GetElementsKindBeforeTransition() == newType.GetElementsKindBeforeTransition() &&
1361                     type.GetElementsKindAfterTransition() == newType.GetElementsKindAfterTransition());
1362             }
1363             return true;
1364         }
1365     }
1366     return false;
1367 }
1368 
StoreBuiltinObjTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,Chunk * chunk)1369 StoreBuiltinObjTypeInfoAccessor::StoreBuiltinObjTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit,
1370                                                                  GateRef gate, Chunk *chunk)
1371     : AccBuiltinObjTypeInfoAccessor(env, circuit, gate, chunk, AccessMode::STORE)
1372 {
1373     EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
1374     switch (ecmaOpcode) {
1375         case EcmaOpcode::STOWNBYINDEX_IMM8_V8_IMM16:
1376         case EcmaOpcode::STOWNBYINDEX_IMM16_V8_IMM16:
1377         case EcmaOpcode::STOBJBYINDEX_IMM8_V8_IMM16:
1378         case EcmaOpcode::STOBJBYINDEX_IMM16_V8_IMM16:
1379         case EcmaOpcode::WIDE_STOBJBYINDEX_PREF_V8_IMM32: {
1380             key_ = acc_.GetValueIn(gate, 0); // 0: key
1381             receiver_ = acc_.GetValueIn(gate, 1);  // 1: receiver
1382             value_ = acc_.GetValueIn(gate, 2); // 2: value
1383             break;
1384         }
1385         case EcmaOpcode::STOBJBYVALUE_IMM8_V8_V8:
1386         case EcmaOpcode::STOBJBYVALUE_IMM16_V8_V8: {
1387             receiver_ = acc_.GetValueIn(gate, 1);  // 1: receiver
1388             key_ = acc_.GetValueIn(gate, 2);   // 2: key
1389             value_ = acc_.GetValueIn(gate, 3);     // 3: value
1390             break;
1391         }
1392         default:
1393             UNREACHABLE();
1394     }
1395     FetchBuiltinsTypes();
1396 }
1397 
CreateObjWithBufferTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,const CString & recordName,Chunk * chunk)1398 CreateObjWithBufferTypeInfoAccessor::CreateObjWithBufferTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit,
1399                                                                          GateRef gate, const CString &recordName,
1400                                                                          Chunk *chunk)
1401     : TypeInfoAccessor(env, circuit, gate), recordName_(recordName)
1402 {
1403     ASSERT(acc_.GetNumValueIn(gate) == 2);  // 2: number of value ins
1404     index_ = acc_.GetValueIn(gate, 0);
1405     if (IsAot()) {
1406         strategy_ = chunk->New<AotAccessorStrategy>(*this);
1407     } else {
1408         strategy_ = chunk->New<JitAccessorStrategy>(*this);
1409     }
1410 }
1411 
GetObject() const1412 JSTaggedValue CreateObjWithBufferTypeInfoAccessor::GetObject() const
1413 {
1414     auto imm = acc_.GetConstantValue(index_);
1415     auto methodOffset = acc_.TryGetMethodOffset(GetGate());
1416     JSTaggedValue unsharedCp = compilationEnv_->FindOrCreateUnsharedConstpool(methodOffset);
1417     if (unsharedCp.IsUndefined()) {
1418         return JSTaggedValue::Undefined();
1419     }
1420     return compilationEnv_->GetObjectLiteralFromCache(unsharedCp, imm, recordName_);
1421 }
1422 
GetHClass() const1423 JSTaggedValue CreateObjWithBufferTypeInfoAccessor::AotAccessorStrategy::GetHClass() const
1424 {
1425     JSTaggedValue obj = parent_.GetObject();
1426     if (obj.IsUndefined()) {
1427         return JSTaggedValue::Undefined();
1428     }
1429     auto sampleType = parent_.acc_.TryGetPGOType(parent_.gate_).GetPGODefineOpType();
1430     auto type = std::make_pair(sampleType->GetProfileType(), sampleType->GetProfileType());
1431     int hclassIndex = static_cast<int>(parent_.ptManager_->GetHClassIndexByProfileType(type));
1432 
1433     JSObject *jsObj = JSObject::Cast(obj);
1434     JSHClass *oldClass = jsObj->GetClass();
1435     JSThread *thread = parent_.compilationEnv_->GetJSThread();
1436     if (hclassIndex == -1) {
1437         if (jsObj->ElementsAndPropertiesIsEmpty(thread)) {
1438             return JSTaggedValue(oldClass);
1439         }
1440         return JSTaggedValue::Undefined();
1441     }
1442     JSTaggedValue newClass = parent_.ptManager_->QueryHClass(type.first, type.second);
1443     if (!newClass.IsJSHClass()) {
1444         return JSTaggedValue::Undefined();
1445     }
1446     if (oldClass->GetInlinedProperties() != JSHClass::Cast(newClass.GetTaggedObject())->GetInlinedProperties()) {
1447         return JSTaggedValue::Undefined();
1448     }
1449     return newClass;
1450 }
1451 
GetHClass() const1452 JSTaggedValue CreateObjWithBufferTypeInfoAccessor::JitAccessorStrategy::GetHClass() const
1453 {
1454     JSTaggedValue obj = parent_.GetObject();
1455     if (obj.IsUndefined()) {
1456         return JSTaggedValue::Undefined();
1457     }
1458     auto sampleType = parent_.acc_.TryGetPGOType(parent_.gate_).GetPGODefineOpType();
1459     if (sampleType->IsNone()) {
1460         return JSTaggedValue::Undefined();
1461     }
1462     JSObject *jsObj = JSObject::Cast(obj);
1463     JSHClass *oldClass = jsObj->GetClass();
1464     JSHClass *newClass = sampleType->GetReceiver();
1465     JSThread *thread = parent_.compilationEnv_->GetJSThread();
1466     if (newClass == nullptr) {
1467         if (jsObj->ElementsAndPropertiesIsEmpty(thread)) {
1468             return JSTaggedValue(oldClass);
1469         }
1470         return JSTaggedValue::Undefined();
1471     }
1472     if (oldClass->GetInlinedProperties() != newClass->GetInlinedProperties()) {
1473         return JSTaggedValue::Undefined();
1474     }
1475     return JSTaggedValue(newClass);
1476 }
1477 
1478 }  // namespace panda::ecmascript::kungfu
1479