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