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