• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "optimizer/ir/analysis.h"
17 #include "optimizer/ir/basicblock.h"
18 #include "optimizer/ir/graph.h"
19 #include "optimizer/analysis/alias_visitor.h"
20 #include "compiler_logger.h"
21 
22 namespace ark::compiler {
23 
Dump(std::ostream * out) const24 void PointerOffset::Dump(std::ostream *out) const
25 {
26     switch (type_) {
27         case STATIC_FIELD:
28             (*out) << "SF #" << imm_;
29             break;
30         case POOL_CONSTANT:
31             (*out) << "PC #" << imm_;
32             break;
33         case OBJECT_FIELD:
34             (*out) << "#" << imm_;
35             break;
36         case ARRAY_ELEMENT:
37         case RAW_OFFSET:
38             (*out) << "[" << imm_ << "]";
39             break;
40         case UNKNOWN_OFFSET:
41             if (*this == CreateDefaultField()) {
42                 (*out) << "DEFAULT";
43             } else if (*this == CreateUnknownOffset()) {
44                 (*out) << "UNKNOWN";
45             } else {
46                 UNREACHABLE();
47             }
48             break;
49         case DICTIONARY_ELEMENT:
50         case OBJECT:
51             UNREACHABLE();
52         default:
53             UNREACHABLE();
54     }
55 }
56 
operator <<(std::ostream & out,const PointerOffset & p)57 std::ostream &operator<<(std::ostream &out, const PointerOffset &p)
58 {
59     p.Dump(&out);
60     return out;
61 }
62 
Dump(std::ostream * out) const63 void Pointer::Dump(std::ostream *out) const
64 {
65     switch (GetType()) {
66         case OBJECT:
67             (*out) << "v" << base_->GetId();
68             break;
69         case STATIC_FIELD:
70             (*out) << "SF #" << GetImm();
71             break;
72         case POOL_CONSTANT:
73             (*out) << "PC #" << GetImm();
74             break;
75         case OBJECT_FIELD:
76             (*out) << "v" << base_->GetId() << " #" << GetImm();
77             break;
78         case ARRAY_ELEMENT:
79         case RAW_OFFSET:
80             (*out) << "v" << base_->GetId() << "[";
81             if (idx_ != nullptr) {
82                 (*out) << "v" << idx_->GetId();
83                 if (GetImm() != 0) {
84                     (*out) << "+" << GetImm();
85                 }
86             } else {
87                 (*out) << GetImm();
88             }
89             (*out) << "]";
90             break;
91         case DICTIONARY_ELEMENT:
92             ASSERT(idx_ != nullptr);
93             (*out) << "v" << base_->GetId() << "[";
94             (*out) << "v" << idx_->GetId();
95             if (GetImm() != 0) {
96                 (*out) << "#NAME";
97             } else {
98                 (*out) << "#INDEX";
99             }
100             (*out) << "]";
101             break;
102         case UNKNOWN_OFFSET:
103             (*out) << "v" << base_->GetId() << " #?";
104             break;
105         default:
106             UNREACHABLE();
107     }
108 }
109 
IsNotEscapingAlias() const110 bool Pointer::IsNotEscapingAlias() const
111 {
112     return GetBase() != nullptr && !IsEscapingAlias(GetBase());
113 }
114 
IsLocalCreatedAlias() const115 bool Pointer::IsLocalCreatedAlias() const
116 {
117     if (base_ == nullptr || base_->GetType() == DataType::POINTER) {
118         return false;
119     }
120     if (!base_->IsReferenceOrAny()) {
121         ASSERT(base_->GetBasicBlock()->GetGraph()->IsDynamicMethod() || base_->IsConst());
122         // primitive tagged value or null const
123         return true;
124     }
125     switch (base_->GetOpcode()) {
126         case Opcode::NullPtr:
127             return true;
128         case Opcode::NewArray:
129         case Opcode::MultiArray:
130         case Opcode::NewObject:
131         case Opcode::InitObject:
132         case Opcode::InitEmptyString:
133         case Opcode::InitString:
134             return true;
135         case Opcode::NullCheck:
136         case Opcode::ObjByIndexCheck:
137             UNREACHABLE();
138             /* fall-through */
139         default:
140             return false;
141     }
142 }
143 
operator <<(std::ostream & out,const Pointer & p)144 std::ostream &operator<<(std::ostream &out, const Pointer &p)
145 {
146     p.Dump(&out);
147     return out;
148 }
149 
150 /**
151  * Returns true if a reference escapes the scope of current function:
152  * Various function calls, constructors and stores to another objects' fields, arrays
153  */
154 /* static */
155 // CC-OFFNXT(huge_method[C++], huge_cyclomatic_complexity[C++], G.FUN.01-CPP) big switch case
IsEscapingAlias(const Inst * inst)156 bool Pointer::IsEscapingAlias(const Inst *inst)
157 {
158     if (!inst->IsReferenceOrAny()) {
159         return false;
160     }
161     for (auto &user : inst->GetUsers()) {
162         auto userInst = user.GetInst();
163         if (userInst->GetType() == DataType::POINTER) {
164             return true;
165         }
166         switch (user.GetInst()->GetOpcode()) {
167             case Opcode::RefTypeCheck:
168                 if (user.GetIndex() == 0) {
169                     break;
170                 }
171                 [[fallthrough]];
172             case Opcode::NullCheck:
173             case Opcode::ObjByIndexCheck:
174             case Opcode::AnyTypeCheck:
175                 if (IsEscapingAlias(userInst)) {
176                     return true;
177                 }
178                 break;
179             // Currently unhandled
180             case Opcode::Store:
181             case Opcode::StoreNative:
182             case Opcode::StoreI:
183                 if (user.GetIndex() != 0) {
184                     return true;
185                 }
186                 break;
187             case Opcode::StoreObject:
188             case Opcode::StoreObjectPair:
189             case Opcode::StoreArray:
190             case Opcode::StoreArrayI:
191             case Opcode::StoreArrayPair:
192             case Opcode::StoreArrayPairI:
193             case Opcode::StoreObjectDynamic:
194                 // Propagate isLocal from base and aliased insts
195                 break;
196             case Opcode::StoreStatic:
197             case Opcode::StoreResolvedObjectField:
198             case Opcode::StoreResolvedObjectFieldStatic:
199             case Opcode::UnresolvedStoreStatic:
200             case Opcode::InitObject:
201             case Opcode::InitClass:
202             case Opcode::LoadAndInitClass:
203             case Opcode::UnresolvedLoadAndInitClass:
204             case Opcode::GetGlobalVarAddress:
205             case Opcode::CallStatic:
206             case Opcode::CallResolvedStatic:
207             case Opcode::CallVirtual:
208             case Opcode::CallResolvedVirtual:
209             case Opcode::CallDynamic:
210             case Opcode::Call:
211             case Opcode::Bitcast:
212             case Opcode::Cast:
213                 return true;
214             case Opcode::CallNative:
215                 if (inst->IsRuntimeCall()) {
216                     return true;
217                 }
218                 break;
219             case Opcode::Intrinsic:
220                 // if intrinsic has no side effects and has primitive type, it
221                 //  does not move ref inputs anywhere
222                 if (!inst->IsNotRemovable() && !inst->IsReferenceOrAny()) {
223                     return true;
224                 }
225                 break;
226             case Opcode::CheckCast:
227             case Opcode::HclassCheck:
228             case Opcode::IsInstance:
229             case Opcode::Compare:
230             case Opcode::CompareAnyType:
231             case Opcode::DeoptimizeCompare:
232             case Opcode::DeoptimizeCompareImm:
233             case Opcode::Return:
234             case Opcode::LiveOut:
235             case Opcode::Throw:
236             case Opcode::LenArray:
237             case Opcode::InitString:
238             case Opcode::IfImm:
239             case Opcode::If:
240             case Opcode::ResolveVirtual:
241             case Opcode::Monitor:
242             case Opcode::FillConstArray:
243             case Opcode::GetInstanceClass:
244             case Opcode::ResolveByName:
245                 break;
246             case Opcode::Phi:
247             case Opcode::CatchPhi:
248             case Opcode::Select:
249             case Opcode::SelectImm:
250             case Opcode::CastValueToAnyType:
251             case Opcode::CastAnyTypeValue:
252                 // Propagate isLocal from users
253                 break;
254             case Opcode::NewArray:
255             case Opcode::NewObject:
256             case Opcode::MultiArray:
257                 ASSERT(user.GetIndex() == 0);  // class input
258                 break;
259             default:
260                 ASSERT_DO(userInst->IsLoad() || userInst->IsSaveState(),
261                           (std::cerr << "unknown user: " << *userInst << std::endl,
262                            inst->GetBasicBlock()->GetGraph()->Dump(&std::cerr)));
263         }
264     }
265     return false;
266 }
267 
GetDynamicAccessPointer(Inst * inst,Inst * base,DynObjectAccessType type,DynObjectAccessMode mode)268 static Pointer GetDynamicAccessPointer(Inst *inst, Inst *base, DynObjectAccessType type, DynObjectAccessMode mode)
269 {
270     if (type == DynObjectAccessType::UNKNOWN || mode == DynObjectAccessMode::UNKNOWN) {
271         return Pointer::CreateUnknownOffset(base);
272     }
273 
274     Inst *idx = inst->GetDataFlowInput(1);
275     uint64_t imm = 0;
276     if (type == DynObjectAccessType::BY_NAME) {
277         ASSERT_DO(mode != DynObjectAccessMode::ARRAY,
278                   (std::cerr << "Unexpected access type BY_NAME for access mode ARRAY: ", inst->Dump(&std::cerr)));
279         imm = UINT64_MAX;
280     } else {
281         ASSERT_DO(type == DynObjectAccessType::BY_INDEX,
282                   (std::cerr << "Unsupported dynamic access type in alias analysis: ", inst->Dump(&std::cerr)));
283     }
284     if (mode == DynObjectAccessMode::ARRAY) {
285         return Pointer::CreateArrayElement(base, idx, imm);
286     }
287     ASSERT_DO(mode == DynObjectAccessMode::DICTIONARY,
288               (std::cerr << "Unsupported dynamic access mode in alias analysis: ", inst->Dump(&std::cerr)));
289     return Pointer::CreateDictionaryElement(base, idx, imm);
290 }
291 
ParseArrayElement(Inst * inst)292 static Pointer ParseArrayElement(Inst *inst)
293 {
294     uint32_t imm = 0;
295     Inst *offset = nullptr;
296     switch (inst->GetOpcode()) {
297         case Opcode::LoadArray:
298         case Opcode::StoreArray:
299             offset = inst->GetDataFlowInput(1);
300             break;
301         case Opcode::LoadArrayI:
302             imm = inst->CastToLoadArrayI()->GetImm();
303             break;
304         case Opcode::StoreArrayI:
305             imm = inst->CastToStoreArrayI()->GetImm();
306             break;
307         default:
308             UNREACHABLE();
309     }
310     auto base = inst->GetDataFlowInput(0);
311     return Pointer::CreateArrayElement(base, offset, imm);
312 }
313 
ParsePoolConstant(Inst * inst)314 static Pointer ParsePoolConstant(Inst *inst)
315 {
316     uint32_t typeId = 0;
317     switch (inst->GetOpcode()) {
318         case Opcode::LoadString:
319             typeId = inst->CastToLoadString()->GetTypeId();
320             break;
321         case Opcode::LoadType:
322             typeId = inst->CastToLoadType()->GetTypeId();
323             break;
324         case Opcode::UnresolvedLoadType:
325             typeId = inst->CastToUnresolvedLoadType()->GetTypeId();
326             break;
327         default:
328             UNREACHABLE();
329     }
330     return Pointer::CreatePoolConstant(typeId);
331 }
332 
ParseStaticField(Inst * inst)333 static Pointer ParseStaticField(Inst *inst)
334 {
335     uint32_t typeId = 0;
336     void *typePtr = nullptr;
337     switch (inst->GetOpcode()) {
338         case Opcode::LoadStatic:
339             typeId = inst->CastToLoadStatic()->GetTypeId();
340             typePtr = inst->CastToLoadStatic()->GetObjField();
341             break;
342         case Opcode::LoadResolvedObjectFieldStatic:
343             typeId = inst->CastToLoadResolvedObjectFieldStatic()->GetTypeId();
344             break;
345         case Opcode::StoreStatic:
346             typeId = inst->CastToStoreStatic()->GetTypeId();
347             typePtr = inst->CastToStoreStatic()->GetObjField();
348             break;
349         case Opcode::UnresolvedStoreStatic:
350             typeId = inst->CastToUnresolvedStoreStatic()->GetTypeId();
351             break;
352         case Opcode::StoreResolvedObjectFieldStatic:
353             typeId = inst->CastToStoreResolvedObjectFieldStatic()->GetTypeId();
354             break;
355         default:
356             UNREACHABLE();
357     }
358     return Pointer::CreateStaticField(typeId, typePtr);
359 }
360 
ParseObjectField(Inst * inst)361 static Pointer ParseObjectField(Inst *inst)
362 {
363     uint32_t typeId = 0;
364     void *typePtr = nullptr;
365     bool isStatic = false;
366     switch (inst->GetOpcode()) {
367         case Opcode::LoadObject:
368             isStatic = inst->CastToLoadObject()->GetObjectType() == ObjectType::MEM_STATIC;
369             typeId = inst->CastToLoadObject()->GetTypeId();
370             typePtr = inst->CastToLoadObject()->GetObjField();
371             break;
372         case Opcode::LoadResolvedObjectField:
373             typeId = inst->CastToLoadResolvedObjectField()->GetTypeId();
374             break;
375         case Opcode::StoreObject:
376             isStatic = inst->CastToStoreObject()->GetObjectType() == ObjectType::MEM_STATIC;
377             typeId = inst->CastToStoreObject()->GetTypeId();
378             typePtr = inst->CastToStoreObject()->GetObjField();
379             break;
380         case Opcode::StoreResolvedObjectField:
381             typeId = inst->CastToStoreResolvedObjectField()->GetTypeId();
382             break;
383         default:
384             UNREACHABLE();
385     }
386     auto base = inst->GetDataFlowInput(0);
387     return isStatic ? Pointer::CreateStaticField(typeId, typePtr) : Pointer::CreateObjectField(base, typeId, typePtr);
388 }
389 
ParseDynamicField(Inst * inst)390 static Pointer ParseDynamicField(Inst *inst)
391 {
392     auto base = inst->GetDataFlowInput(0);
393 
394     DynObjectAccessType type;
395     DynObjectAccessMode mode;
396     switch (inst->GetOpcode()) {
397         case Opcode::LoadObjectDynamic:
398             type = inst->CastToLoadObjectDynamic()->GetAccessType();
399             mode = inst->CastToLoadObjectDynamic()->GetAccessMode();
400             break;
401         case Opcode::StoreObjectDynamic:
402             type = inst->CastToStoreObjectDynamic()->GetAccessType();
403             mode = inst->CastToStoreObjectDynamic()->GetAccessMode();
404             break;
405         default:
406             UNREACHABLE();
407     }
408 
409     return GetDynamicAccessPointer(inst, base, type, mode);
410 }
411 
412 /// Selects the address from instruction that should be checked on alias
ParseInstruction(Inst * inst,Pointer * pointer)413 bool AliasVisitor::ParseInstruction(Inst *inst, Pointer *pointer)
414 {
415     Pointer p {};
416     switch (inst->GetOpcode()) {
417         case Opcode::LoadArray:
418         case Opcode::LoadArrayI:
419         case Opcode::StoreArray:
420         case Opcode::StoreArrayI:
421             p = ParseArrayElement(inst);
422             break;
423         case Opcode::LoadString:
424         case Opcode::LoadType:
425         case Opcode::UnresolvedLoadType:
426             p = ParsePoolConstant(inst);
427             break;
428         case Opcode::LoadStatic:
429         case Opcode::StoreStatic:
430         case Opcode::UnresolvedStoreStatic:
431         case Opcode::LoadResolvedObjectFieldStatic:
432         case Opcode::StoreResolvedObjectFieldStatic:
433             p = ParseStaticField(inst);
434             break;
435         case Opcode::LoadObject:
436         case Opcode::StoreObject:
437         case Opcode::LoadResolvedObjectField:
438         case Opcode::StoreResolvedObjectField:
439             p = ParseObjectField(inst);
440             break;
441         case Opcode::LoadObjectDynamic:
442         case Opcode::StoreObjectDynamic:
443             p = ParseDynamicField(inst);
444             break;
445         default:
446             return false;
447     }
448 
449     auto base = p.GetBase();
450     if (base != nullptr) {
451         // Currently unhandled and return always MAY_ALIAS
452         if (base->GetOpcode() == Opcode::LoadArrayPair || base->GetOpcode() == Opcode::LoadArrayPairI ||
453             base->GetOpcode() == Opcode::LoadPairPart || base->GetOpcode() == Opcode::CatchPhi ||
454             base->GetOpcode() == Opcode::Load || base->GetOpcode() == Opcode::LoadI ||
455             base->GetOpcode() == Opcode::Store || base->GetOpcode() == Opcode::StoreI) {
456             return false;
457         }
458         ASSERT(base->IsDominate(inst));
459     }
460 
461     *pointer = p;
462     return true;
463 }
464 
Init(ArenaAllocator * allocator)465 void AliasVisitor::Init(ArenaAllocator *allocator)
466 {
467     inputsSet_ = allocator->New<ArenaSet<Inst *>>(allocator->Adapter());
468     ASSERT(inputsSet_ != nullptr);
469 }
470 
471 /// Instructions that definitely are not an alias of anything.
VisitNullPtr(GraphVisitor * v,Inst * inst)472 void AliasVisitor::VisitNullPtr(GraphVisitor *v, Inst *inst)
473 {
474     static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
475 }
VisitLoadUniqueObject(GraphVisitor * v,Inst * inst)476 void AliasVisitor::VisitLoadUniqueObject(GraphVisitor *v, Inst *inst)
477 {
478     static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
479 }
VisitLoadUndefined(GraphVisitor * v,Inst * inst)480 void AliasVisitor::VisitLoadUndefined(GraphVisitor *v, Inst *inst)
481 {
482     static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
483 }
VisitInitObject(GraphVisitor * v,Inst * inst)484 void AliasVisitor::VisitInitObject(GraphVisitor *v, Inst *inst)
485 {
486     static_cast<AliasVisitor *>(v)->VisitAllocation(inst);
487 }
VisitNewObject(GraphVisitor * v,Inst * inst)488 void AliasVisitor::VisitNewObject(GraphVisitor *v, Inst *inst)
489 {
490     static_cast<AliasVisitor *>(v)->VisitAllocation(inst);
491 }
VisitNewArray(GraphVisitor * v,Inst * inst)492 void AliasVisitor::VisitNewArray(GraphVisitor *v, Inst *inst)
493 {
494     static_cast<AliasVisitor *>(v)->VisitAllocation(inst);
495 }
VisitMultiArray(GraphVisitor * v,Inst * inst)496 void AliasVisitor::VisitMultiArray(GraphVisitor *v, Inst *inst)
497 {
498     static_cast<AliasVisitor *>(v)->VisitAllocation(inst);
499 }
VisitInitEmptyString(GraphVisitor * v,Inst * inst)500 void AliasVisitor::VisitInitEmptyString(GraphVisitor *v, Inst *inst)
501 {
502     static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
503 }
VisitInitString(GraphVisitor * v,Inst * inst)504 void AliasVisitor::VisitInitString(GraphVisitor *v, Inst *inst)
505 {
506     static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
507 }
508 
509 /**
510  * Instructions that can introduce references that are an alias of
511  * something already existed.
512  */
VisitConstant(GraphVisitor * v,Inst * inst)513 void AliasVisitor::VisitConstant(GraphVisitor *v, Inst *inst)
514 {
515     if (inst->IsReferenceOrAny()) {
516         static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
517     }
518 }
VisitParameter(GraphVisitor * v,Inst * inst)519 void AliasVisitor::VisitParameter(GraphVisitor *v, Inst *inst)
520 {
521     if (inst->IsReferenceOrAny()) {
522         static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
523     }
524 }
VisitLiveIn(GraphVisitor * v,Inst * inst)525 void AliasVisitor::VisitLiveIn(GraphVisitor *v, Inst *inst)
526 {
527     if (inst->IsReferenceOrAny()) {
528         static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
529     }
530 }
VisitLoadImmediate(GraphVisitor * v,Inst * inst)531 void AliasVisitor::VisitLoadImmediate(GraphVisitor *v, Inst *inst)
532 {
533     if (inst->IsReferenceOrAny()) {
534         static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
535     }
536 }
VisitBitcast(GraphVisitor * v,Inst * inst)537 void AliasVisitor::VisitBitcast(GraphVisitor *v, Inst *inst)
538 {
539     if (inst->IsReferenceOrAny()) {
540         static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
541     }
542 }
543 
VisitIntrinsic(GraphVisitor * v,Inst * inst)544 void AliasVisitor::VisitIntrinsic(GraphVisitor *v, Inst *inst)
545 {
546     if (inst->IsReferenceOrAny()) {
547         static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
548     }
549     if (inst->GetFlag(inst_flags::HEAP_INV)) {
550         // NB: we assume that for not HEAP_INV intrinsics their inputs don't escape
551         static_cast<AliasVisitor *>(v)->EscapeInputsAndInv(inst);
552     }
553 }
554 
VisitBuiltin(GraphVisitor * v,Inst * inst)555 void AliasVisitor::VisitBuiltin(GraphVisitor *v, Inst *inst)
556 {
557     VisitCall(v, inst);
558 }
VisitCallStatic(GraphVisitor * v,Inst * inst)559 void AliasVisitor::VisitCallStatic(GraphVisitor *v, Inst *inst)
560 {
561     VisitCall(v, inst);
562 }
VisitCallResolvedStatic(GraphVisitor * v,Inst * inst)563 void AliasVisitor::VisitCallResolvedStatic(GraphVisitor *v, Inst *inst)
564 {
565     VisitCall(v, inst);
566 }
VisitCallVirtual(GraphVisitor * v,Inst * inst)567 void AliasVisitor::VisitCallVirtual(GraphVisitor *v, Inst *inst)
568 {
569     VisitCall(v, inst);
570 }
VisitCallResolvedVirtual(GraphVisitor * v,Inst * inst)571 void AliasVisitor::VisitCallResolvedVirtual(GraphVisitor *v, Inst *inst)
572 {
573     VisitCall(v, inst);
574 }
VisitCallDynamic(GraphVisitor * v,Inst * inst)575 void AliasVisitor::VisitCallDynamic(GraphVisitor *v, Inst *inst)
576 {
577     VisitCall(v, inst);
578 }
VisitCallNative(GraphVisitor * v,Inst * inst)579 void AliasVisitor::VisitCallNative(GraphVisitor *v, Inst *inst)
580 {
581     VisitCall(v, inst);
582 }
VisitCall(GraphVisitor * v,Inst * inst)583 void AliasVisitor::VisitCall(GraphVisitor *v, Inst *inst)
584 {
585     if (static_cast<CallInst *>(inst)->IsInlined()) {
586         ASSERT(inst->GetUsers().Empty());
587         return;
588     }
589     if (inst->IsReferenceOrAny()) {
590         static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
591     }
592     static_cast<AliasVisitor *>(v)->EscapeInputsAndInv(inst);
593 }
594 
VisitGetManagedClassObject(GraphVisitor * v,Inst * inst)595 void AliasVisitor::VisitGetManagedClassObject(GraphVisitor *v, Inst *inst)
596 {
597     if (inst->IsReferenceOrAny()) {
598         static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
599     }
600 }
VisitResolveObjectFieldStatic(GraphVisitor * v,Inst * inst)601 void AliasVisitor::VisitResolveObjectFieldStatic(GraphVisitor *v, Inst *inst)
602 {
603     if (inst->IsReferenceOrAny()) {
604         static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
605     }
606 }
607 
608 /// Instructions that introduce static fields (global variables).
VisitLoadStatic(GraphVisitor * v,Inst * inst)609 void AliasVisitor::VisitLoadStatic(GraphVisitor *v, Inst *inst)
610 {
611     if (!inst->IsReferenceOrAny()) {
612         return;
613     }
614     auto visitor = static_cast<AliasVisitor *>(v);
615     auto typedInst = inst->CastToLoadStatic();
616     uint32_t typeId = typedInst->GetTypeId();
617     Pointer sfield = Pointer::CreateStaticField(typeId, typedInst->GetObjField());
618 
619     visitor->SetVolatile(sfield, inst);
620 
621     visitor->AddDirectEdge(sfield);
622     visitor->AddCopyEdge(sfield, Pointer::CreateObject(inst));
623 }
624 
VisitLoadResolvedObjectFieldStatic(GraphVisitor * v,Inst * inst)625 void AliasVisitor::VisitLoadResolvedObjectFieldStatic(GraphVisitor *v, Inst *inst)
626 {
627     if (!inst->IsReferenceOrAny()) {
628         return;
629     }
630     auto visitor = static_cast<AliasVisitor *>(v);
631     auto typedInst = inst->CastToLoadResolvedObjectFieldStatic();
632     uint32_t typeId = typedInst->GetTypeId();
633     Pointer sfield = Pointer::CreateStaticField(typeId);
634 
635     visitor->SetVolatile(sfield, inst);
636 
637     visitor->AddDirectEdge(sfield);
638     visitor->AddCopyEdge(sfield, Pointer::CreateObject(inst));
639 }
640 
VisitStoreStatic(GraphVisitor * v,Inst * inst)641 void AliasVisitor::VisitStoreStatic(GraphVisitor *v, Inst *inst)
642 {
643     if (!inst->IsReferenceOrAny()) {
644         return;
645     }
646     auto visitor = static_cast<AliasVisitor *>(v);
647     auto typedInst = inst->CastToStoreStatic();
648     uint32_t typeId = typedInst->GetTypeId();
649     Pointer sfield = Pointer::CreateStaticField(typeId, typedInst->GetObjField());
650 
651     visitor->SetVolatile(sfield, inst);
652 
653     visitor->AddDirectEdge(sfield);
654     auto stored = inst->GetDataFlowInput(typedInst->STORED_INPUT_INDEX);
655     visitor->AddCopyEdge(Pointer::CreateObject(stored), sfield);
656     visitor->Escape(stored);
657 }
658 
VisitStoreResolvedObjectFieldStatic(GraphVisitor * v,Inst * inst)659 void AliasVisitor::VisitStoreResolvedObjectFieldStatic(GraphVisitor *v, Inst *inst)
660 {
661     if (inst->GetType() != DataType::REFERENCE) {
662         return;
663     }
664     auto visitor = static_cast<AliasVisitor *>(v);
665     auto typedInst = inst->CastToStoreResolvedObjectFieldStatic();
666     uint32_t typeId = typedInst->GetTypeId();
667     Pointer sfield = Pointer::CreateStaticField(typeId);
668 
669     visitor->SetVolatile(sfield, inst);
670 
671     visitor->AddDirectEdge(sfield);
672     auto stored = inst->GetDataFlowInput(typedInst->STORED_INPUT_INDEX);
673     visitor->AddCopyEdge(Pointer::CreateObject(stored), sfield);
674     visitor->Escape(stored);
675 }
676 
VisitUnresolvedStoreStatic(GraphVisitor * v,Inst * inst)677 void AliasVisitor::VisitUnresolvedStoreStatic(GraphVisitor *v, Inst *inst)
678 {
679     if (!inst->IsReferenceOrAny()) {
680         return;
681     }
682     auto visitor = static_cast<AliasVisitor *>(v);
683     auto typedInst = inst->CastToUnresolvedStoreStatic();
684     uint32_t typeId = typedInst->GetTypeId();
685     Pointer sfield = Pointer::CreateStaticField(typeId);
686 
687     visitor->SetVolatile(sfield, inst);
688 
689     visitor->AddDirectEdge(sfield);
690     auto stored = inst->GetDataFlowInput(typedInst->STORED_INPUT_INDEX);
691     visitor->AddCopyEdge(Pointer::CreateObject(stored), sfield);
692     visitor->Escape(stored);
693 }
694 
695 /// Instructions that introduce unique constant references (global constants).
VisitLoadRuntimeClass(GraphVisitor * v,Inst * inst)696 void AliasVisitor::VisitLoadRuntimeClass(GraphVisitor *v, Inst *inst)
697 {
698     if (inst->IsReferenceOrAny()) {
699         uint32_t typeId = inst->CastToLoadRuntimeClass()->GetTypeId();
700         static_cast<AliasVisitor *>(v)->AddConstantDirectEdge(inst, typeId);
701     }
702 }
703 
VisitLoadClass(GraphVisitor * v,Inst * inst)704 void AliasVisitor::VisitLoadClass(GraphVisitor *v, Inst *inst)
705 {
706     if (inst->IsReferenceOrAny()) {
707         uint32_t typeId = inst->CastToLoadClass()->GetTypeId();
708         static_cast<AliasVisitor *>(v)->AddConstantDirectEdge(inst, typeId);
709     }
710 }
VisitLoadAndInitClass(GraphVisitor * v,Inst * inst)711 void AliasVisitor::VisitLoadAndInitClass(GraphVisitor *v, Inst *inst)
712 {
713     if (inst->IsReferenceOrAny()) {
714         uint32_t typeId = inst->CastToLoadAndInitClass()->GetTypeId();
715         static_cast<AliasVisitor *>(v)->AddConstantDirectEdge(inst, typeId);
716     }
717 }
VisitUnresolvedLoadAndInitClass(GraphVisitor * v,Inst * inst)718 void AliasVisitor::VisitUnresolvedLoadAndInitClass(GraphVisitor *v, Inst *inst)
719 {
720     if (inst->IsReferenceOrAny()) {
721         uint32_t typeId = inst->CastToUnresolvedLoadAndInitClass()->GetTypeId();
722         static_cast<AliasVisitor *>(v)->AddConstantDirectEdge(inst, typeId);
723     }
724 }
VisitGetGlobalVarAddress(GraphVisitor * v,Inst * inst)725 void AliasVisitor::VisitGetGlobalVarAddress(GraphVisitor *v, Inst *inst)
726 {
727     if (inst->IsReferenceOrAny()) {
728         uint32_t typeId = inst->CastToGetGlobalVarAddress()->GetTypeId();
729         static_cast<AliasVisitor *>(v)->AddConstantDirectEdge(inst, typeId);
730     }
731 }
VisitLoadString(GraphVisitor * v,Inst * inst)732 void AliasVisitor::VisitLoadString(GraphVisitor *v, Inst *inst)
733 {
734     if (inst->IsReferenceOrAny()) {
735         uint32_t typeId = inst->CastToLoadString()->GetTypeId();
736         static_cast<AliasVisitor *>(v)->AddConstantDirectEdge(inst, typeId);
737     }
738 }
VisitLoadConstArray(GraphVisitor * v,Inst * inst)739 void AliasVisitor::VisitLoadConstArray(GraphVisitor *v, Inst *inst)
740 {
741     if (inst->IsReferenceOrAny()) {
742         uint32_t typeId = inst->CastToLoadConstArray()->GetTypeId();
743         static_cast<AliasVisitor *>(v)->AddConstantDirectEdge(inst, typeId);
744     }
745 }
VisitLoadType(GraphVisitor * v,Inst * inst)746 void AliasVisitor::VisitLoadType(GraphVisitor *v, Inst *inst)
747 {
748     if (inst->IsReferenceOrAny()) {
749         uint32_t typeId = inst->CastToLoadType()->GetTypeId();
750         static_cast<AliasVisitor *>(v)->AddConstantDirectEdge(inst, typeId);
751     }
752 }
VisitUnresolvedLoadType(GraphVisitor * v,Inst * inst)753 void AliasVisitor::VisitUnresolvedLoadType(GraphVisitor *v, Inst *inst)
754 {
755     if (inst->IsReferenceOrAny()) {
756         uint32_t typeId = inst->CastToUnresolvedLoadType()->GetTypeId();
757         static_cast<AliasVisitor *>(v)->AddConstantDirectEdge(inst, typeId);
758     }
759 }
760 
VisitLoadObjFromConst(GraphVisitor * v,Inst * inst)761 void AliasVisitor::VisitLoadObjFromConst(GraphVisitor *v, Inst *inst)
762 {
763     if (inst->IsReferenceOrAny()) {
764         static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
765     }
766 }
767 
768 /// Instructions that introduce aliases.
VisitLoadArray(GraphVisitor * v,Inst * inst)769 void AliasVisitor::VisitLoadArray(GraphVisitor *v, Inst *inst)
770 {
771     if (!inst->IsReferenceOrAny()) {
772         return;
773     }
774     auto visitor = static_cast<AliasVisitor *>(v);
775     Inst *arr = inst->GetDataFlowInput(0);
776     Inst *idx = inst->GetDataFlowInput(1);
777     Pointer obj = Pointer::CreateObject(arr);
778     Pointer elem = Pointer::CreateArrayElement(arr, idx);
779     Pointer val = Pointer::CreateObject(inst);
780 
781     visitor->AddPseudoCopyEdge(obj, elem);
782     visitor->AddCopyEdge(elem, val);
783 }
784 
VisitStoreArray(GraphVisitor * v,Inst * inst)785 void AliasVisitor::VisitStoreArray(GraphVisitor *v, Inst *inst)
786 {
787     if (!inst->IsReferenceOrAny()) {
788         return;
789     }
790     auto visitor = static_cast<AliasVisitor *>(v);
791     Inst *arr = inst->GetDataFlowInput(0);
792     Inst *idx = inst->GetDataFlowInput(1);
793     Pointer obj = Pointer::CreateObject(arr);
794     Pointer elem = Pointer::CreateArrayElement(arr, idx);
795     Pointer val = Pointer::CreateObject(inst->GetDataFlowInput(2U));
796 
797     visitor->AddPseudoCopyEdge(obj, elem);
798     visitor->AddCopyEdge(val, elem);
799 }
800 
VisitLoadArrayI(GraphVisitor * v,Inst * inst)801 void AliasVisitor::VisitLoadArrayI(GraphVisitor *v, Inst *inst)
802 {
803     if (!inst->IsReferenceOrAny()) {
804         return;
805     }
806     auto visitor = static_cast<AliasVisitor *>(v);
807     Inst *arr = inst->GetDataFlowInput(0);
808     Pointer obj = Pointer::CreateObject(arr);
809     Pointer elem = Pointer::CreateArrayElement(arr, nullptr, inst->CastToLoadArrayI()->GetImm());
810     Pointer val = Pointer::CreateObject(inst);
811 
812     visitor->AddPseudoCopyEdge(obj, elem);
813     visitor->AddCopyEdge(elem, val);
814 }
815 
VisitStoreArrayI(GraphVisitor * v,Inst * inst)816 void AliasVisitor::VisitStoreArrayI(GraphVisitor *v, Inst *inst)
817 {
818     if (!inst->IsReferenceOrAny()) {
819         return;
820     }
821     auto visitor = static_cast<AliasVisitor *>(v);
822     Inst *arr = inst->GetDataFlowInput(0);
823     Pointer obj = Pointer::CreateObject(arr);
824     Pointer elem = Pointer::CreateArrayElement(arr, nullptr, inst->CastToStoreArrayI()->GetImm());
825     Pointer val = Pointer::CreateObject(inst->GetDataFlowInput(1));
826 
827     visitor->AddPseudoCopyEdge(obj, elem);
828     visitor->AddCopyEdge(val, elem);
829 }
830 
VisitLoadArrayPair(GraphVisitor * v,Inst * inst)831 void AliasVisitor::VisitLoadArrayPair(GraphVisitor *v, Inst *inst)
832 {
833     if (!inst->IsReferenceOrAny()) {
834         return;
835     }
836     auto visitor = static_cast<AliasVisitor *>(v);
837     auto *load = inst->CastToLoadArrayPair();
838     Inst *arr = load->GetDataFlowInput(load->GetArray());
839     Pointer obj = Pointer::CreateObject(arr);
840     for (auto &user : load->GetUsers()) {
841         ASSERT(user.GetInst()->GetOpcode() == Opcode::LoadPairPart);
842         auto uinst = user.GetInst()->CastToLoadPairPart();
843 
844         Pointer elem = Pointer::CreateArrayElement(arr, load->GetIndex(), uinst->GetImm());
845         Pointer val = Pointer::CreateObject(uinst);
846         visitor->AddPseudoCopyEdge(obj, elem);
847         visitor->AddCopyEdge(elem, val);
848         visitor->AddCopyEdge(elem, Pointer::CreateObject(load));
849     }
850 }
851 
VisitStoreArrayPair(GraphVisitor * v,Inst * inst)852 void AliasVisitor::VisitStoreArrayPair(GraphVisitor *v, Inst *inst)
853 {
854     if (!inst->IsReferenceOrAny()) {
855         return;
856     }
857     auto visitor = static_cast<AliasVisitor *>(v);
858     auto *store = inst->CastToStoreArrayPair();
859     Inst *arr = store->GetDataFlowInput(store->GetArray());
860     Pointer obj = Pointer::CreateObject(arr);
861     Pointer elFst = Pointer::CreateArrayElement(arr, store->GetIndex());
862     Pointer elSnd = Pointer::CreateArrayElement(arr, store->GetIndex(), 1);
863     Pointer valFst = Pointer::CreateObject(store->GetDataFlowInput(store->GetStoredValue(0)));
864     Pointer valSnd = Pointer::CreateObject(store->GetDataFlowInput(store->GetStoredValue(1)));
865 
866     visitor->AddPseudoCopyEdge(obj, elFst);
867     visitor->AddPseudoCopyEdge(obj, elSnd);
868     visitor->AddCopyEdge(valFst, elFst);
869     visitor->AddCopyEdge(valSnd, elSnd);
870 }
871 
VisitLoadObjectPair(GraphVisitor * v,Inst * inst)872 void AliasVisitor::VisitLoadObjectPair(GraphVisitor *v, Inst *inst)
873 {
874     if (!inst->IsReferenceOrAny()) {
875         return;
876     }
877     auto visitor = static_cast<AliasVisitor *>(v);
878     auto typedInst = inst->CastToLoadObjectPair();
879     uint32_t typeId0 = typedInst->GetTypeId0();
880     uint32_t typeId1 = typedInst->GetTypeId1();
881     ASSERT(typedInst->GetObjectType() != ObjectType::MEM_STATIC);
882     Inst *dfobj = inst->GetDataFlowInput(0);
883     Pointer obj = Pointer::CreateObject(dfobj);
884     Pointer field0 = Pointer::CreateObjectField(dfobj, typeId0, typedInst->GetObjField0());
885     Pointer field1 = Pointer::CreateObjectField(dfobj, typeId1, typedInst->GetObjField1());
886 
887     visitor->SetVolatile(field0, inst);
888     visitor->SetVolatile(field1, inst);
889 
890     visitor->AddPseudoCopyEdge(obj, field0);
891     visitor->AddPseudoCopyEdge(obj, field1);
892 
893     for (auto &user : inst->GetUsers()) {
894         ASSERT(user.GetInst()->GetOpcode() == Opcode::LoadPairPart);
895         auto uinst = user.GetInst()->CastToLoadPairPart();
896         const auto &field = uinst->GetImm() == 0 ? field0 : field1;
897         visitor->AddCopyEdge(field, Pointer::CreateObject(user.GetInst()));
898     }
899 }
900 
VisitStoreObjectPair(GraphVisitor * v,Inst * inst)901 void AliasVisitor::VisitStoreObjectPair(GraphVisitor *v, Inst *inst)
902 {
903     if (!inst->IsReferenceOrAny()) {
904         return;
905     }
906     auto visitor = static_cast<AliasVisitor *>(v);
907     auto typedInst = inst->CastToStoreObjectPair();
908     uint32_t typeId0 = typedInst->GetTypeId0();
909     uint32_t typeId1 = typedInst->GetTypeId1();
910     ASSERT(typedInst->GetObjectType() != ObjectType::MEM_STATIC);
911     Inst *dfobj = inst->GetDataFlowInput(0);
912     Pointer obj = Pointer::CreateObject(dfobj);
913     Pointer field0 = Pointer::CreateObjectField(dfobj, typeId0, typedInst->GetObjField0());
914     Pointer val0 = Pointer::CreateObject(inst->GetDataFlowInput(1));
915     Pointer field1 = Pointer::CreateObjectField(dfobj, typeId1, typedInst->GetObjField1());
916     Pointer val1 = Pointer::CreateObject(inst->GetDataFlowInput(2));
917 
918     visitor->SetVolatile(field0, inst);
919     visitor->SetVolatile(field1, inst);
920 
921     visitor->AddPseudoCopyEdge(obj, field0);
922     visitor->AddCopyEdge(val0, field0);
923     visitor->AddPseudoCopyEdge(obj, field1);
924     visitor->AddCopyEdge(val1, field1);
925 }
926 
VisitLoadArrayPairI(GraphVisitor * v,Inst * inst)927 void AliasVisitor::VisitLoadArrayPairI(GraphVisitor *v, Inst *inst)
928 {
929     if (!inst->IsReferenceOrAny()) {
930         return;
931     }
932     auto visitor = static_cast<AliasVisitor *>(v);
933     auto *load = inst->CastToLoadArrayPairI();
934     Inst *arr = load->GetDataFlowInput(load->GetArray());
935     Pointer obj = Pointer::CreateObject(arr);
936     for (auto &user : load->GetUsers()) {
937         ASSERT(user.GetInst()->GetOpcode() == Opcode::LoadPairPart);
938         auto uinst = user.GetInst()->CastToLoadPairPart();
939 
940         Pointer elem = Pointer::CreateArrayElement(arr, nullptr, load->GetImm() + uinst->GetImm());
941         Pointer val = Pointer::CreateObject(uinst);
942         visitor->AddPseudoCopyEdge(obj, elem);
943         visitor->AddCopyEdge(elem, val);
944     }
945 }
946 
VisitStoreArrayPairI(GraphVisitor * v,Inst * inst)947 void AliasVisitor::VisitStoreArrayPairI(GraphVisitor *v, Inst *inst)
948 {
949     if (!inst->IsReferenceOrAny()) {
950         return;
951     }
952     auto visitor = static_cast<AliasVisitor *>(v);
953     auto *store = inst->CastToStoreArrayPairI();
954     Inst *arr = store->GetDataFlowInput(store->GetArray());
955     Pointer obj = Pointer::CreateObject(arr);
956     Pointer elFst = Pointer::CreateArrayElement(arr, nullptr, store->GetImm());
957     Pointer elSnd = Pointer::CreateArrayElement(arr, nullptr, store->GetImm() + 1);
958     Pointer valFst = Pointer::CreateObject(store->GetDataFlowInput(store->GetFirstValue()));
959     Pointer valSnd = Pointer::CreateObject(store->GetDataFlowInput(store->GetSecondValue()));
960 
961     visitor->AddPseudoCopyEdge(obj, elFst);
962     visitor->AddPseudoCopyEdge(obj, elSnd);
963     visitor->AddCopyEdge(valFst, elFst);
964     visitor->AddCopyEdge(valSnd, elSnd);
965 }
966 
VisitLoadObject(GraphVisitor * v,Inst * inst)967 void AliasVisitor::VisitLoadObject(GraphVisitor *v, Inst *inst)
968 {
969     if (!inst->IsReferenceOrAny()) {
970         return;
971     }
972     auto visitor = static_cast<AliasVisitor *>(v);
973     auto typedInst = inst->CastToLoadObject();
974     uint32_t typeId = typedInst->GetTypeId();
975     if (inst->CastToLoadObject()->GetObjectType() == ObjectType::MEM_STATIC) {
976         Pointer sfield = Pointer::CreateStaticField(typeId, typedInst->GetObjField());
977 
978         visitor->SetVolatile(sfield, inst);
979 
980         visitor->AddDirectEdge(sfield);
981         visitor->AddCopyEdge(sfield, Pointer::CreateObject(inst));
982     } else {
983         Inst *dfobj = inst->GetDataFlowInput(0);
984         Pointer obj = Pointer::CreateObject(dfobj);
985         Pointer ifield = Pointer::CreateObjectField(dfobj, typeId, typedInst->GetObjField());
986         Pointer to = Pointer::CreateObject(inst);
987 
988         visitor->SetVolatile(ifield, inst);
989 
990         visitor->AddPseudoCopyEdge(obj, ifield);
991         visitor->AddCopyEdge(ifield, to);
992     }
993 }
994 
VisitLoadResolvedObjectField(GraphVisitor * v,Inst * inst)995 void AliasVisitor::VisitLoadResolvedObjectField(GraphVisitor *v, Inst *inst)
996 {
997     if (!inst->IsReferenceOrAny()) {
998         return;
999     }
1000     auto visitor = static_cast<AliasVisitor *>(v);
1001     auto typedInst = inst->CastToLoadResolvedObjectField();
1002     uint32_t typeId = typedInst->GetTypeId();
1003     Inst *dfobj = inst->GetDataFlowInput(0);
1004     Pointer obj = Pointer::CreateObject(dfobj);
1005     Pointer ifield = Pointer::CreateObjectField(dfobj, typeId);
1006     Pointer to = Pointer::CreateObject(inst);
1007 
1008     visitor->SetVolatile(ifield, inst);
1009 
1010     visitor->AddPseudoCopyEdge(obj, ifield);
1011     visitor->AddCopyEdge(ifield, to);
1012 }
1013 
VisitStoreObject(GraphVisitor * v,Inst * inst)1014 void AliasVisitor::VisitStoreObject(GraphVisitor *v, Inst *inst)
1015 {
1016     if (!inst->IsReferenceOrAny()) {
1017         return;
1018     }
1019     auto visitor = static_cast<AliasVisitor *>(v);
1020     auto typedInst = inst->CastToStoreObject();
1021     uint32_t typeId = typedInst->GetTypeId();
1022     if (inst->CastToStoreObject()->GetObjectType() == ObjectType::MEM_STATIC) {
1023         Pointer sfield = Pointer::CreateStaticField(typeId, typedInst->GetObjField());
1024 
1025         visitor->SetVolatile(sfield, inst);
1026 
1027         visitor->AddDirectEdge(sfield);
1028         visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(0)), sfield);
1029     } else {
1030         Inst *dfobj = inst->GetDataFlowInput(0);
1031         Pointer obj = Pointer::CreateObject(dfobj);
1032         Pointer ifield = Pointer::CreateObjectField(dfobj, typeId, typedInst->GetObjField());
1033         Pointer val = Pointer::CreateObject(inst->GetDataFlowInput(1));
1034 
1035         visitor->SetVolatile(ifield, inst);
1036 
1037         visitor->AddPseudoCopyEdge(obj, ifield);
1038         visitor->AddCopyEdge(val, ifield);
1039     }
1040 }
1041 
VisitStoreResolvedObjectField(GraphVisitor * v,Inst * inst)1042 void AliasVisitor::VisitStoreResolvedObjectField(GraphVisitor *v, Inst *inst)
1043 {
1044     if (!inst->IsReferenceOrAny()) {
1045         return;
1046     }
1047     auto visitor = static_cast<AliasVisitor *>(v);
1048     auto typedInst = inst->CastToStoreResolvedObjectField();
1049     uint32_t typeId = typedInst->GetTypeId();
1050     Inst *dfobj = inst->GetDataFlowInput(0);
1051     Pointer obj = Pointer::CreateObject(dfobj);
1052     Pointer ifield = Pointer::CreateObjectField(dfobj, typeId);
1053     Pointer val = Pointer::CreateObject(inst->GetDataFlowInput(typedInst->STORED_INPUT_INDEX));
1054 
1055     visitor->SetVolatile(ifield, inst);
1056 
1057     visitor->AddPseudoCopyEdge(obj, ifield);
1058     visitor->AddCopyEdge(val, ifield);
1059 }
1060 
VisitLoad(GraphVisitor * v,Inst * inst)1061 void AliasVisitor::VisitLoad(GraphVisitor *v, Inst *inst)
1062 {
1063     if (!inst->IsReferenceOrAny()) {
1064         return;
1065     }
1066     auto visitor = static_cast<AliasVisitor *>(v);
1067     Inst *dfobj = inst->GetDataFlowInput(0);
1068     if (dfobj->GetType() == DataType::POINTER) {
1069         visitor->AddDirectEdge(Pointer::CreateObject(inst));
1070         return;
1071     }
1072     Pointer obj = Pointer::CreateObject(dfobj);
1073     Inst *idx = inst->GetDataFlowInput(1);
1074     Pointer elem = Pointer::CreateRawOffset(dfobj, idx);
1075     Pointer val = Pointer::CreateObject(inst);
1076 
1077     visitor->AddPseudoCopyEdge(obj, elem);
1078     visitor->AddCopyEdge(elem, val);
1079 }
1080 
VisitLoadNative(GraphVisitor * v,Inst * inst)1081 void AliasVisitor::VisitLoadNative(GraphVisitor *v, Inst *inst)
1082 {
1083     VisitLoad(v, inst);
1084 }
1085 
VisitStore(GraphVisitor * v,Inst * inst)1086 void AliasVisitor::VisitStore(GraphVisitor *v, Inst *inst)
1087 {
1088     if (!inst->IsReferenceOrAny()) {
1089         return;
1090     }
1091     auto stored = inst->GetDataFlowInput(2U);
1092     auto visitor = static_cast<AliasVisitor *>(v);
1093     Inst *dfobj = inst->GetDataFlowInput(0);
1094     if (dfobj->GetType() == DataType::POINTER) {
1095         // Treat store to pointer as escaping for simplicity
1096         visitor->Escape(stored);
1097         return;
1098     }
1099     Pointer obj = Pointer::CreateObject(dfobj);
1100     Inst *idx = inst->GetDataFlowInput(1);
1101     Pointer elem = Pointer::CreateRawOffset(dfobj, idx);
1102     Pointer val = Pointer::CreateObject(stored);
1103 
1104     visitor->AddPseudoCopyEdge(obj, elem);
1105     visitor->AddCopyEdge(val, elem);
1106 }
1107 
VisitStoreNative(GraphVisitor * v,Inst * inst)1108 void AliasVisitor::VisitStoreNative(GraphVisitor *v, Inst *inst)
1109 {
1110     VisitStore(v, inst);
1111 }
1112 
VisitLoadI(GraphVisitor * v,Inst * inst)1113 void AliasVisitor::VisitLoadI(GraphVisitor *v, Inst *inst)
1114 {
1115     if (!inst->IsReferenceOrAny()) {
1116         return;
1117     }
1118     auto visitor = static_cast<AliasVisitor *>(v);
1119     Inst *dfobj = inst->GetDataFlowInput(0);
1120     if (dfobj->GetType() == DataType::POINTER) {
1121         visitor->AddDirectEdge(Pointer::CreateObject(inst));
1122         return;
1123     }
1124     Pointer obj = Pointer::CreateObject(dfobj);
1125     Pointer elem = Pointer::CreateRawOffset(dfobj, nullptr, inst->CastToLoadI()->GetImm());
1126     Pointer val = Pointer::CreateObject(inst);
1127 
1128     visitor->AddPseudoCopyEdge(obj, elem);
1129     visitor->AddCopyEdge(elem, val);
1130 }
1131 
VisitStoreI(GraphVisitor * v,Inst * inst)1132 void AliasVisitor::VisitStoreI(GraphVisitor *v, Inst *inst)
1133 {
1134     if (!inst->IsReferenceOrAny()) {
1135         return;
1136     }
1137     auto stored = inst->GetDataFlowInput(1U);
1138     auto visitor = static_cast<AliasVisitor *>(v);
1139     Inst *dfobj = inst->GetDataFlowInput(0);
1140     if (dfobj->GetType() == DataType::POINTER) {
1141         // Treat store to pointer as escaping for simplicity
1142         visitor->Escape(stored);
1143         return;
1144     }
1145     Pointer obj = Pointer::CreateObject(dfobj);
1146     Pointer elem = Pointer::CreateRawOffset(dfobj, nullptr, inst->CastToStoreI()->GetImm());
1147     Pointer val = Pointer::CreateObject(stored);
1148 
1149     visitor->AddPseudoCopyEdge(obj, elem);
1150     visitor->AddCopyEdge(val, elem);
1151 }
1152 
VisitCatchPhi(GraphVisitor * v,Inst * inst)1153 void AliasVisitor::VisitCatchPhi(GraphVisitor *v, Inst *inst)
1154 {
1155     if (!inst->IsReferenceOrAny()) {
1156         return;
1157     }
1158     auto visitor = static_cast<AliasVisitor *>(v);
1159     auto inputsSet = visitor->GetClearInputsSet();
1160     for (size_t i = 0; i < inst->GetInputsCount(); i++) {
1161         inputsSet->insert(inst->GetDataFlowInput(i));
1162     }
1163 
1164     for (auto inputInst : *inputsSet) {
1165         visitor->AddCopyEdge(Pointer::CreateObject(inputInst), Pointer::CreateObject(inst));
1166     }
1167     if (inputsSet->empty()) {
1168         // TryCatchResolving hasn't run yet
1169         visitor->AddDirectEdge(Pointer::CreateObject(inst));
1170     }
1171 }
1172 
VisitPhi(GraphVisitor * v,Inst * inst)1173 void AliasVisitor::VisitPhi(GraphVisitor *v, Inst *inst)
1174 {
1175     if (!inst->IsReferenceOrAny()) {
1176         return;
1177     }
1178     auto visitor = static_cast<AliasVisitor *>(v);
1179     for (size_t i = 0; i < inst->GetInputsCount(); i++) {
1180         visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(i)), Pointer::CreateObject(inst));
1181     }
1182 }
1183 
VisitSelect(GraphVisitor * v,Inst * inst)1184 void AliasVisitor::VisitSelect(GraphVisitor *v, Inst *inst)
1185 {
1186     if (!inst->IsReferenceOrAny()) {
1187         return;
1188     }
1189     ASSERT(inst->GetInputsCount() == 4U);
1190     auto visitor = static_cast<AliasVisitor *>(v);
1191     visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(0)), Pointer::CreateObject(inst));
1192     visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(1)), Pointer::CreateObject(inst));
1193 }
1194 
VisitSelectImm(GraphVisitor * v,Inst * inst)1195 void AliasVisitor::VisitSelectImm(GraphVisitor *v, Inst *inst)
1196 {
1197     if (!inst->IsReferenceOrAny()) {
1198         return;
1199     }
1200     ASSERT(inst->GetInputsCount() == 3U);
1201     auto visitor = static_cast<AliasVisitor *>(v);
1202     visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(0)), Pointer::CreateObject(inst));
1203     visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(1)), Pointer::CreateObject(inst));
1204 }
1205 
VisitMov(GraphVisitor * v,Inst * inst)1206 void AliasVisitor::VisitMov(GraphVisitor *v, Inst *inst)
1207 {
1208     UNREACHABLE();
1209     if (!inst->IsReferenceOrAny()) {
1210         return;
1211     }
1212     auto visitor = static_cast<AliasVisitor *>(v);
1213     visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(0)), Pointer::CreateObject(inst));
1214 }
1215 
1216 // RefTypeCheck is always of a known type, but dataflow input isn't until the check actually happens;
1217 // So it makes sence to add a copy edge to new pointer
VisitRefTypeCheck(GraphVisitor * v,Inst * inst)1218 void AliasVisitor::VisitRefTypeCheck(GraphVisitor *v, Inst *inst)
1219 {
1220     ASSERT(inst->IsReferenceOrAny());
1221     auto visitor = static_cast<AliasVisitor *>(v);
1222     visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(1U)), Pointer::CreateObject(inst));
1223 }
1224 
VisitCastAnyTypeValue(GraphVisitor * v,Inst * inst)1225 void AliasVisitor::VisitCastAnyTypeValue(GraphVisitor *v, Inst *inst)
1226 {
1227     if (inst->GetType() == DataType::REFERENCE) {
1228         static_cast<AliasVisitor *>(v)->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(0)),
1229                                                     Pointer::CreateObject(inst));
1230     }
1231 }
1232 
VisitCastValueToAnyType(GraphVisitor * v,Inst * inst)1233 void AliasVisitor::VisitCastValueToAnyType(GraphVisitor *v, Inst *inst)
1234 {
1235     if (inst->CastToCastValueToAnyType()->GetInputType(0) == DataType::REFERENCE) {
1236         static_cast<AliasVisitor *>(v)->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(0)),
1237                                                     Pointer::CreateObject(inst));
1238     } else if (inst->IsReferenceOrAny()) {
1239         static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
1240     }
1241 }
1242 
VisitGetAnyTypeName(GraphVisitor * v,Inst * inst)1243 void AliasVisitor::VisitGetAnyTypeName(GraphVisitor *v, Inst *inst)
1244 {
1245     static_cast<AliasVisitor *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
1246 }
1247 
VisitLoadConstantPool(GraphVisitor * v,Inst * inst)1248 void AliasVisitor::VisitLoadConstantPool(GraphVisitor *v, Inst *inst)
1249 {
1250     Inst *dfobj = inst->GetDataFlowInput(0);
1251     // fake offset to avoid aliasing with real fields
1252     // also avoid cross_values usage here to get real offset
1253     Pointer elem = Pointer::CreateArrayElement(dfobj, nullptr, UINT64_MAX - 2U);
1254     Pointer to = Pointer::CreateObject(inst);
1255     static_cast<AliasVisitor *>(v)->AddCopyEdge(elem, to);
1256 }
1257 
VisitLoadLexicalEnv(GraphVisitor * v,Inst * inst)1258 void AliasVisitor::VisitLoadLexicalEnv(GraphVisitor *v, Inst *inst)
1259 {
1260     Inst *dfobj = inst->GetDataFlowInput(0);
1261     Pointer elem = Pointer::CreateArrayElement(dfobj, nullptr, UINT64_MAX - 1U);
1262     Pointer to = Pointer::CreateObject(inst);
1263     static_cast<AliasVisitor *>(v)->AddCopyEdge(elem, to);
1264 }
1265 
VisitLoadObjectDynamic(GraphVisitor * v,Inst * inst)1266 void AliasVisitor::VisitLoadObjectDynamic(GraphVisitor *v, Inst *inst)
1267 {
1268     if (!inst->IsReferenceOrAny()) {
1269         return;
1270     }
1271     auto visitor = static_cast<AliasVisitor *>(v);
1272     auto type = inst->CastToLoadObjectDynamic()->GetAccessType();
1273     auto mode = inst->CastToLoadObjectDynamic()->GetAccessMode();
1274 
1275     Inst *dfobj = inst->GetDataFlowInput(0);
1276     Pointer obj = Pointer::CreateObject(dfobj);
1277     Pointer val = Pointer::CreateObject(inst);
1278     Pointer elem = GetDynamicAccessPointer(inst, dfobj, type, mode);
1279 
1280     visitor->AddPseudoCopyEdge(obj, elem);
1281     visitor->AddCopyEdge(elem, val);
1282 }
1283 
VisitStoreObjectDynamic(GraphVisitor * v,Inst * inst)1284 void AliasVisitor::VisitStoreObjectDynamic(GraphVisitor *v, Inst *inst)
1285 {
1286     if (!inst->IsReferenceOrAny()) {
1287         return;
1288     }
1289     auto stored = inst->GetDataFlowInput(2U);
1290     auto visitor = static_cast<AliasVisitor *>(v);
1291     auto type = inst->CastToStoreObjectDynamic()->GetAccessType();
1292     auto mode = inst->CastToStoreObjectDynamic()->GetAccessMode();
1293 
1294     Inst *dfobj = inst->GetDataFlowInput(0);
1295     Pointer obj = Pointer::CreateObject(dfobj);
1296     Pointer val = Pointer::CreateObject(stored);
1297     Pointer elem = GetDynamicAccessPointer(inst, dfobj, type, mode);
1298 
1299     visitor->AddPseudoCopyEdge(obj, elem);
1300     visitor->AddCopyEdge(val, elem);
1301 }
1302 
VisitLoadFromConstantPool(GraphVisitor * v,Inst * inst)1303 void AliasVisitor::VisitLoadFromConstantPool(GraphVisitor *v, Inst *inst)
1304 {
1305     if (!inst->IsReferenceOrAny()) {
1306         return;
1307     }
1308     uint32_t typeId = inst->CastToLoadFromConstantPool()->GetTypeId();
1309     auto visitor = static_cast<AliasVisitor *>(v);
1310     Inst *constpool = inst->GetDataFlowInput(0);
1311     Pointer obj = Pointer::CreateObject(constpool);
1312     Pointer elem = Pointer::CreateArrayElement(constpool, nullptr, typeId);
1313     Pointer val = Pointer::CreateObject(inst);
1314 
1315     visitor->AddPseudoCopyEdge(obj, elem);
1316     visitor->AddCopyEdge(elem, val);
1317 }
1318 
VisitDefault(Inst * inst)1319 void AliasVisitor::VisitDefault([[maybe_unused]] Inst *inst)
1320 {
1321     /* Ignore the following instructions with REFERENCE type intentionally */
1322     switch (inst->GetOpcode()) {
1323         // Handled on its input
1324         case Opcode::LoadPairPart:
1325         // No passes that check class references aliasing
1326         case Opcode::GetInstanceClass:
1327         case Opcode::LoadImmediate:
1328         // NOTE(compiler): Probably should be added
1329         case Opcode::Monitor:
1330         // Mitigated by using GetDataFlowInput
1331         case Opcode::NullCheck:
1332         case Opcode::RefTypeCheck:
1333         case Opcode::AnyTypeCheck:
1334         case Opcode::ObjByIndexCheck:
1335         case Opcode::HclassCheck:
1336         // Irrelevant for analysis
1337         case Opcode::Return:
1338         case Opcode::ReturnI:
1339         // No need to analyze
1340         case Opcode::LiveOut:
1341         case Opcode::FunctionImmediate:
1342             return;
1343         default:
1344             ASSERT_DO(!inst->IsReferenceOrAny(),
1345                       (std::cerr << "Unsupported instruction in alias analysis: ", inst->Dump(&std::cerr)));
1346             return;
1347     }
1348 }
1349 
EscapeInputsAndInv(Inst * inst)1350 void AliasVisitor::EscapeInputsAndInv(Inst *inst)
1351 {
1352     for (auto &input : inst->GetInputs()) {
1353         auto *inputInst = Inst::GetDataFlowInput(input.GetInst());
1354         if (inputInst->IsReferenceOrAny()) {
1355             Escape(inputInst);
1356         }
1357     }
1358     VisitHeapInv(inst);
1359 }
1360 
1361 }  // namespace ark::compiler
1362