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