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 eaCG->nodes[id - 1] = nullptr;
220 return true;
221 }
222
PropagateEAStatusForNode(const EACGBaseNode * subRoot) const223 void EACGObjectNode::PropagateEAStatusForNode(const EACGBaseNode *subRoot) const
224 {
225 for (auto fieldNodePair : fieldNodes) {
226 EACGFieldNode *field = fieldNodePair.second;
227 (void)field->UpdateEAStatus(eaStatus);
228 }
229 }
230
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)231 void EACGObjectNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
232 const IRMap *irMap)
233 {
234 if (dumped[this]) {
235 return;
236 }
237 dumped[this] = true;
238
239 std::string name = GetName(nullptr);
240 std::string label;
241 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;
272 label = GetName(irMap) + " Reference\\n";
273 if (IsStaticRef()) {
274 label += "Static\\n";
275 }
276 std::string color;
277 GetNodeFormatInDot(label, color);
278 fout << name << " [shape=ellipse, label=\"" << label << "\", fontcolor=" << color << "];"
279 << "\n";
280 if (dumpPt) {
281 for (auto obj : pointsTo) {
282 fout << name << "->" << obj->GetName(nullptr) << ";"
283 << "\n";
284 }
285 for (auto obj : pointsTo) {
286 obj->DumpDotFile(fout, dumped, dumpPt, irMap);
287 }
288 } else {
289 for (auto outNode : out) {
290 std::string edgeStyle;
291 if (!outNode->IsObjectNode()) {
292 edgeStyle = " [style =\"dotted\"]";
293 }
294 fout << name << "->" << outNode->GetName(nullptr) << edgeStyle << ";"
295 << "\n";
296 }
297 for (auto outNode : out) {
298 outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
299 }
300 }
301 }
302
ReplaceByGlobalNode()303 bool EACGRefNode::ReplaceByGlobalNode()
304 {
305 for (EACGBaseNode *inNode : in) {
306 DEBUG_ASSERT(inNode->id > 3, "must be greater than three"); // the least valid idx is 3
307 (void)inNode->out.erase(this);
308 (void)inNode->out.insert(eaCG->GetGlobalReference());
309 }
310 in.clear();
311 for (EACGBaseNode *outNode : out) {
312 (void)outNode->in.erase(this);
313 }
314 out.clear();
315 for (EACGObjectNode *base : pointsTo) {
316 base->EraseNodeFromPointsBy(this);
317 }
318 pointsTo.clear();
319 if (meExpr != nullptr) {
320 eaCG->expr2Nodes[meExpr]->clear();
321 eaCG->expr2Nodes[meExpr]->insert(eaCG->GetGlobalReference());
322 }
323 DEBUG_ASSERT(eaCG->nodes[id - 1] == this, "must be this");
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;
337 label = GetName(irMap) + "\\nPointer Indirect Level : " + std::to_string(indirectLevel) + "\\n";
338 std::string color;
339 GetNodeFormatInDot(label, color);
340 fout << name << " [shape=ellipse, label=\"" << label << "\", fontcolor=" << color << "];"
341 << "\n";
342 for (EACGBaseNode *outNode : out) {
343 fout << name << "->" << outNode->GetName(nullptr) << " [style =\"dotted\", color = \"blue\"];"
344 << "\n";
345 }
346 for (auto outNode : out) {
347 outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
348 }
349 }
350
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)351 void EACGActualNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
352 const IRMap *irMap)
353 {
354 if (dumped[this]) {
355 return;
356 }
357 dumped[this] = true;
358
359 std::string name = GetName(nullptr);
360 std::string label;
361 if (IsReturn()) {
362 label = GetName(irMap) + "\\nRet Idx : " + std::to_string(GetArgIndex()) + "\\n";
363 } else {
364 label = GetName(irMap) + "\\nArg Idx : " + std::to_string(GetArgIndex()) +
365 " Call Site : " + std::to_string(GetCallSite()) + "\\n";
366 }
367 std::string style;
368 if (IsPhantom()) {
369 style = "dotted";
370 } else {
371 style = "bold";
372 }
373 std::string color;
374 GetNodeFormatInDot(label, color);
375 fout << name << " [shape=ellipse, label=\"" << label << "\", fontcolor=" << color << ", style=" << style << "];\n";
376 if (dumpPt) {
377 for (auto obj : pointsTo) {
378 fout << name << "->" << obj->GetName(nullptr) << ";\n";
379 }
380 for (auto obj : pointsTo) {
381 obj->DumpDotFile(fout, dumped, dumpPt, irMap);
382 }
383 } else {
384 for (auto outNode : out) {
385 std::string edgeStyle;
386 if (!outNode->IsObjectNode()) {
387 edgeStyle = " [style =\"dotted\"]";
388 }
389 fout << name << "->" << outNode->GetName(nullptr) << edgeStyle << ";\n";
390 }
391 for (auto outNode : out) {
392 outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
393 }
394 }
395 }
396
ReplaceByGlobalNode()397 bool EACGActualNode::ReplaceByGlobalNode()
398 {
399 DEBUG_ASSERT(callSiteInfo == kInvalid, "must be invalid");
400 DEBUG_ASSERT(out.size() == 1, "the size of out must be one");
401 DEBUG_ASSERT(pointsTo.size() == 1, "the size of pointsTo must be one");
402 for (EACGBaseNode *inNode : in) {
403 inNode->out.erase(this);
404 }
405 in.clear();
406 return false;
407 }
408
DumpDotFile(std::ostream & fout,std::map<EACGBaseNode *,bool> & dumped,bool dumpPt,const IRMap * irMap)409 void EACGFieldNode::DumpDotFile(std::ostream &fout, std::map<EACGBaseNode *, bool> &dumped, bool dumpPt,
410 const IRMap *irMap)
411 {
412 if (dumped[this]) {
413 return;
414 }
415 dumped[this] = true;
416 std::string name = GetName(nullptr);
417 std::string label = GetName(irMap) + "\\nFIdx : " + std::to_string(GetFieldID()) + "\\n";
418 std::string color;
419 GetNodeFormatInDot(label, color);
420 std::string style;
421 if (IsPhantom()) {
422 style = "dotted";
423 } else {
424 style = "bold";
425 }
426 fout << name << " [shape=circle, label=\"" << label << "\", fontcolor=" << color << ", style=" << style
427 << ", margin=0];\n";
428 if (dumpPt) {
429 for (auto obj : pointsTo) {
430 fout << name << "->" << obj->GetName(nullptr) << ";\n";
431 }
432 for (auto obj : pointsTo) {
433 obj->DumpDotFile(fout, dumped, dumpPt, irMap);
434 }
435 } else {
436 for (auto outNode : out) {
437 std::string edgeStyle;
438 if (!outNode->IsObjectNode()) {
439 edgeStyle = " [style =\"dotted\"]";
440 }
441 fout << name << "->" << outNode->GetName(nullptr) << edgeStyle << ";\n";
442 }
443 for (auto outNode : out) {
444 outNode->DumpDotFile(fout, dumped, dumpPt, irMap);
445 }
446 }
447 }
448
ReplaceByGlobalNode()449 bool EACGFieldNode::ReplaceByGlobalNode()
450 {
451 for (EACGObjectNode *obj : pointsTo) {
452 obj->pointsBy.erase(this);
453 }
454 pointsTo.clear();
455 (void)pointsTo.insert(eaCG->GetGlobalObject());
456 for (EACGBaseNode *outNode : out) {
457 outNode->in.erase(this);
458 }
459 out.clear();
460 (void)out.insert(eaCG->GetGlobalObject());
461 bool canDelete = true;
462 std::set<EACGObjectNode *> tmp = belongsTo;
463 for (EACGObjectNode *obj : tmp) {
464 if (obj->GetEAStatus() != kGlobalEscape) {
465 canDelete = false;
466 } else {
467 belongsTo.erase(obj);
468 }
469 }
470 if (canDelete) {
471 DEBUG_ASSERT(eaCG->nodes[id - 1] == this, "must be this");
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 EACGActualNode *ret = static_cast<EACGActualNode *>(funcArgNodes[funcArgNodes.size() - 1]);
695 if (ret->IsReturn()) {
696 return ret;
697 }
698 return nullptr;
699 }
700 #ifdef DEBUG
CheckArgNodeOrder(MapleVector<EACGBaseNode * > & funcArgV)701 void EAConnectionGraph::CheckArgNodeOrder(MapleVector<EACGBaseNode *> &funcArgV)
702 {
703 uint8 preIndex = 0;
704 for (size_t i = 0; i < funcArgV.size(); ++i) {
705 DEBUG_ASSERT(funcArgV[i]->IsActualNode(), "must be ActualNode");
706 EACGActualNode *actNode = static_cast<EACGActualNode *>(funcArgV[i]);
707 if (i == funcArgV.size() - 1) {
708 if (actNode->IsReturn()) {
709 continue;
710 } else {
711 DEBUG_ASSERT(actNode->GetArgIndex() >= preIndex, "must be greater than preIndex");
712 }
713 } else {
714 DEBUG_ASSERT(!actNode->IsReturn(), "must be return");
715 DEBUG_ASSERT(actNode->GetArgIndex() >= preIndex, "must be greater than preIndex");
716 }
717 preIndex = actNode->GetArgIndex();
718 }
719 }
720 #endif
ExprCanBeOptimized(MeExpr & expr)721 bool EAConnectionGraph::ExprCanBeOptimized(MeExpr &expr)
722 {
723 if (expr2Nodes.find(&expr) == expr2Nodes.end()) {
724 MeExpr *rhs = nullptr;
725 if (expr.GetMeOp() == kMeOpVar) {
726 DEBUG_ASSERT(static_cast<VarMeExpr *>(&expr)->GetDefBy() == kDefByStmt, "must be kDefByStmt");
727 DEBUG_ASSERT(static_cast<VarMeExpr *>(&expr)->GetDefStmt()->GetOp() == OP_dassign, "must be OP_dassign");
728 MeStmt *defStmt = static_cast<VarMeExpr *>(&expr)->GetDefStmt();
729 DassignMeStmt *dassignStmt = static_cast<DassignMeStmt *>(defStmt);
730 rhs = dassignStmt->GetRHS();
731 } else if (expr.GetMeOp() == kMeOpReg) {
732 DEBUG_ASSERT(static_cast<RegMeExpr *>(&expr)->GetDefBy() == kDefByStmt, "must be kDefByStmt");
733 DEBUG_ASSERT(static_cast<RegMeExpr *>(&expr)->GetDefStmt()->GetOp() == OP_regassign,
734 "must be OP_regassign");
735 MeStmt *defStmt = static_cast<RegMeExpr *>(&expr)->GetDefStmt();
736 AssignMeStmt *regassignStmt = static_cast<AssignMeStmt *>(defStmt);
737 rhs = regassignStmt->GetRHS();
738 } else {
739 CHECK_FATAL(false, "impossible");
740 }
741 DEBUG_ASSERT(expr2Nodes.find(rhs) != expr2Nodes.end(), "impossible");
742 expr = *rhs;
743 }
744 MapleSet<EACGBaseNode *> &nodesTmp = *expr2Nodes[&expr];
745
746 for (EACGBaseNode *node : nodesTmp) {
747 for (EACGObjectNode *obj : node->GetPointsToSet()) {
748 if (obj->GetEAStatus() != kNoEscape && obj->GetEAStatus() != kReturnEscape) {
749 return false;
750 }
751 }
752 }
753 return true;
754 }
755
GetCallSiteArgNodeVector(uint32 callSite)756 MapleVector<EACGBaseNode *> *EAConnectionGraph::GetCallSiteArgNodeVector(uint32 callSite)
757 {
758 CHECK_FATAL(callSite2Nodes.find(callSite) != callSite2Nodes.end(), "find failed");
759 ASSERT_NOT_NULL(callSite2Nodes[callSite]);
760 return callSite2Nodes[callSite];
761 }
762
763 // if we have scc of connection graph, it will be more efficient.
PropogateEAStatus()764 void EAConnectionGraph::PropogateEAStatus()
765 {
766 bool oldStatus = CGHasUpdated();
767 do {
768 UnSetCGUpdateFlag();
769 for (EACGBaseNode *node : nodes) {
770 if (node == nullptr) {
771 continue;
772 }
773 if (node->IsObjectNode()) {
774 EACGObjectNode *obj = static_cast<EACGObjectNode *>(node);
775 for (auto fieldPair : obj->GetFieldNodeMap()) {
776 EACGBaseNode *field = fieldPair.second;
777 (void)field->UpdateEAStatus(obj->GetEAStatus());
778 }
779 } else {
780 for (EACGBaseNode *pointsToNode : node->GetPointsToSet()) {
781 (void)pointsToNode->UpdateEAStatus(node->GetEAStatus());
782 }
783 }
784 }
785 DEBUG_ASSERT(!CGHasUpdated(), "must be Updated");
786 } while (CGHasUpdated());
787 RestoreStatus(oldStatus);
788 }
789
GetFuncArgNodeVector() const790 const MapleVector<EACGBaseNode *> *EAConnectionGraph::GetFuncArgNodeVector() const
791 {
792 return &funcArgNodes;
793 }
794
795 // this func is called from callee context
UpdateEACGFromCaller(const MapleVector<EACGBaseNode * > & callerCallSiteArg,const MapleVector<EACGBaseNode * > & calleeFuncArg)796 void EAConnectionGraph::UpdateEACGFromCaller(const MapleVector<EACGBaseNode *> &callerCallSiteArg,
797 const MapleVector<EACGBaseNode *> &calleeFuncArg)
798 {
799 DEBUG_ASSERT(abs(static_cast<int>(callerCallSiteArg.size()) - static_cast<int>(calleeFuncArg.size())) <= 1,
800 "greater than");
801
802 UnSetCGUpdateFlag();
803 for (uint32 i = 0; i < callerCallSiteArg.size(); ++i) {
804 EACGBaseNode *callerNode = callerCallSiteArg[i];
805 ASSERT_NOT_NULL(callerNode);
806 DEBUG_ASSERT(callerNode->IsActualNode(), "must be ActualNode");
807 if ((i == callerCallSiteArg.size() - 1) && static_cast<EACGActualNode *>(callerNode)->IsReturn()) {
808 continue;
809 }
810 bool hasGlobalEA = false;
811 for (EACGObjectNode *obj : callerNode->GetPointsToSet()) {
812 if (obj->GetEAStatus() == kGlobalEscape) {
813 hasGlobalEA = true;
814 break;
815 }
816 }
817 if (hasGlobalEA) {
818 EACGBaseNode *calleeNode = (calleeFuncArg)[i];
819 for (EACGObjectNode *obj : calleeNode->GetPointsToSet()) {
820 (void)obj->UpdateEAStatus(kGlobalEscape);
821 }
822 }
823 }
824 if (CGHasUpdated()) {
825 PropogateEAStatus();
826 }
827 TrimGlobalNode();
828 }
829
DumpDotFile(const IRMap * irMap,bool dumpPt,MapleVector<EACGBaseNode * > * dumpVec)830 void EAConnectionGraph::DumpDotFile(const IRMap *irMap, bool dumpPt, MapleVector<EACGBaseNode *> *dumpVec)
831 {
832 if (dumpVec == nullptr) {
833 dumpVec = &nodes;
834 }
835 std::filebuf fb;
836 std::string outFile = GlobalTables::GetStrTable().GetStringFromStrIdx(funcStIdx) + "-connectiongraph.dot";
837 fb.open(outFile, std::ios::trunc | std::ios::out);
838 CHECK_FATAL(fb.is_open(), "open file failed");
839 std::ostream cgDotFile(&fb);
840 cgDotFile << "digraph connectiongraph{\n";
841 std::map<EACGBaseNode *, bool> dumped;
842 for (auto node : nodes) {
843 dumped[node] = false;
844 }
845 for (EACGBaseNode *node : *dumpVec) {
846 if (node == nullptr) {
847 continue;
848 }
849 if (dumped[node]) {
850 continue;
851 }
852 node->DumpDotFile(cgDotFile, dumped, dumpPt, irMap);
853 dumped[node] = true;
854 }
855 cgDotFile << "}\n";
856 fb.close();
857 }
858
CountObjEAStatus() const859 void EAConnectionGraph::CountObjEAStatus() const
860 {
861 int sum = 0;
862 int eaCount[4] = {0}; // There are 4 EAStatus.
863 for (EACGBaseNode *node : nodes) {
864 if (node == nullptr) {
865 continue;
866 }
867
868 if (node->IsObjectNode()) {
869 EACGObjectNode *objNode = static_cast<EACGObjectNode *>(node);
870 if (!objNode->IsPhantom()) {
871 CHECK_FATAL(objNode->locInfo != nullptr, "Impossible");
872 MIRType *type = nullptr;
873 const MeExpr *expr = objNode->GetMeExpr();
874 CHECK_FATAL(expr != nullptr, "Impossible");
875 if (expr->GetOp() == OP_gcmalloc || expr->GetOp() == OP_gcpermalloc) {
876 TyIdx tyIdx = static_cast<const GcmallocMeExpr *>(expr)->GetTyIdx();
877 type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
878 } else {
879 TyIdx tyIdx = static_cast<const OpMeExpr *>(expr)->GetTyIdx();
880 type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx);
881 }
882 LogInfo::MapleLogger() << "[LOCATION] [" << objNode->locInfo->GetModName() << " "
883 << objNode->locInfo->GetFileId() << " " << objNode->locInfo->GetLineId() << " "
884 << EscapeName(objNode->GetEAStatus()) << " " << expr->GetExprID() << " ";
885 type->Dump(0, false);
886 LogInfo::MapleLogger() << "]\n";
887 ++sum;
888 ++eaCount[node->GetEAStatus()];
889 }
890 }
891 }
892 LogInfo::MapleLogger() << "[gcmalloc object statistics] "
893 << GlobalTables::GetStrTable().GetStringFromStrIdx(funcStIdx) << " "
894 << "Gcmallocs: " << sum << " "
895 << "NoEscape: " << eaCount[kNoEscape] << " "
896 << "RetEscape: " << eaCount[kReturnEscape] << " "
897 << "ArgEscape: " << eaCount[kArgumentEscape] << " "
898 << "GlobalEscape: " << eaCount[kGlobalEscape] << "\n";
899 }
900
RestoreStatus(bool old)901 void EAConnectionGraph::RestoreStatus(bool old)
902 {
903 if (old) {
904 SetCGHasUpdated();
905 } else {
906 UnSetCGUpdateFlag();
907 }
908 }
909
910 // Update caller's ConnectionGraph using callee's summary information.
911 // If the callee's summary is not found, we just mark all the pointsTo nodes of caller's actual node to GlobalEscape.
912 // Otherwise, we do these steps:
913 //
914 // 1, update caller nodes using callee's summary, new node might be added into caller's CG in this step.
915 //
916 // 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)917 bool EAConnectionGraph::MergeCG(MapleVector<EACGBaseNode *> &caller, const MapleVector<EACGBaseNode *> *callee)
918 {
919 TrimGlobalNode();
920 bool cgChanged = false;
921 bool oldStatus = CGHasUpdated();
922 UnSetCGUpdateFlag();
923 if (callee == nullptr) {
924 for (EACGBaseNode *actualInCaller : caller) {
925 for (EACGObjectNode *p : actualInCaller->GetPointsToSet()) {
926 (void)p->UpdateEAStatus(EAStatus::kGlobalEscape);
927 }
928 }
929 cgChanged = CGHasUpdated();
930 if (!cgChanged) {
931 RestoreStatus(oldStatus);
932 }
933 TrimGlobalNode();
934 return cgChanged;
935 }
936 size_t callerSize = caller.size();
937 size_t calleeSize = callee->size();
938 if (callerSize > calleeSize) {
939 DEBUG_ASSERT((callerSize - calleeSize) <= 1, "must be one in EAConnectionGraph::MergeCG()");
940 } else {
941 DEBUG_ASSERT((calleeSize - callerSize) <= 1, "must be one in EAConnectionGraph::MergeCG()");
942 }
943 if (callerSize == 0 || calleeSize == 0) {
944 cgChanged = CGHasUpdated();
945 if (!cgChanged) {
946 RestoreStatus(oldStatus);
947 }
948 return cgChanged;
949 }
950 if ((callerSize != calleeSize) &&
951 (callerSize != calleeSize + 1 || static_cast<EACGActualNode *>(callee->back())->IsReturn()) &&
952 (callerSize != calleeSize - 1 || !static_cast<EACGActualNode *>(callee->back())->IsReturn())) {
953 DEBUG_ASSERT(false, "Impossible");
954 }
955
956 callee2Caller.clear();
957 UpdateCallerNodes(caller, *callee);
958 UpdateCallerEdges();
959 UpdateCallerRetNode(caller, *callee);
960 callee2Caller.clear();
961
962 cgChanged = CGHasUpdated();
963 if (!cgChanged) {
964 RestoreStatus(oldStatus);
965 }
966 TrimGlobalNode();
967 return cgChanged;
968 }
969
AddMaps2Object(EACGObjectNode * caller,EACGObjectNode * callee)970 void EAConnectionGraph::AddMaps2Object(EACGObjectNode *caller, EACGObjectNode *callee)
971 {
972 if (callee2Caller.find(callee) == callee2Caller.end()) {
973 std::set<EACGObjectNode *> callerSet;
974 callee2Caller[callee] = callerSet;
975 }
976 (void)callee2Caller[callee].insert(caller);
977 }
978
UpdateCallerRetNode(MapleVector<EACGBaseNode * > & caller,const MapleVector<EACGBaseNode * > & callee)979 void EAConnectionGraph::UpdateCallerRetNode(MapleVector<EACGBaseNode *> &caller,
980 const MapleVector<EACGBaseNode *> &callee)
981 {
982 EACGActualNode *lastInCaller = static_cast<EACGActualNode *>(caller.back());
983 EACGActualNode *lastInCallee = static_cast<EACGActualNode *>(callee.back());
984 if (!lastInCaller->IsReturn()) {
985 return;
986 }
987 CHECK_FATAL(lastInCaller->GetOutSet().size() == 1, "Impossible");
988 for (EACGBaseNode *callerRetNode : lastInCaller->GetOutSet()) {
989 for (EACGObjectNode *calleeRetNode : lastInCallee->GetPointsToSet()) {
990 for (EACGObjectNode *objInCaller : callee2Caller[calleeRetNode]) {
991 auto pointsToSet = callerRetNode->GetPointsToSet();
992 if (pointsToSet.find(objInCaller) == pointsToSet.end()) {
993 (void)callerRetNode->AddOutNode(*objInCaller);
994 }
995 }
996 }
997 }
998 }
999
1000 // Update caller node by adding some nodes which are mapped from callee.
UpdateCallerNodes(const MapleVector<EACGBaseNode * > & caller,const MapleVector<EACGBaseNode * > & callee)1001 void EAConnectionGraph::UpdateCallerNodes(const MapleVector<EACGBaseNode *> &caller,
1002 const MapleVector<EACGBaseNode *> &callee)
1003 {
1004 const size_t callerSize = caller.size();
1005 const size_t calleeSize = callee.size();
1006 const size_t actualCount = ((callerSize < calleeSize) ? callerSize : calleeSize);
1007 bool firstTime = true;
1008
1009 for (size_t i = 0; i < actualCount; ++i) {
1010 EACGBaseNode *actualInCaller = caller.at(i);
1011 EACGBaseNode *actualInCallee = callee.at(i);
1012 UpdateNodes(*actualInCallee, *actualInCaller, firstTime);
1013 }
1014 }
1015
1016 // Update caller edges using information from callee.
UpdateCallerEdges()1017 void EAConnectionGraph::UpdateCallerEdges()
1018 {
1019 std::set<EACGObjectNode *> set;
1020 for (auto pair : callee2Caller) {
1021 (void)set.insert(pair.first);
1022 }
1023 for (EACGObjectNode *p : set) {
1024 for (auto tempPair : p->GetFieldNodeMap()) {
1025 int32 fieldID = tempPair.first;
1026 EACGBaseNode *fieldNode = tempPair.second;
1027 for (EACGObjectNode *q : fieldNode->GetPointsToSet()) {
1028 UpdateCallerEdgesInternal(p, fieldID, q);
1029 }
1030 }
1031 }
1032 }
1033
1034 // Update caller edges using information of given ObjectNode from callee.
UpdateCallerEdgesInternal(EACGObjectNode * node1,int32 fieldID,EACGObjectNode * node2)1035 void EAConnectionGraph::UpdateCallerEdgesInternal(EACGObjectNode *node1, int32 fieldID, EACGObjectNode *node2)
1036 {
1037 CHECK_FATAL(callee2Caller.find(node1) != callee2Caller.end(), "find failed");
1038 CHECK_FATAL(callee2Caller.find(node2) != callee2Caller.end(), "find failed");
1039 for (EACGObjectNode *p1 : callee2Caller[node1]) {
1040 for (EACGObjectNode *q1 : callee2Caller[node2]) {
1041 EACGFieldNode *fieldNode = p1->GetFieldNodeFromIdx(fieldID);
1042 if (fieldNode == nullptr) {
1043 CHECK_NULL_FATAL(node1);
1044 fieldNode = node1->GetFieldNodeFromIdx(fieldID);
1045 CHECK_FATAL(fieldNode != nullptr, "fieldNode must not be nullptr because we have handled it before!");
1046 CHECK_FATAL(fieldNode->IsBelongTo(this), "must be belong to this");
1047 (void)p1->AddOutNode(*fieldNode);
1048 }
1049 (void)fieldNode->AddOutNode(*q1);
1050 }
1051 }
1052 }
1053
UpdateNodes(const EACGBaseNode & actualInCallee,EACGBaseNode & actualInCaller,bool firstTime)1054 void EAConnectionGraph::UpdateNodes(const EACGBaseNode &actualInCallee, EACGBaseNode &actualInCaller, bool firstTime)
1055 {
1056 DEBUG_ASSERT(actualInCallee.GetPointsToSet().size() > 0, "actualInCallee->GetPointsToSet().size() must gt 0!");
1057 for (EACGObjectNode *objInCallee : actualInCallee.GetPointsToSet()) {
1058 if (actualInCaller.GetPointsToSet().size() == 0) {
1059 std::set<EACGObjectNode *> &mapsTo = callee2Caller[objInCallee];
1060 if (mapsTo.size() > 0) {
1061 for (EACGObjectNode *temp : mapsTo) {
1062 (void)actualInCaller.AddOutNode(*temp);
1063 }
1064 } else if (objInCallee->IsBelongTo(this)) {
1065 DEBUG_ASSERT(false, "must be belong to this");
1066 } else {
1067 EACGObjectNode *phantom = CreateObjectNode(nullptr, actualInCaller.GetEAStatus(), true, TyIdx(0));
1068 (void)actualInCaller.AddOutNode(*phantom);
1069 AddMaps2Object(phantom, objInCallee);
1070 UpdateCallerWithCallee(*phantom, *objInCallee, firstTime);
1071 }
1072 } else {
1073 for (EACGObjectNode *objInCaller : actualInCaller.GetPointsToSet()) {
1074 std::set<EACGObjectNode *> &mapsTo = callee2Caller[objInCallee];
1075 if (mapsTo.find(objInCaller) == mapsTo.end()) {
1076 AddMaps2Object(objInCaller, objInCallee);
1077 UpdateCallerWithCallee(*objInCaller, *objInCallee, firstTime);
1078 }
1079 }
1080 }
1081 }
1082 }
1083
1084 // The escape state of the nodes in MapsTo(which is the object node in caller) is marked
1085 // GlobalEscape if the escape state of object node in callee is GlobalEscape.
1086 // Otherwise, the escape state of the caller nodes is not affected.
UpdateCallerWithCallee(EACGObjectNode & objInCaller,const EACGObjectNode & objInCallee,bool firstTime)1087 void EAConnectionGraph::UpdateCallerWithCallee(EACGObjectNode &objInCaller, const EACGObjectNode &objInCallee,
1088 bool firstTime)
1089 {
1090 if (objInCallee.GetEAStatus() == EAStatus::kGlobalEscape) {
1091 (void)objInCaller.UpdateEAStatus(EAStatus::kGlobalEscape);
1092 }
1093
1094 // At this moment, a node in caller is mapped to the corresponding node in callee,
1095 // we need make sure that all the field nodes also exist in caller. If not,
1096 // we create both the field node and the phantom object node it should point to for the caller.
1097 for (auto tempPair : objInCallee.GetFieldNodeMap()) {
1098 EACGFieldNode *fieldInCaller = objInCaller.GetFieldNodeFromIdx(tempPair.first);
1099 EACGFieldNode *fieldInCallee = tempPair.second;
1100 if (fieldInCaller == nullptr && fieldInCallee->IsBelongTo(this)) {
1101 (void)objInCaller.AddOutNode(*fieldInCallee);
1102 }
1103 fieldInCaller = GetOrCreateFieldNodeFromIdx(objInCaller, tempPair.first);
1104 UpdateNodes(*fieldInCallee, *fieldInCaller, firstTime);
1105 }
1106 }
1107
GetOrCreateFieldNodeFromIdx(EACGObjectNode & obj,int32 fieldID)1108 EACGFieldNode *EAConnectionGraph::GetOrCreateFieldNodeFromIdx(EACGObjectNode &obj, int32 fieldID)
1109 {
1110 EACGFieldNode *ret = obj.GetFieldNodeFromIdx(fieldID);
1111 if (ret == nullptr) {
1112 // this node is always phantom
1113 ret = CreateFieldNode(nullptr, obj.GetEAStatus(), fieldID, &obj, true);
1114 }
1115 return ret;
1116 }
1117 } // namespace maple
1118