1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ea_connection_graph.h"
17
18 namespace maple {
19 constexpr maple::uint32 kInvalid = 0xffffffff;
CheckAllConnectionInNodes()20 void EACGBaseNode::CheckAllConnectionInNodes()
21 {
22 #ifdef DEBUG
23 for (EACGBaseNode *inNode : in) {
24 ASSERT_NOT_NULL(eaCG->nodes[inNode->id - 1]);
25 DEBUG_ASSERT(eaCG->nodes[inNode->id - 1] == inNode, "must be inNode");
26 }
27 for (EACGBaseNode *outNode : out) {
28 ASSERT_NOT_NULL(eaCG->nodes[outNode->id - 1]);
29 DEBUG_ASSERT(eaCG->nodes[outNode->id - 1] == outNode, "must be outNode");
30 }
31 for (EACGObjectNode *obj : pointsTo) {
32 ASSERT_NOT_NULL(eaCG->nodes[obj->id - 1]);
33 DEBUG_ASSERT(eaCG->nodes[obj->id - 1] == obj, "must be obj");
34 }
35 if (IsFieldNode()) {
36 for (EACGObjectNode *obj : static_cast<EACGFieldNode *>(this)->GetBelongsToObj()) {
37 ASSERT_NOT_NULL(eaCG->nodes[obj->id - 1]);
38 DEBUG_ASSERT(eaCG->nodes[obj->id - 1] == obj, "must be obj");
39 }
40 }
41 #endif
42 }
43
AddOutNode(EACGBaseNode & newOut)44 bool EACGBaseNode::AddOutNode(EACGBaseNode &newOut)
45 {
46 if (out.find(&newOut) != out.end()) {
47 return false;
48 }
49 bool newIsLocal = newOut.UpdateEAStatus(eaStatus);
50 if (eaStatus == kGlobalEscape && pointsTo.size() > 0) {
51 if (newIsLocal) {
52 eaCG->SetCGUpdateFlag();
53 }
54 return newIsLocal;
55 }
56 (void)out.insert(&newOut);
57 (void)newOut.in.insert(this);
58 DEBUG_ASSERT(newOut.pointsTo.size() != 0, "must be greater than zero");
59 bool hasChanged = UpdatePointsTo(newOut.pointsTo);
60 eaCG->SetCGUpdateFlag();
61 return hasChanged;
62 }
63
PropagateEAStatusForNode(const EACGBaseNode * subRoot) const64 void EACGBaseNode::PropagateEAStatusForNode(const EACGBaseNode *subRoot) const
65 {
66 for (EACGBaseNode *outNode : out) {
67 (void)outNode->UpdateEAStatus(eaStatus);
68 }
69 }
70
GetName(const IRMap * irMap) const71 std::string EACGBaseNode::GetName(const IRMap *irMap) const
72 {
73 std::string name;
74 if (irMap == nullptr || meExpr == nullptr) {
75 name += std::to_string(id);
76 } else {
77 name += std::to_string(id);
78 name += "\\n";
79 if (meExpr->GetMeOp() == kMeOpVar) {
80 VarMeExpr *varMeExpr = static_cast<VarMeExpr *>(meExpr);
81 const MIRSymbol *sym = varMeExpr->GetOst()->GetMIRSymbol();
82 name += ((sym->GetStIdx().IsGlobal() ? "$" : "%") + sym->GetName() + "\\nmx" +
83 std::to_string(meExpr->GetExprID()) + " (field)" + std::to_string(varMeExpr->GetFieldID()));
84 } else if (meExpr->GetMeOp() == kMeOpIvar) {
85 IvarMeExpr *ivarMeExpr = static_cast<IvarMeExpr *>(meExpr);
86 MeExpr *base = ivarMeExpr->GetBase();
87 VarMeExpr *varMeExpr = nullptr;
88 if (base->GetMeOp() == kMeOpVar) {
89 varMeExpr = static_cast<VarMeExpr *>(base);
90 } else {
91 name += std::to_string(id);
92 return name;
93 }
94 const MIRSymbol *sym = varMeExpr->GetOst()->GetMIRSymbol();
95 name += (std::string("base :") + (sym->GetStIdx().IsGlobal() ? "$" : "%") + sym->GetName() + "\\nmx" +
96 std::to_string(meExpr->GetExprID()) + " (field)" + std::to_string(ivarMeExpr->GetFieldID()));
97 } else if (meExpr->GetOp() == OP_gcmalloc || meExpr->GetOp() == OP_gcmallocjarray) {
98 name += "mx" + std::to_string(meExpr->GetExprID());
99 }
100 }
101 return name;
102 }
103
UpdatePointsTo(const std::set<EACGObjectNode * > & cPointsTo)104 bool EACGBaseNode::UpdatePointsTo(const std::set<EACGObjectNode *> &cPointsTo)
105 {
106 size_t oldPtSize = pointsTo.size();
107 pointsTo.insert(cPointsTo.begin(), cPointsTo.end());
108 if (oldPtSize == pointsTo.size()) {
109 return false;
110 }
111 for (EACGObjectNode *pt : pointsTo) {
112 pt->Insert2PointsBy(this);
113 }
114 for (EACGBaseNode *pred : in) {
115 (void)pred->UpdatePointsTo(pointsTo);
116 }
117 return true;
118 }
119
GetNodeFormatInDot(std::string & label,std::string & color) const120 void EACGBaseNode::GetNodeFormatInDot(std::string &label, std::string &color) const
121 {
122 switch (GetEAStatus()) {
123 case kNoEscape:
124 label += "NoEscape";
125 color = "darkgreen";
126 break;
127 case kArgumentEscape:
128 label += "ArgEscape";
129 color = "brown";
130 break;
131 case kReturnEscape:
132 label += "RetEscape";
133 color = "orange";
134 break;
135 case kGlobalEscape:
136 label += "GlobalEscape";
137 color = "red";
138 break;
139 }
140 }
141
CanIgnoreRC() const142 bool EACGBaseNode::CanIgnoreRC() const
143 {
144 for (auto obj : pointsTo) {
145 if (!obj->GetIgnorRC()) {
146 return false;
147 }
148 }
149 return true;
150 }
151
CheckAllConnectionInNodes()152 void EACGObjectNode::CheckAllConnectionInNodes()
153 {
154 #ifdef DEBUG
155 for (EACGBaseNode *inNode : in) {
156 ASSERT_NOT_NULL(eaCG->nodes[inNode->id - 1]);
157 DEBUG_ASSERT(eaCG->nodes[inNode->id - 1] == inNode, "must be inNode");
158 }
159 for (EACGBaseNode *outNode : out) {
160 ASSERT_NOT_NULL(eaCG->nodes[outNode->id - 1]);
161 DEBUG_ASSERT(eaCG->nodes[outNode->id - 1] == outNode, "must be outNode");
162 }
163 for (EACGBaseNode *pBy : pointsBy) {
164 ASSERT_NOT_NULL(eaCG->nodes[pBy->id - 1]);
165 DEBUG_ASSERT(eaCG->nodes[pBy->id - 1] == pBy, "must be pBy");
166 }
167 for (auto fieldPair : fieldNodes) {
168 EACGFieldNode *field = fieldPair.second;
169 DEBUG_ASSERT(field->fieldID == fieldPair.first, "must be fieldPair.first");
170 ASSERT_NOT_NULL(eaCG->nodes[field->id - 1]);
171 DEBUG_ASSERT(eaCG->nodes[field->id - 1] == field, "must be filed");
172 }
173 #endif
174 }
175
IsPointedByFieldNode() const176 bool EACGObjectNode::IsPointedByFieldNode() const
177 {
178 for (EACGBaseNode *pBy : pointsBy) {
179 if (pBy->IsFieldNode()) {
180 return true;
181 }
182 }
183 return false;
184 }
185
AddOutNode(EACGBaseNode & newOut)186 bool EACGObjectNode::AddOutNode(EACGBaseNode &newOut)
187 {
188 DEBUG_ASSERT(newOut.IsFieldNode(), "must be fieldNode");
189 EACGFieldNode *field = static_cast<EACGFieldNode *>(&newOut);
190 fieldNodes[field->GetFieldID()] = field;
191 (void)newOut.UpdateEAStatus(eaStatus);
192 field->AddBelongTo(this);
193 return true;
194 }
195
ReplaceByGlobalNode()196 bool EACGObjectNode::ReplaceByGlobalNode()
197 {
198 DEBUG_ASSERT(out.size() == 0, "must be zero");
199 for (EACGBaseNode *node : pointsBy) {
200 node->pointsTo.erase(this);
201 (void)node->pointsTo.insert(eaCG->GetGlobalObject());
202 }
203 pointsBy.clear();
204 for (EACGBaseNode *inNode : in) {
205 (void)inNode->out.erase(this);
206 (void)inNode->out.insert(eaCG->GetGlobalObject());
207 }
208 in.clear();
209 for (auto fieldPair : fieldNodes) {
210 EACGFieldNode *field = fieldPair.second;
211 field->belongsTo.erase(this);
212 }
213 fieldNodes.clear();
214 if (meExpr != nullptr) {
215 eaCG->expr2Nodes[meExpr]->clear();
216 eaCG->expr2Nodes[meExpr]->insert(eaCG->GetGlobalObject());
217 }
218 DEBUG_ASSERT(eaCG->nodes[id - 1] == this, "must be");
219 CHECK_FATAL(id > 0, "must not be zero");
220 eaCG->nodes[id - 1] = nullptr;
221 return true;
222 }
223
PropagateEAStatusForNode(const EACGBaseNode * subRoot) const224 void EACGObjectNode::PropagateEAStatusForNode(const EACGBaseNode *subRoot) const
225 {
226 for (auto fieldNodePair : fieldNodes) {
227 EACGFieldNode *field = fieldNodePair.second;
228 (void)field->UpdateEAStatus(eaStatus);
229 }
230 }
231
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)232 void EACGObjectNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
233 const IRMap *irMap)
234 {
235 if (dumped[this]) {
236 return;
237 }
238 dumped[this] = true;
239
240 std::string name = GetName(nullptr);
241 std::string label = GetName(irMap) + " Object\\n";
242 std::string color;
243 GetNodeFormatInDot(label, color);
244 std::string style;
245 if (IsPhantom()) {
246 style = "dotted";
247 } else {
248 style = "bold";
249 }
250 fout << name << " [shape=box, label=\"" << label << "\", fontcolor=" << color << ", style=" << style << "];\n";
251 for (auto fieldPair : fieldNodes) {
252 EACGBaseNode *field = fieldPair.second;
253 fout << name << "->" << field->GetName(nullptr) << ";"
254 << "\n";
255 }
256 for (auto fieldPair : fieldNodes) {
257 EACGBaseNode *field = fieldPair.second;
258 field->DumpDotFile(fout, dumped, dumpPt, irMap);
259 }
260 }
261
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)262 void EACGRefNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
263 const IRMap *irMap)
264 {
265 if (dumped[this]) {
266 return;
267 }
268 dumped[this] = true;
269
270 std::string name = GetName(nullptr);
271 std::string label = GetName(irMap) + " Reference\\n";
272 if (IsStaticRef()) {
273 label += "Static\\n";
274 }
275 std::string color;
276 GetNodeFormatInDot(label, color);
277 fout << name << " [shape=ellipse, label=\"" << label << "\", fontcolor=" << color << "];"
278 << "\n";
279 if (dumpPt) {
280 for (auto obj : pointsTo) {
281 fout << name << "->" << obj->GetName(nullptr) << ";"
282 << "\n";
283 }
284 for (auto obj : pointsTo) {
285 obj->DumpDotFile(fout, dumped, dumpPt, irMap);
286 }
287 } else {
288 for (auto outNode : out) {
289 std::string edgeStyle;
290 if (!outNode->IsObjectNode()) {
291 edgeStyle = " [style =\"dotted\"]";
292 }
293 fout << name << "->" << outNode->GetName(nullptr) << edgeStyle << ";"
294 << "\n";
295 }
296 for (auto outNode : out) {
297 outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
298 }
299 }
300 }
301
ReplaceByGlobalNode()302 bool EACGRefNode::ReplaceByGlobalNode()
303 {
304 for (EACGBaseNode *inNode : in) {
305 DEBUG_ASSERT(inNode->id > 3, "must be greater than three"); // the least valid idx is 3
306 (void)inNode->out.erase(this);
307 (void)inNode->out.insert(eaCG->GetGlobalReference());
308 }
309 in.clear();
310 for (EACGBaseNode *outNode : out) {
311 (void)outNode->in.erase(this);
312 }
313 out.clear();
314 for (EACGObjectNode *base : pointsTo) {
315 base->EraseNodeFromPointsBy(this);
316 }
317 pointsTo.clear();
318 if (meExpr != nullptr) {
319 eaCG->expr2Nodes[meExpr]->clear();
320 eaCG->expr2Nodes[meExpr]->insert(eaCG->GetGlobalReference());
321 }
322 DEBUG_ASSERT(eaCG->nodes[id - 1] == this, "must be this");
323 CHECK_FATAL(id > 0, "must not be zero");
324 eaCG->nodes[id - 1] = nullptr;
325 return true;
326 }
327
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)328 void EACGPointerNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
329 const IRMap *irMap)
330 {
331 if (dumped[this]) {
332 return;
333 }
334 dumped[this] = true;
335 std::string name = GetName(nullptr);
336 std::string label = GetName(irMap) + "\\nPointer Indirect Level : " + std::to_string(indirectLevel) + "\\n";
337 std::string color;
338 GetNodeFormatInDot(label, color);
339 fout << name << " [shape=ellipse, label=\"" << label << "\", fontcolor=" << color << "];"
340 << "\n";
341 for (EACGBaseNode *outNode : out) {
342 fout << name << "->" << outNode->GetName(nullptr) << " [style =\"dotted\", color = \"blue\"];"
343 << "\n";
344 }
345 for (auto outNode : out) {
346 outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
347 }
348 }
349
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)350 void EACGActualNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
351 const IRMap *irMap)
352 {
353 if (dumped[this]) {
354 return;
355 }
356 dumped[this] = true;
357
358 std::string name = GetName(nullptr);
359 std::string label;
360 if (IsReturn()) {
361 label = GetName(irMap) + "\\nRet Idx : " + std::to_string(GetArgIndex()) + "\\n";
362 } else {
363 label = GetName(irMap) + "\\nArg Idx : " + std::to_string(GetArgIndex()) +
364 " Call Site : " + std::to_string(GetCallSite()) + "\\n";
365 }
366 std::string style;
367 if (IsPhantom()) {
368 style = "dotted";
369 } else {
370 style = "bold";
371 }
372 std::string color;
373 GetNodeFormatInDot(label, color);
374 fout << name << " [shape=ellipse, label=\"" << label << "\", fontcolor=" << color << ", style=" << style << "];\n";
375 if (dumpPt) {
376 for (auto obj : pointsTo) {
377 fout << name << "->" << obj->GetName(nullptr) << ";\n";
378 }
379 for (auto obj : pointsTo) {
380 obj->DumpDotFile(fout, dumped, dumpPt, irMap);
381 }
382 } else {
383 for (auto outNode : out) {
384 std::string edgeStyle;
385 if (!outNode->IsObjectNode()) {
386 edgeStyle = " [style =\"dotted\"]";
387 }
388 fout << name << "->" << outNode->GetName(nullptr) << edgeStyle << ";\n";
389 }
390 for (auto outNode : out) {
391 outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
392 }
393 }
394 }
395
ReplaceByGlobalNode()396 bool EACGActualNode::ReplaceByGlobalNode()
397 {
398 DEBUG_ASSERT(callSiteInfo == kInvalid, "must be invalid");
399 DEBUG_ASSERT(out.size() == 1, "the size of out must be one");
400 DEBUG_ASSERT(pointsTo.size() == 1, "the size of pointsTo must be one");
401 for (EACGBaseNode *inNode : in) {
402 inNode->out.erase(this);
403 }
404 in.clear();
405 return false;
406 }
407
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)408 void EACGFieldNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
409 const IRMap *irMap)
410 {
411 if (dumped[this]) {
412 return;
413 }
414 dumped[this] = true;
415 std::string name = GetName(nullptr);
416 std::string label = GetName(irMap) + "\\nFIdx : " + std::to_string(GetFieldID()) + "\\n";
417 std::string color;
418 GetNodeFormatInDot(label, color);
419 std::string style;
420 if (IsPhantom()) {
421 style = "dotted";
422 } else {
423 style = "bold";
424 }
425 fout << name << " [shape=circle, label=\"" << label << "\", fontcolor=" << color << ", style=" << style
426 << ", margin=0];\n";
427 if (dumpPt) {
428 for (auto obj : pointsTo) {
429 fout << name << "->" << obj->GetName(nullptr) << ";\n";
430 }
431 for (auto obj : pointsTo) {
432 obj->DumpDotFile(fout, dumped, dumpPt, irMap);
433 }
434 } else {
435 for (auto outNode : out) {
436 std::string edgeStyle;
437 if (!outNode->IsObjectNode()) {
438 edgeStyle = " [style =\"dotted\"]";
439 }
440 fout << name << "->" << outNode->GetName(nullptr) << edgeStyle << ";\n";
441 }
442 for (auto outNode : out) {
443 outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
444 }
445 }
446 }
447
ReplaceByGlobalNode()448 bool EACGFieldNode::ReplaceByGlobalNode()
449 {
450 for (EACGObjectNode *obj : pointsTo) {
451 obj->pointsBy.erase(this);
452 }
453 pointsTo.clear();
454 (void)pointsTo.insert(eaCG->GetGlobalObject());
455 for (EACGBaseNode *outNode : out) {
456 outNode->in.erase(this);
457 }
458 out.clear();
459 (void)out.insert(eaCG->GetGlobalObject());
460 bool canDelete = true;
461 std::set<EACGObjectNode *> tmp = belongsTo;
462 for (EACGObjectNode *obj : tmp) {
463 if (obj->GetEAStatus() != kGlobalEscape) {
464 canDelete = false;
465 } else {
466 belongsTo.erase(obj);
467 }
468 }
469 if (canDelete) {
470 DEBUG_ASSERT(eaCG->nodes[id - 1] == this, "must be this");
471 CHECK_FATAL(id > 0, "must not be zero");
472 eaCG->nodes[id - 1] = nullptr;
473 for (EACGBaseNode *inNode : in) {
474 DEBUG_ASSERT(!inNode->IsObjectNode(), "must be ObjectNode");
475 inNode->out.erase(this);
476 (void)inNode->out.insert(eaCG->globalField);
477 }
478 for (auto exprPair : eaCG->expr2Nodes) {
479 size_t eraseSize = exprPair.second->erase(this);
480 if (eraseSize != 0 && exprPair.first->GetMeOp() != kMeOpIvar && exprPair.first->GetMeOp() != kMeOpOp) {
481 DEBUG_ASSERT(false, "must be kMeOpIvar or kMeOpOp");
482 }
483 if (exprPair.second->size() == 0) {
484 exprPair.second->insert(eaCG->globalField);
485 }
486 }
487 in.clear();
488 return true;
489 }
490 return false;
491 }
492
DeleteEACG() const493 void EAConnectionGraph::DeleteEACG() const
494 {
495 for (EACGBaseNode *node : nodes) {
496 if (node == nullptr) {
497 continue;
498 }
499 delete node;
500 node = nullptr;
501 }
502 }
503
TrimGlobalNode() const504 void EAConnectionGraph::TrimGlobalNode() const
505 {
506 for (EACGBaseNode *node : nodes) {
507 if (node == nullptr) {
508 continue;
509 }
510 constexpr int leastIdx = 3;
511 if (node->id <= leastIdx) {
512 continue;
513 }
514 bool canDelete = false;
515 if (node->GetEAStatus() == kGlobalEscape) {
516 canDelete = node->ReplaceByGlobalNode();
517 }
518 #ifdef DEBUG
519 node->CheckAllConnectionInNodes();
520 #endif
521 if (canDelete) {
522 delete node;
523 node = nullptr;
524 }
525 }
526 }
527
InitGlobalNode()528 void EAConnectionGraph::InitGlobalNode()
529 {
530 globalObj = CreateObjectNode(nullptr, kNoEscape, true, TyIdx(0));
531 globalRef = CreateReferenceNode(nullptr, kNoEscape, true);
532 (void)globalRef->AddOutNode(*globalObj);
533 (void)globalRef->AddOutNode(*globalRef);
534 globalField = CreateFieldNode(nullptr, kNoEscape, -1, globalObj, true); // -1 expresses global
535 (void)globalField->AddOutNode(*globalObj);
536 (void)globalField->AddOutNode(*globalRef);
537 (void)globalField->AddOutNode(*globalField);
538 (void)globalRef->AddOutNode(*globalField);
539 globalObj->eaStatus = kGlobalEscape;
540 globalField->eaStatus = kGlobalEscape;
541 globalRef->eaStatus = kGlobalEscape;
542 }
543
CreateObjectNode(MeExpr * expr,EAStatus initialEas,bool isPh,TyIdx tyIdx)544 EACGObjectNode *EAConnectionGraph::CreateObjectNode(MeExpr *expr, EAStatus initialEas, bool isPh, TyIdx tyIdx)
545 {
546 EACGObjectNode *newObjNode =
547 new (std::nothrow) EACGObjectNode(mirModule, alloc, *this, expr, initialEas, nodes.size() + 1, isPh);
548 ASSERT_NOT_NULL(newObjNode);
549 nodes.push_back(newObjNode);
550 if (expr != nullptr) {
551 if (expr2Nodes.find(expr) == expr2Nodes.end()) {
552 expr2Nodes[expr] = alloc->GetMemPool()->New<MapleSet<EACGBaseNode *>>(alloc->Adapter());
553 expr2Nodes[expr]->insert(newObjNode);
554 } else {
555 DEBUG_ASSERT(false, "must find expr");
556 }
557 }
558 return newObjNode;
559 }
560
CreatePointerNode(MeExpr * expr,EAStatus initialEas,int inderictL)561 EACGPointerNode *EAConnectionGraph::CreatePointerNode(MeExpr *expr, EAStatus initialEas, int inderictL)
562 {
563 EACGPointerNode *newPointerNode =
564 new (std::nothrow) EACGPointerNode(mirModule, alloc, *this, expr, initialEas, nodes.size() + 1, inderictL);
565 ASSERT_NOT_NULL(newPointerNode);
566 nodes.push_back(newPointerNode);
567 if (expr != nullptr) {
568 if (expr2Nodes.find(expr) == expr2Nodes.end()) {
569 expr2Nodes[expr] = alloc->GetMemPool()->New<MapleSet<EACGBaseNode *>>(alloc->Adapter());
570 expr2Nodes[expr]->insert(newPointerNode);
571 } else {
572 DEBUG_ASSERT(false, "must find expr");
573 }
574 }
575 return newPointerNode;
576 }
577
CreateReferenceNode(MeExpr * expr,EAStatus initialEas,bool isStatic)578 EACGRefNode *EAConnectionGraph::CreateReferenceNode(MeExpr *expr, EAStatus initialEas, bool isStatic)
579 {
580 EACGRefNode *newRefNode =
581 new (std::nothrow) EACGRefNode(mirModule, alloc, *this, expr, initialEas, nodes.size() + 1, isStatic);
582 ASSERT_NOT_NULL(newRefNode);
583 nodes.push_back(newRefNode);
584 if (expr != nullptr) {
585 if (expr2Nodes.find(expr) == expr2Nodes.end()) {
586 expr2Nodes[expr] = alloc->GetMemPool()->New<MapleSet<EACGBaseNode *>>(alloc->Adapter());
587 expr2Nodes[expr]->insert(newRefNode);
588 } else {
589 DEBUG_ASSERT(false, "must find expr");
590 }
591 if (expr->GetMeOp() != kMeOpVar && expr->GetMeOp() != kMeOpAddrof && expr->GetMeOp() != kMeOpReg &&
592 expr->GetMeOp() != kMeOpOp) {
593 DEBUG_ASSERT(false, "must be kMeOpVar, kMeOpAddrof, kMeOpReg or kMeOpOp");
594 }
595 }
596 return newRefNode;
597 }
598
TouchCallSite(uint32 callSiteInfo)599 void EAConnectionGraph::TouchCallSite(uint32 callSiteInfo)
600 {
601 CHECK_FATAL(callSite2Nodes.find(callSiteInfo) != callSite2Nodes.end(), "find failed");
602 if (callSite2Nodes[callSiteInfo] == nullptr) {
603 MapleVector<EACGBaseNode *> *tmp = alloc->GetMemPool()->New<MapleVector<EACGBaseNode *>>(alloc->Adapter());
604 callSite2Nodes[callSiteInfo] = tmp;
605 }
606 }
607
CreateActualNode(EAStatus initialEas,bool isReurtn,bool isPh,uint8 argIdx,uint32 callSiteInfo)608 EACGActualNode *EAConnectionGraph::CreateActualNode(EAStatus initialEas, bool isReurtn, bool isPh, uint8 argIdx,
609 uint32 callSiteInfo)
610 {
611 MeExpr *expr = nullptr;
612 DEBUG_ASSERT(isPh, "must be ph");
613 DEBUG_ASSERT(callSiteInfo != 0, "must not be zero");
614 EACGActualNode *newActNode = new (std::nothrow) EACGActualNode(
615 mirModule, alloc, *this, expr, initialEas, nodes.size() + 1, isReurtn, isPh, argIdx, callSiteInfo);
616 ASSERT_NOT_NULL(newActNode);
617 nodes.push_back(newActNode);
618 if (expr != nullptr) {
619 if (expr2Nodes.find(expr) == expr2Nodes.end()) {
620 expr2Nodes[expr] = alloc->GetMemPool()->New<MapleSet<EACGBaseNode *>>(alloc->Adapter());
621 expr2Nodes[expr]->insert(newActNode);
622 } else {
623 DEBUG_ASSERT(false, "must find expr");
624 }
625 }
626 if (callSiteInfo != kInvalid) {
627 DEBUG_ASSERT(callSite2Nodes[callSiteInfo] != nullptr, "must touched before");
628 callSite2Nodes[callSiteInfo]->push_back(newActNode);
629 #ifdef DEBUG
630 CheckArgNodeOrder(*callSite2Nodes[callSiteInfo]);
631 #endif
632 } else {
633 funcArgNodes.push_back(newActNode);
634 }
635 return newActNode;
636 }
637
CreateFieldNode(MeExpr * expr,EAStatus initialEas,FieldID fId,EACGObjectNode * belongTo,bool isPh)638 EACGFieldNode *EAConnectionGraph::CreateFieldNode(MeExpr *expr, EAStatus initialEas, FieldID fId,
639 EACGObjectNode *belongTo, bool isPh)
640 {
641 EACGFieldNode *newFieldNode = new (std::nothrow)
642 EACGFieldNode(mirModule, alloc, *this, expr, initialEas, nodes.size() + 1, fId, belongTo, isPh);
643 ASSERT_NOT_NULL(newFieldNode);
644 nodes.push_back(newFieldNode);
645 if (expr != nullptr) {
646 if (expr2Nodes.find(expr) == expr2Nodes.end()) {
647 expr2Nodes[expr] = alloc->GetMemPool()->New<MapleSet<EACGBaseNode *>>(alloc->Adapter());
648 expr2Nodes[expr]->insert(newFieldNode);
649 } else {
650 expr2Nodes[expr]->insert(newFieldNode);
651 }
652 if (expr->GetMeOp() != kMeOpIvar && expr->GetMeOp() != kMeOpOp) {
653 DEBUG_ASSERT(false, "must be kMeOpIvar or kMeOpOp");
654 }
655 }
656 return newFieldNode;
657 }
658
GetCGNodeFromExpr(MeExpr * me)659 EACGBaseNode *EAConnectionGraph::GetCGNodeFromExpr(MeExpr *me)
660 {
661 if (expr2Nodes.find(me) == expr2Nodes.end()) {
662 return nullptr;
663 }
664 return *(expr2Nodes[me]->begin());
665 }
666
UpdateExprOfNode(EACGBaseNode & node,MeExpr * me)667 void EAConnectionGraph::UpdateExprOfNode(EACGBaseNode &node, MeExpr *me)
668 {
669 if (expr2Nodes.find(me) == expr2Nodes.end()) {
670 expr2Nodes[me] = alloc->GetMemPool()->New<MapleSet<EACGBaseNode *>>(alloc->Adapter());
671 expr2Nodes[me]->insert(&node);
672 } else {
673 if (node.IsFieldNode()) {
674 expr2Nodes[me]->insert(&node);
675 } else {
676 if (expr2Nodes[me]->find(&node) == expr2Nodes[me]->end()) {
677 CHECK_FATAL(false, "must be filed node");
678 }
679 }
680 }
681 node.SetMeExpr(*me);
682 }
683
UpdateExprOfGlobalRef(MeExpr * me)684 void EAConnectionGraph::UpdateExprOfGlobalRef(MeExpr *me)
685 {
686 UpdateExprOfNode(*globalRef, me);
687 }
688
GetReturnNode() const689 EACGActualNode *EAConnectionGraph::GetReturnNode() const
690 {
691 if (funcArgNodes.size() == 0) {
692 return nullptr;
693 }
694 CHECK_FATAL(funcArgNodes.size() > 0, "must not be zero");
695 EACGActualNode *ret = static_cast<EACGActualNode *>(funcArgNodes[funcArgNodes.size() - 1]);
696 if (ret->IsReturn()) {
697 return ret;
698 }
699 return nullptr;
700 }
701 #ifdef DEBUG
CheckArgNodeOrder(MapleVector<EACGBaseNode * > & funcArgV)702 void EAConnectionGraph::CheckArgNodeOrder(MapleVector<EACGBaseNode *> &funcArgV)
703 {
704 uint8 preIndex = 0;
705 for (size_t i = 0; i < funcArgV.size(); ++i) {
706 DEBUG_ASSERT(funcArgV[i]->IsActualNode(), "must be ActualNode");
707 EACGActualNode *actNode = static_cast<EACGActualNode *>(funcArgV[i]);
708 if (i == funcArgV.size() - 1) {
709 if (actNode->IsReturn()) {
710 continue;
711 } else {
712 DEBUG_ASSERT(actNode->GetArgIndex() >= preIndex, "must be greater than preIndex");
713 }
714 } else {
715 DEBUG_ASSERT(!actNode->IsReturn(), "must be return");
716 DEBUG_ASSERT(actNode->GetArgIndex() >= preIndex, "must be greater than preIndex");
717 }
718 preIndex = actNode->GetArgIndex();
719 }
720 }
721 #endif
ExprCanBeOptimized(MeExpr & expr)722 bool EAConnectionGraph::ExprCanBeOptimized(MeExpr &expr)
723 {
724 if (expr2Nodes.find(&expr) == expr2Nodes.end()) {
725 MeExpr *rhs = nullptr;
726 if (expr.GetMeOp() == kMeOpVar) {
727 DEBUG_ASSERT(static_cast<VarMeExpr *>(&expr)->GetDefBy() == kDefByStmt, "must be kDefByStmt");
728 DEBUG_ASSERT(static_cast<VarMeExpr *>(&expr)->GetDefStmt()->GetOp() == OP_dassign, "must be OP_dassign");
729 MeStmt *defStmt = static_cast<VarMeExpr *>(&expr)->GetDefStmt();
730 DassignMeStmt *dassignStmt = static_cast<DassignMeStmt *>(defStmt);
731 rhs = dassignStmt->GetRHS();
732 } else if (expr.GetMeOp() == kMeOpReg) {
733 DEBUG_ASSERT(static_cast<RegMeExpr *>(&expr)->GetDefBy() == kDefByStmt, "must be kDefByStmt");
734 DEBUG_ASSERT(static_cast<RegMeExpr *>(&expr)->GetDefStmt()->GetOp() == OP_regassign,
735 "must be OP_regassign");
736 MeStmt *defStmt = static_cast<RegMeExpr *>(&expr)->GetDefStmt();
737 AssignMeStmt *regassignStmt = static_cast<AssignMeStmt *>(defStmt);
738 rhs = regassignStmt->GetRHS();
739 } else {
740 CHECK_FATAL(false, "impossible");
741 }
742 DEBUG_ASSERT(expr2Nodes.find(rhs) != expr2Nodes.end(), "impossible");
743 expr = *rhs;
744 }
745 MapleSet<EACGBaseNode *> &nodesTmp = *expr2Nodes[&expr];
746
747 for (EACGBaseNode *node : nodesTmp) {
748 for (EACGObjectNode *obj : node->GetPointsToSet()) {
749 if (obj->GetEAStatus() != kNoEscape && obj->GetEAStatus() != kReturnEscape) {
750 return false;
751 }
752 }
753 }
754 return true;
755 }
756
GetCallSiteArgNodeVector(uint32 callSite)757 MapleVector<EACGBaseNode *> *EAConnectionGraph::GetCallSiteArgNodeVector(uint32 callSite)
758 {
759 CHECK_FATAL(callSite2Nodes.find(callSite) != callSite2Nodes.end(), "find failed");
760 ASSERT_NOT_NULL(callSite2Nodes[callSite]);
761 return callSite2Nodes[callSite];
762 }
763
764 // if we have scc of connection graph, it will be more efficient.
PropogateEAStatus()765 void EAConnectionGraph::PropogateEAStatus()
766 {
767 bool oldStatus = CGHasUpdated();
768 do {
769 UnSetCGUpdateFlag();
770 for (EACGBaseNode *node : nodes) {
771 if (node == nullptr) {
772 continue;
773 }
774 if (node->IsObjectNode()) {
775 EACGObjectNode *obj = static_cast<EACGObjectNode *>(node);
776 for (auto fieldPair : obj->GetFieldNodeMap()) {
777 EACGBaseNode *field = fieldPair.second;
778 (void)field->UpdateEAStatus(obj->GetEAStatus());
779 }
780 } else {
781 for (EACGBaseNode *pointsToNode : node->GetPointsToSet()) {
782 (void)pointsToNode->UpdateEAStatus(node->GetEAStatus());
783 }
784 }
785 }
786 DEBUG_ASSERT(!CGHasUpdated(), "must be Updated");
787 } while (CGHasUpdated());
788 RestoreStatus(oldStatus);
789 }
790
GetFuncArgNodeVector() const791 const MapleVector<EACGBaseNode *> *EAConnectionGraph::GetFuncArgNodeVector() const
792 {
793 return &funcArgNodes;
794 }
795
796 // this func is called from callee context
UpdateEACGFromCaller(const MapleVector<EACGBaseNode * > & callerCallSiteArg,const MapleVector<EACGBaseNode * > & calleeFuncArg)797 void EAConnectionGraph::UpdateEACGFromCaller(const MapleVector<EACGBaseNode *> &callerCallSiteArg,
798 const MapleVector<EACGBaseNode *> &calleeFuncArg)
799 {
800 DEBUG_ASSERT(abs(static_cast<int>(callerCallSiteArg.size()) - static_cast<int>(calleeFuncArg.size())) <= 1,
801 "greater than");
802
803 UnSetCGUpdateFlag();
804 for (uint32 i = 0; i < callerCallSiteArg.size(); ++i) {
805 EACGBaseNode *callerNode = callerCallSiteArg[i];
806 ASSERT_NOT_NULL(callerNode);
807 DEBUG_ASSERT(callerNode->IsActualNode(), "must be ActualNode");
808 CHECK_FATAL(callerCallSiteArg.size() - 1, "must not be zero");
809 if ((i == callerCallSiteArg.size() - 1) && static_cast<EACGActualNode *>(callerNode)->IsReturn()) {
810 continue;
811 }
812 bool hasGlobalEA = false;
813 for (EACGObjectNode *obj : callerNode->GetPointsToSet()) {
814 if (obj->GetEAStatus() == kGlobalEscape) {
815 hasGlobalEA = true;
816 break;
817 }
818 }
819 if (hasGlobalEA) {
820 EACGBaseNode *calleeNode = (calleeFuncArg)[i];
821 for (EACGObjectNode *obj : calleeNode->GetPointsToSet()) {
822 (void)obj->UpdateEAStatus(kGlobalEscape);
823 }
824 }
825 }
826 if (CGHasUpdated()) {
827 PropogateEAStatus();
828 }
829 TrimGlobalNode();
830 }
831
DumpDotFile(const IRMap * irMap,bool dumpPt,MapleVector<EACGBaseNode * > * dumpVec)832 void EAConnectionGraph::DumpDotFile(const IRMap *irMap, bool dumpPt, MapleVector<EACGBaseNode *> *dumpVec)
833 {
834 if (dumpVec == nullptr) {
835 dumpVec = &nodes;
836 }
837 std::filebuf fb;
838 std::string outFile = GlobalTables::GetStrTable().GetStringFromStrIdx(funcStIdx) + "-connectiongraph.dot";
839 fb.open(outFile, std::ios::trunc | std::ios::out);
840 CHECK_FATAL(fb.is_open(), "open file failed");
841 std::ostream cgDotFile(&fb);
842 cgDotFile << "digraph connectiongraph{\n";
843 std::map<EACGBaseNode *, bool> dumped;
844 for (auto node : nodes) {
845 dumped[node] = false;
846 }
847 for (EACGBaseNode *node : *dumpVec) {
848 if (node == nullptr) {
849 continue;
850 }
851 if (dumped[node]) {
852 continue;
853 }
854 node->DumpDotFile(cgDotFile, dumped, dumpPt, irMap);
855 dumped[node] = true;
856 }
857 cgDotFile << "}\n";
858 fb.close();
859 }
860
CountObjEAStatus() const861 void EAConnectionGraph::CountObjEAStatus() const
862 {
863 int sum = 0;
864 int eaCount[4] = {0}; // There are 4 EAStatus.
865 for (EACGBaseNode *node : nodes) {
866 if (node == nullptr) {
867 continue;
868 }
869
870 if (node->IsObjectNode()) {
871 EACGObjectNode *objNode = static_cast<EACGObjectNode *>(node);
872 if (!objNode->IsPhantom()) {
873 CHECK_FATAL(objNode->locInfo != nullptr, "Impossible");
874 MIRType *type = nullptr;
875 const MeExpr *expr = objNode->GetMeExpr();
876 CHECK_FATAL(expr != nullptr, "Impossible");
877 if (expr->GetOp() == OP_gcmalloc || expr->GetOp() == OP_gcpermalloc) {
878 TyIdx tyIdx = static_cast<const GcmallocMeExpr *>(expr)->GetTyIdx();
879 type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
880 } else {
881 TyIdx tyIdx = static_cast<const OpMeExpr *>(expr)->GetTyIdx();
882 type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
883 }
884 LogInfo::MapleLogger() << "[LOCATION] [" << objNode->locInfo->GetModName() << " "
885 << objNode->locInfo->GetFileId() << " " << objNode->locInfo->GetLineId() << " "
886 << EscapeName(objNode->GetEAStatus()) << " " << expr->GetExprID() << " ";
887 type->Dump(0, false);
888 LogInfo::MapleLogger() << "]\n";
889 ++sum;
890 ++eaCount[node->GetEAStatus()];
891 }
892 }
893 }
894 LogInfo::MapleLogger() << "[gcmalloc object statistics] "
895 << GlobalTables::GetStrTable().GetStringFromStrIdx(funcStIdx) << " "
896 << "Gcmallocs: " << sum << " "
897 << "NoEscape: " << eaCount[kNoEscape] << " "
898 << "RetEscape: " << eaCount[kReturnEscape] << " "
899 << "ArgEscape: " << eaCount[kArgumentEscape] << " "
900 << "GlobalEscape: " << eaCount[kGlobalEscape] << "\n";
901 }
902
RestoreStatus(bool old)903 void EAConnectionGraph::RestoreStatus(bool old)
904 {
905 if (old) {
906 SetCGHasUpdated();
907 } else {
908 UnSetCGUpdateFlag();
909 }
910 }
911
912 // Update caller's ConnectionGraph using callee's summary information.
913 // If the callee's summary is not found, we just mark all the pointsTo nodes of caller's actual node to GlobalEscape.
914 // Otherwise, we do these steps:
915 //
916 // 1, update caller nodes using callee's summary, new node might be added into caller's CG in this step.
917 //
918 // 2, update caller edges using callee's summary, new points-to edge might be added into caller's CG in this step.
MergeCG(MapleVector<EACGBaseNode * > & caller,const MapleVector<EACGBaseNode * > * callee)919 bool EAConnectionGraph::MergeCG(MapleVector<EACGBaseNode *> &caller, const MapleVector<EACGBaseNode *> *callee)
920 {
921 TrimGlobalNode();
922 bool cgChanged = false;
923 bool oldStatus = CGHasUpdated();
924 UnSetCGUpdateFlag();
925 if (callee == nullptr) {
926 for (EACGBaseNode *actualInCaller : caller) {
927 for (EACGObjectNode *p : actualInCaller->GetPointsToSet()) {
928 (void)p->UpdateEAStatus(EAStatus::kGlobalEscape);
929 }
930 }
931 cgChanged = CGHasUpdated();
932 if (!cgChanged) {
933 RestoreStatus(oldStatus);
934 }
935 TrimGlobalNode();
936 return cgChanged;
937 }
938 size_t callerSize = caller.size();
939 size_t calleeSize = callee->size();
940 if (callerSize > calleeSize) {
941 DEBUG_ASSERT((callerSize - calleeSize) <= 1, "must be one in EAConnectionGraph::MergeCG()");
942 } else {
943 DEBUG_ASSERT((calleeSize - callerSize) <= 1, "must be one in EAConnectionGraph::MergeCG()");
944 }
945 if (callerSize == 0 || calleeSize == 0) {
946 cgChanged = CGHasUpdated();
947 if (!cgChanged) {
948 RestoreStatus(oldStatus);
949 }
950 return cgChanged;
951 }
952 if ((callerSize != calleeSize) &&
953 (callerSize != calleeSize + 1 || static_cast<EACGActualNode *>(callee->back())->IsReturn()) &&
954 (callerSize != calleeSize - 1 || !static_cast<EACGActualNode *>(callee->back())->IsReturn())) {
955 DEBUG_ASSERT(false, "Impossible");
956 }
957
958 callee2Caller.clear();
959 UpdateCallerNodes(caller, *callee);
960 UpdateCallerEdges();
961 UpdateCallerRetNode(caller, *callee);
962 callee2Caller.clear();
963
964 cgChanged = CGHasUpdated();
965 if (!cgChanged) {
966 RestoreStatus(oldStatus);
967 }
968 TrimGlobalNode();
969 return cgChanged;
970 }
971
AddMaps2Object(EACGObjectNode * caller,EACGObjectNode * callee)972 void EAConnectionGraph::AddMaps2Object(EACGObjectNode *caller, EACGObjectNode *callee)
973 {
974 if (callee2Caller.find(callee) == callee2Caller.end()) {
975 std::set<EACGObjectNode *> callerSet;
976 callee2Caller[callee] = callerSet;
977 }
978 (void)callee2Caller[callee].insert(caller);
979 }
980
UpdateCallerRetNode(MapleVector<EACGBaseNode * > & caller,const MapleVector<EACGBaseNode * > & callee)981 void EAConnectionGraph::UpdateCallerRetNode(MapleVector<EACGBaseNode *> &caller,
982 const MapleVector<EACGBaseNode *> &callee)
983 {
984 EACGActualNode *lastInCaller = static_cast<EACGActualNode *>(caller.back());
985 EACGActualNode *lastInCallee = static_cast<EACGActualNode *>(callee.back());
986 if (!lastInCaller->IsReturn()) {
987 return;
988 }
989 CHECK_FATAL(lastInCaller->GetOutSet().size() == 1, "Impossible");
990 for (EACGBaseNode *callerRetNode : lastInCaller->GetOutSet()) {
991 for (EACGObjectNode *calleeRetNode : lastInCallee->GetPointsToSet()) {
992 for (EACGObjectNode *objInCaller : callee2Caller[calleeRetNode]) {
993 auto pointsToSet = callerRetNode->GetPointsToSet();
994 if (pointsToSet.find(objInCaller) == pointsToSet.end()) {
995 (void)callerRetNode->AddOutNode(*objInCaller);
996 }
997 }
998 }
999 }
1000 }
1001
1002 // Update caller node by adding some nodes which are mapped from callee.
UpdateCallerNodes(const MapleVector<EACGBaseNode * > & caller,const MapleVector<EACGBaseNode * > & callee)1003 void EAConnectionGraph::UpdateCallerNodes(const MapleVector<EACGBaseNode *> &caller,
1004 const MapleVector<EACGBaseNode *> &callee)
1005 {
1006 const size_t callerSize = caller.size();
1007 const size_t calleeSize = callee.size();
1008 const size_t actualCount = ((callerSize < calleeSize) ? callerSize : calleeSize);
1009 bool firstTime = true;
1010
1011 for (size_t i = 0; i < actualCount; ++i) {
1012 EACGBaseNode *actualInCaller = caller.at(i);
1013 EACGBaseNode *actualInCallee = callee.at(i);
1014 UpdateNodes(*actualInCallee, *actualInCaller, firstTime);
1015 }
1016 }
1017
1018 // Update caller edges using information from callee.
UpdateCallerEdges()1019 void EAConnectionGraph::UpdateCallerEdges()
1020 {
1021 std::set<EACGObjectNode *> set;
1022 for (auto pair : callee2Caller) {
1023 (void)set.insert(pair.first);
1024 }
1025 for (EACGObjectNode *p : set) {
1026 for (auto tempPair : p->GetFieldNodeMap()) {
1027 int32 fieldID = tempPair.first;
1028 EACGBaseNode *fieldNode = tempPair.second;
1029 for (EACGObjectNode *q : fieldNode->GetPointsToSet()) {
1030 UpdateCallerEdgesInternal(p, fieldID, q);
1031 }
1032 }
1033 }
1034 }
1035
1036 // Update caller edges using information of given ObjectNode from callee.
UpdateCallerEdgesInternal(EACGObjectNode * node1,int32 fieldID,EACGObjectNode * node2)1037 void EAConnectionGraph::UpdateCallerEdgesInternal(EACGObjectNode *node1, int32 fieldID, EACGObjectNode *node2)
1038 {
1039 CHECK_FATAL(callee2Caller.find(node1) != callee2Caller.end(), "find failed");
1040 CHECK_FATAL(callee2Caller.find(node2) != callee2Caller.end(), "find failed");
1041 for (EACGObjectNode *p1 : callee2Caller[node1]) {
1042 for (EACGObjectNode *q1 : callee2Caller[node2]) {
1043 EACGFieldNode *fieldNode = p1->GetFieldNodeFromIdx(fieldID);
1044 if (fieldNode == nullptr) {
1045 CHECK_NULL_FATAL(node1);
1046 fieldNode = node1->GetFieldNodeFromIdx(fieldID);
1047 CHECK_FATAL(fieldNode != nullptr, "fieldNode must not be nullptr because we have handled it before!");
1048 CHECK_FATAL(fieldNode->IsBelongTo(this), "must be belong to this");
1049 (void)p1->AddOutNode(*fieldNode);
1050 }
1051 (void)fieldNode->AddOutNode(*q1);
1052 }
1053 }
1054 }
1055
UpdateNodes(const EACGBaseNode & actualInCallee,EACGBaseNode & actualInCaller,bool firstTime)1056 void EAConnectionGraph::UpdateNodes(const EACGBaseNode &actualInCallee, EACGBaseNode &actualInCaller, bool firstTime)
1057 {
1058 DEBUG_ASSERT(actualInCallee.GetPointsToSet().size() > 0, "actualInCallee->GetPointsToSet().size() must gt 0!");
1059 for (EACGObjectNode *objInCallee : actualInCallee.GetPointsToSet()) {
1060 if (actualInCaller.GetPointsToSet().size() == 0) {
1061 std::set<EACGObjectNode *> &mapsTo = callee2Caller[objInCallee];
1062 if (mapsTo.size() > 0) {
1063 for (EACGObjectNode *temp : mapsTo) {
1064 (void)actualInCaller.AddOutNode(*temp);
1065 }
1066 } else if (objInCallee->IsBelongTo(this)) {
1067 DEBUG_ASSERT(false, "must be belong to this");
1068 } else {
1069 EACGObjectNode *phantom = CreateObjectNode(nullptr, actualInCaller.GetEAStatus(), true, TyIdx(0));
1070 ASSERT_NOT_NULL(phantom);
1071 (void)actualInCaller.AddOutNode(*phantom);
1072 AddMaps2Object(phantom, objInCallee);
1073 UpdateCallerWithCallee(*phantom, *objInCallee, firstTime);
1074 }
1075 } else {
1076 for (EACGObjectNode *objInCaller : actualInCaller.GetPointsToSet()) {
1077 std::set<EACGObjectNode *> &mapsTo = callee2Caller[objInCallee];
1078 if (mapsTo.find(objInCaller) == mapsTo.end()) {
1079 AddMaps2Object(objInCaller, objInCallee);
1080 UpdateCallerWithCallee(*objInCaller, *objInCallee, firstTime);
1081 }
1082 }
1083 }
1084 }
1085 }
1086
1087 // The escape state of the nodes in MapsTo(which is the object node in caller) is marked
1088 // GlobalEscape if the escape state of object node in callee is GlobalEscape.
1089 // Otherwise, the escape state of the caller nodes is not affected.
UpdateCallerWithCallee(EACGObjectNode & objInCaller,const EACGObjectNode & objInCallee,bool firstTime)1090 void EAConnectionGraph::UpdateCallerWithCallee(EACGObjectNode &objInCaller, const EACGObjectNode &objInCallee,
1091 bool firstTime)
1092 {
1093 if (objInCallee.GetEAStatus() == EAStatus::kGlobalEscape) {
1094 (void)objInCaller.UpdateEAStatus(EAStatus::kGlobalEscape);
1095 }
1096
1097 // At this moment, a node in caller is mapped to the corresponding node in callee,
1098 // we need make sure that all the field nodes also exist in caller. If not,
1099 // we create both the field node and the phantom object node it should point to for the caller.
1100 for (auto tempPair : objInCallee.GetFieldNodeMap()) {
1101 EACGFieldNode *fieldInCaller = objInCaller.GetFieldNodeFromIdx(tempPair.first);
1102 EACGFieldNode *fieldInCallee = tempPair.second;
1103 if (fieldInCaller == nullptr && fieldInCallee->IsBelongTo(this)) {
1104 (void)objInCaller.AddOutNode(*fieldInCallee);
1105 }
1106 fieldInCaller = GetOrCreateFieldNodeFromIdx(objInCaller, tempPair.first);
1107 UpdateNodes(*fieldInCallee, *fieldInCaller, firstTime);
1108 }
1109 }
1110
GetOrCreateFieldNodeFromIdx(EACGObjectNode & obj,int32 fieldID)1111 EACGFieldNode *EAConnectionGraph::GetOrCreateFieldNodeFromIdx(EACGObjectNode &obj, int32 fieldID)
1112 {
1113 EACGFieldNode *ret = obj.GetFieldNodeFromIdx(fieldID);
1114 if (ret == nullptr) {
1115 // this node is always phantom
1116 ret = CreateFieldNode(nullptr, obj.GetEAStatus(), fieldID, &obj, true);
1117 }
1118 return ret;
1119 }
1120 } // namespace maple
1121