1023 if (addp2 != NULL) { |
1028 if (addp2 != NULL) { |
1024 assert(alloc->is_AllocateArray(),"array allocation was expected"); |
1029 assert(alloc->is_AllocateArray(),"array allocation was expected"); |
1025 alloc_worklist.append_if_missing(addp2); |
1030 alloc_worklist.append_if_missing(addp2); |
1026 } |
1031 } |
1027 alloc_worklist.append_if_missing(use); |
1032 alloc_worklist.append_if_missing(use); |
1028 } else if (use->is_Initialize()) { |
1033 } else if (use->is_MemBar()) { |
1029 memnode_worklist.append_if_missing(use); |
1034 memnode_worklist.append_if_missing(use); |
1030 } |
1035 } |
1031 } |
1036 } |
1032 } |
1037 } |
1033 } else if (n->is_AddP()) { |
1038 } else if (n->is_AddP()) { |
1034 ptset.Clear(); |
1039 ptset.Clear(); |
1035 PointsTo(ptset, get_addp_base(n), igvn); |
1040 PointsTo(ptset, get_addp_base(n), igvn); |
1036 assert(ptset.Size() == 1, "AddP address is unique"); |
1041 assert(ptset.Size() == 1, "AddP address is unique"); |
1037 uint elem = ptset.getelem(); // Allocation node's index |
1042 uint elem = ptset.getelem(); // Allocation node's index |
1038 if (elem == _phantom_object) |
1043 if (elem == _phantom_object) { |
|
1044 assert(false, "escaped allocation"); |
1039 continue; // Assume the value was set outside this method. |
1045 continue; // Assume the value was set outside this method. |
|
1046 } |
1040 Node *base = get_map(elem); // CheckCastPP node |
1047 Node *base = get_map(elem); // CheckCastPP node |
1041 if (!split_AddP(n, base, igvn)) continue; // wrong type |
1048 if (!split_AddP(n, base, igvn)) continue; // wrong type from dead path |
1042 tinst = igvn->type(base)->isa_oopptr(); |
1049 tinst = igvn->type(base)->isa_oopptr(); |
1043 } else if (n->is_Phi() || |
1050 } else if (n->is_Phi() || |
1044 n->is_CheckCastPP() || |
1051 n->is_CheckCastPP() || |
1045 n->is_EncodeP() || |
1052 n->is_EncodeP() || |
1046 n->is_DecodeN() || |
1053 n->is_DecodeN() || |
1051 } |
1058 } |
1052 ptset.Clear(); |
1059 ptset.Clear(); |
1053 PointsTo(ptset, n, igvn); |
1060 PointsTo(ptset, n, igvn); |
1054 if (ptset.Size() == 1) { |
1061 if (ptset.Size() == 1) { |
1055 uint elem = ptset.getelem(); // Allocation node's index |
1062 uint elem = ptset.getelem(); // Allocation node's index |
1056 if (elem == _phantom_object) |
1063 if (elem == _phantom_object) { |
|
1064 assert(false, "escaped allocation"); |
1057 continue; // Assume the value was set outside this method. |
1065 continue; // Assume the value was set outside this method. |
|
1066 } |
1058 Node *val = get_map(elem); // CheckCastPP node |
1067 Node *val = get_map(elem); // CheckCastPP node |
1059 TypeNode *tn = n->as_Type(); |
1068 TypeNode *tn = n->as_Type(); |
1060 tinst = igvn->type(val)->isa_oopptr(); |
1069 tinst = igvn->type(val)->isa_oopptr(); |
1061 assert(tinst != NULL && tinst->is_known_instance() && |
1070 assert(tinst != NULL && tinst->is_known_instance() && |
1062 (uint)tinst->instance_id() == elem , "instance type expected."); |
1071 (uint)tinst->instance_id() == elem , "instance type expected."); |
1080 igvn->set_type(tn, tn_type); |
1088 igvn->set_type(tn, tn_type); |
1081 tn->set_type(tn_type); |
1089 tn->set_type(tn_type); |
1082 igvn->hash_insert(tn); |
1090 igvn->hash_insert(tn); |
1083 record_for_optimizer(n); |
1091 record_for_optimizer(n); |
1084 } else { |
1092 } else { |
1085 continue; // wrong type |
1093 assert(tn_type == TypePtr::NULL_PTR || |
|
1094 tn_t != NULL && !tinst->klass()->is_subtype_of(tn_t->klass()), |
|
1095 "unexpected type"); |
|
1096 continue; // Skip dead path with different type |
1086 } |
1097 } |
1087 } |
1098 } |
1088 } else { |
1099 } else { |
|
1100 debug_only(n->dump();) |
|
1101 assert(false, "EA: unexpected node"); |
1089 continue; |
1102 continue; |
1090 } |
1103 } |
1091 // push users on appropriate worklist |
1104 // push allocation's users on appropriate worklist |
1092 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
1105 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
1093 Node *use = n->fast_out(i); |
1106 Node *use = n->fast_out(i); |
1094 if(use->is_Mem() && use->in(MemNode::Address) == n) { |
1107 if(use->is_Mem() && use->in(MemNode::Address) == n) { |
|
1108 // Load/store to instance's field |
1095 memnode_worklist.append_if_missing(use); |
1109 memnode_worklist.append_if_missing(use); |
1096 } else if (use->is_Initialize()) { |
1110 } else if (use->is_MemBar()) { |
1097 memnode_worklist.append_if_missing(use); |
1111 memnode_worklist.append_if_missing(use); |
1098 } else if (use->is_MergeMem()) { |
|
1099 mergemem_worklist.append_if_missing(use); |
|
1100 } else if (use->is_SafePoint() && tinst != NULL) { |
|
1101 // Look for MergeMem nodes for calls which reference unique allocation |
|
1102 // (through CheckCastPP nodes) even for debug info. |
|
1103 Node* m = use->in(TypeFunc::Memory); |
|
1104 uint iid = tinst->instance_id(); |
|
1105 while (m->is_Proj() && m->in(0)->is_SafePoint() && |
|
1106 m->in(0) != use && !m->in(0)->_idx != iid) { |
|
1107 m = m->in(0)->in(TypeFunc::Memory); |
|
1108 } |
|
1109 if (m->is_MergeMem()) { |
|
1110 mergemem_worklist.append_if_missing(m); |
|
1111 } |
|
1112 } else if (use->is_AddP() && use->outcnt() > 0) { // No dead nodes |
1112 } else if (use->is_AddP() && use->outcnt() > 0) { // No dead nodes |
1113 Node* addp2 = find_second_addp(use, n); |
1113 Node* addp2 = find_second_addp(use, n); |
1114 if (addp2 != NULL) { |
1114 if (addp2 != NULL) { |
1115 alloc_worklist.append_if_missing(addp2); |
1115 alloc_worklist.append_if_missing(addp2); |
1116 } |
1116 } |
1119 use->is_CheckCastPP() || |
1119 use->is_CheckCastPP() || |
1120 use->is_EncodeP() || |
1120 use->is_EncodeP() || |
1121 use->is_DecodeN() || |
1121 use->is_DecodeN() || |
1122 (use->is_ConstraintCast() && use->Opcode() == Op_CastPP)) { |
1122 (use->is_ConstraintCast() && use->Opcode() == Op_CastPP)) { |
1123 alloc_worklist.append_if_missing(use); |
1123 alloc_worklist.append_if_missing(use); |
|
1124 #ifdef ASSERT |
|
1125 } else if (use->is_Mem()) { |
|
1126 assert(use->in(MemNode::Address) != n, "EA: missing allocation reference path"); |
|
1127 } else if (use->is_MergeMem()) { |
|
1128 assert(_mergemem_worklist.contains(use->as_MergeMem()), "EA: missing MergeMem node in the worklist"); |
|
1129 } else if (use->is_SafePoint()) { |
|
1130 // Look for MergeMem nodes for calls which reference unique allocation |
|
1131 // (through CheckCastPP nodes) even for debug info. |
|
1132 Node* m = use->in(TypeFunc::Memory); |
|
1133 if (m->is_MergeMem()) { |
|
1134 assert(_mergemem_worklist.contains(m->as_MergeMem()), "EA: missing MergeMem node in the worklist"); |
|
1135 } |
|
1136 } else { |
|
1137 uint op = use->Opcode(); |
|
1138 if (!(op == Op_CmpP || op == Op_Conv2B || |
|
1139 op == Op_CastP2X || op == Op_StoreCM || |
|
1140 op == Op_FastLock || op == Op_AryEq || op == Op_StrComp || |
|
1141 op == Op_StrEquals || op == Op_StrIndexOf)) { |
|
1142 n->dump(); |
|
1143 use->dump(); |
|
1144 assert(false, "EA: missing allocation reference path"); |
|
1145 } |
|
1146 #endif |
1124 } |
1147 } |
1125 } |
1148 } |
1126 |
1149 |
1127 } |
1150 } |
1128 // New alias types were created in split_AddP(). |
1151 // New alias types were created in split_AddP(). |
1136 |
1159 |
1137 while (memnode_worklist.length() != 0) { |
1160 while (memnode_worklist.length() != 0) { |
1138 Node *n = memnode_worklist.pop(); |
1161 Node *n = memnode_worklist.pop(); |
1139 if (visited.test_set(n->_idx)) |
1162 if (visited.test_set(n->_idx)) |
1140 continue; |
1163 continue; |
1141 if (n->is_Phi()) { |
1164 if (n->is_Phi() || n->is_ClearArray()) { |
1142 assert(n->as_Phi()->adr_type() != TypePtr::BOTTOM, "narrow memory slice required"); |
1165 // we don't need to do anything, but the users must be pushed |
1143 // we don't need to do anything, but the users must be pushed if we haven't processed |
1166 } else if (n->is_MemBar()) { // Initialize, MemBar nodes |
1144 // this Phi before |
1167 // we don't need to do anything, but the users must be pushed |
1145 } else if (n->is_Initialize()) { |
1168 n = n->as_MemBar()->proj_out(TypeFunc::Memory); |
1146 // we don't need to do anything, but the users of the memory projection must be pushed |
|
1147 n = n->as_Initialize()->proj_out(TypeFunc::Memory); |
|
1148 if (n == NULL) |
1169 if (n == NULL) |
1149 continue; |
1170 continue; |
1150 } else { |
1171 } else { |
1151 assert(n->is_Mem(), "memory node required."); |
1172 assert(n->is_Mem(), "memory node required."); |
1152 Node *addr = n->in(MemNode::Address); |
1173 Node *addr = n->in(MemNode::Address); |
1179 } |
1200 } |
1180 } |
1201 } |
1181 // push user on appropriate worklist |
1202 // push user on appropriate worklist |
1182 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
1203 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
1183 Node *use = n->fast_out(i); |
1204 Node *use = n->fast_out(i); |
1184 if (use->is_Phi()) { |
1205 if (use->is_Phi() || use->is_ClearArray()) { |
1185 memnode_worklist.append_if_missing(use); |
1206 memnode_worklist.append_if_missing(use); |
1186 } else if(use->is_Mem() && use->in(MemNode::Memory) == n) { |
1207 } else if(use->is_Mem() && use->in(MemNode::Memory) == n) { |
|
1208 if (use->Opcode() == Op_StoreCM) // Ignore cardmark stores |
|
1209 continue; |
1187 memnode_worklist.append_if_missing(use); |
1210 memnode_worklist.append_if_missing(use); |
1188 } else if (use->is_Initialize()) { |
1211 } else if (use->is_MemBar()) { |
1189 memnode_worklist.append_if_missing(use); |
1212 memnode_worklist.append_if_missing(use); |
|
1213 #ifdef ASSERT |
|
1214 } else if(use->is_Mem()) { |
|
1215 assert(use->in(MemNode::Memory) != n, "EA: missing memory path"); |
1190 } else if (use->is_MergeMem()) { |
1216 } else if (use->is_MergeMem()) { |
1191 mergemem_worklist.append_if_missing(use); |
1217 assert(_mergemem_worklist.contains(use->as_MergeMem()), "EA: missing MergeMem node in the worklist"); |
|
1218 } else { |
|
1219 uint op = use->Opcode(); |
|
1220 if (!(op == Op_StoreCM || |
|
1221 (op == Op_CallLeaf && use->as_CallLeaf()->_name != NULL && |
|
1222 strcmp(use->as_CallLeaf()->_name, "g1_wb_pre") == 0) || |
|
1223 op == Op_AryEq || op == Op_StrComp || |
|
1224 op == Op_StrEquals || op == Op_StrIndexOf)) { |
|
1225 n->dump(); |
|
1226 use->dump(); |
|
1227 assert(false, "EA: missing memory path"); |
|
1228 } |
|
1229 #endif |
1192 } |
1230 } |
1193 } |
1231 } |
1194 } |
1232 } |
1195 |
1233 |
1196 // Phase 3: Process MergeMem nodes from mergemem_worklist. |
1234 // Phase 3: Process MergeMem nodes from mergemem_worklist. |
1197 // Walk each memory moving the first node encountered of each |
1235 // Walk each memory slice moving the first node encountered of each |
1198 // instance type to the the input corresponding to its alias index. |
1236 // instance type to the the input corresponding to its alias index. |
1199 while (mergemem_worklist.length() != 0) { |
1237 uint length = _mergemem_worklist.length(); |
1200 Node *n = mergemem_worklist.pop(); |
1238 for( uint next = 0; next < length; ++next ) { |
1201 assert(n->is_MergeMem(), "MergeMem node required."); |
1239 MergeMemNode* nmm = _mergemem_worklist.at(next); |
1202 if (visited.test_set(n->_idx)) |
1240 assert(!visited.test_set(nmm->_idx), "should not be visited before"); |
1203 continue; |
|
1204 MergeMemNode *nmm = n->as_MergeMem(); |
|
1205 // Note: we don't want to use MergeMemStream here because we only want to |
1241 // Note: we don't want to use MergeMemStream here because we only want to |
1206 // scan inputs which exist at the start, not ones we add during processing. |
1242 // scan inputs which exist at the start, not ones we add during processing. |
|
1243 // Note 2: MergeMem may already contains instance memory slices added |
|
1244 // during find_inst_mem() call when memory nodes were processed above. |
|
1245 igvn->hash_delete(nmm); |
1207 uint nslices = nmm->req(); |
1246 uint nslices = nmm->req(); |
1208 igvn->hash_delete(nmm); |
|
1209 for (uint i = Compile::AliasIdxRaw+1; i < nslices; i++) { |
1247 for (uint i = Compile::AliasIdxRaw+1; i < nslices; i++) { |
1210 Node* mem = nmm->in(i); |
1248 Node* mem = nmm->in(i); |
1211 Node* cur = NULL; |
1249 Node* cur = NULL; |
1212 if (mem == NULL || mem->is_top()) |
1250 if (mem == NULL || mem->is_top()) |
1213 continue; |
1251 continue; |
1257 nmm->set_memory_at(ni, result); |
1295 nmm->set_memory_at(ni, result); |
1258 } |
1296 } |
1259 } |
1297 } |
1260 igvn->hash_insert(nmm); |
1298 igvn->hash_insert(nmm); |
1261 record_for_optimizer(nmm); |
1299 record_for_optimizer(nmm); |
1262 |
|
1263 // Propagate new memory slices to following MergeMem nodes. |
|
1264 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
|
1265 Node *use = n->fast_out(i); |
|
1266 if (use->is_Call()) { |
|
1267 CallNode* in = use->as_Call(); |
|
1268 if (in->proj_out(TypeFunc::Memory) != NULL) { |
|
1269 Node* m = in->proj_out(TypeFunc::Memory); |
|
1270 for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) { |
|
1271 Node* mm = m->fast_out(j); |
|
1272 if (mm->is_MergeMem()) { |
|
1273 mergemem_worklist.append_if_missing(mm); |
|
1274 } |
|
1275 } |
|
1276 } |
|
1277 if (use->is_Allocate()) { |
|
1278 use = use->as_Allocate()->initialization(); |
|
1279 if (use == NULL) { |
|
1280 continue; |
|
1281 } |
|
1282 } |
|
1283 } |
|
1284 if (use->is_Initialize()) { |
|
1285 InitializeNode* in = use->as_Initialize(); |
|
1286 if (in->proj_out(TypeFunc::Memory) != NULL) { |
|
1287 Node* m = in->proj_out(TypeFunc::Memory); |
|
1288 for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) { |
|
1289 Node* mm = m->fast_out(j); |
|
1290 if (mm->is_MergeMem()) { |
|
1291 mergemem_worklist.append_if_missing(mm); |
|
1292 } |
|
1293 } |
|
1294 } |
|
1295 } |
|
1296 } |
|
1297 } |
1300 } |
1298 |
1301 |
1299 // Phase 4: Update the inputs of non-instance memory Phis and |
1302 // Phase 4: Update the inputs of non-instance memory Phis and |
1300 // the Memory input of memnodes |
1303 // the Memory input of memnodes |
1301 // First update the inputs of any non-instance Phi's from |
1304 // First update the inputs of any non-instance Phi's from |
1379 // for an escape status. See process_call_result() below. |
1382 // for an escape status. See process_call_result() below. |
1380 if (n->is_Allocate() || n->is_CallStaticJava() && |
1383 if (n->is_Allocate() || n->is_CallStaticJava() && |
1381 ptnode_adr(n->_idx)->node_type() == PointsToNode::JavaObject) { |
1384 ptnode_adr(n->_idx)->node_type() == PointsToNode::JavaObject) { |
1382 has_allocations = true; |
1385 has_allocations = true; |
1383 } |
1386 } |
1384 if(n->is_AddP()) |
1387 if(n->is_AddP()) { |
1385 cg_worklist.append(n->_idx); |
1388 // Collect address nodes which directly reference an allocation. |
|
1389 // Use them during stage 3 below to build initial connection graph |
|
1390 // field edges. Other field edges could be added after StoreP/LoadP |
|
1391 // nodes are processed during stage 4 below. |
|
1392 Node* base = get_addp_base(n); |
|
1393 if(base->is_Proj() && base->in(0)->is_Allocate()) { |
|
1394 cg_worklist.append(n->_idx); |
|
1395 } |
|
1396 } else if (n->is_MergeMem()) { |
|
1397 // Collect all MergeMem nodes to add memory slices for |
|
1398 // scalar replaceable objects in split_unique_types(). |
|
1399 _mergemem_worklist.append(n->as_MergeMem()); |
|
1400 } |
1386 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
1401 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
1387 Node* m = n->fast_out(i); // Get user |
1402 Node* m = n->fast_out(i); // Get user |
1388 worklist_init.push(m); |
1403 worklist_init.push(m); |
1389 } |
1404 } |
1390 } |
1405 } |
1421 if (ptn->node_type() != PointsToNode::UnknownType) |
1436 if (ptn->node_type() != PointsToNode::UnknownType) |
1422 cg_worklist.append(n->_idx); // Collect CG nodes |
1437 cg_worklist.append(n->_idx); // Collect CG nodes |
1423 } |
1438 } |
1424 } |
1439 } |
1425 |
1440 |
1426 VectorSet ptset(Thread::current()->resource_area()); |
1441 Arena* arena = Thread::current()->resource_area(); |
|
1442 VectorSet ptset(arena); |
1427 GrowableArray<uint> deferred_edges; |
1443 GrowableArray<uint> deferred_edges; |
1428 VectorSet visited(Thread::current()->resource_area()); |
1444 VectorSet visited(arena); |
1429 |
1445 |
1430 // 5. Remove deferred edges from the graph and collect |
1446 // 5. Remove deferred edges from the graph and adjust |
1431 // information needed for type splitting. |
1447 // escape state of nonescaping objects. |
1432 cg_length = cg_worklist.length(); |
1448 cg_length = cg_worklist.length(); |
1433 for( uint next = 0; next < cg_length; ++next ) { |
1449 for( uint next = 0; next < cg_length; ++next ) { |
1434 int ni = cg_worklist.at(next); |
1450 int ni = cg_worklist.at(next); |
1435 PointsToNode* ptn = ptnode_adr(ni); |
1451 PointsToNode* ptn = ptnode_adr(ni); |
1436 PointsToNode::NodeType nt = ptn->node_type(); |
1452 PointsToNode::NodeType nt = ptn->node_type(); |
1437 if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) { |
1453 if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) { |
1438 remove_deferred(ni, &deferred_edges, &visited); |
1454 remove_deferred(ni, &deferred_edges, &visited); |
1439 Node *n = ptn->_node; |
1455 Node *n = ptn->_node; |
1440 if (n->is_AddP()) { |
1456 if (n->is_AddP()) { |
1441 // Search for objects which are not scalar replaceable. |
1457 // Search for objects which are not scalar replaceable |
1442 // Mark their escape state as ArgEscape to propagate the state |
1458 // and adjust their escape state. |
1443 // to referenced objects. |
1459 verify_escape_state(ni, ptset, igvn); |
1444 // Note: currently there are no difference in compiler optimizations |
|
1445 // for ArgEscape objects and NoEscape objects which are not |
|
1446 // scalar replaceable. |
|
1447 |
|
1448 int offset = ptn->offset(); |
|
1449 Node *base = get_addp_base(n); |
|
1450 ptset.Clear(); |
|
1451 PointsTo(ptset, base, igvn); |
|
1452 int ptset_size = ptset.Size(); |
|
1453 |
|
1454 // Check if a field's initializing value is recorded and add |
|
1455 // a corresponding NULL field's value if it is not recorded. |
|
1456 // Connection Graph does not record a default initialization by NULL |
|
1457 // captured by Initialize node. |
|
1458 // |
|
1459 // Note: it will disable scalar replacement in some cases: |
|
1460 // |
|
1461 // Point p[] = new Point[1]; |
|
1462 // p[0] = new Point(); // Will be not scalar replaced |
|
1463 // |
|
1464 // but it will save us from incorrect optimizations in next cases: |
|
1465 // |
|
1466 // Point p[] = new Point[1]; |
|
1467 // if ( x ) p[0] = new Point(); // Will be not scalar replaced |
|
1468 // |
|
1469 // Without a control flow analysis we can't distinguish above cases. |
|
1470 // |
|
1471 if (offset != Type::OffsetBot && ptset_size == 1) { |
|
1472 uint elem = ptset.getelem(); // Allocation node's index |
|
1473 // It does not matter if it is not Allocation node since |
|
1474 // only non-escaping allocations are scalar replaced. |
|
1475 if (ptnode_adr(elem)->_node->is_Allocate() && |
|
1476 ptnode_adr(elem)->escape_state() == PointsToNode::NoEscape) { |
|
1477 AllocateNode* alloc = ptnode_adr(elem)->_node->as_Allocate(); |
|
1478 InitializeNode* ini = alloc->initialization(); |
|
1479 Node* value = NULL; |
|
1480 if (ini != NULL) { |
|
1481 BasicType ft = UseCompressedOops ? T_NARROWOOP : T_OBJECT; |
|
1482 Node* store = ini->find_captured_store(offset, type2aelembytes(ft), igvn); |
|
1483 if (store != NULL && store->is_Store()) |
|
1484 value = store->in(MemNode::ValueIn); |
|
1485 } |
|
1486 if (value == NULL || value != ptnode_adr(value->_idx)->_node) { |
|
1487 // A field's initializing value was not recorded. Add NULL. |
|
1488 uint null_idx = UseCompressedOops ? _noop_null : _oop_null; |
|
1489 add_pointsto_edge(ni, null_idx); |
|
1490 } |
|
1491 } |
|
1492 } |
|
1493 |
|
1494 // An object is not scalar replaceable if the field which may point |
|
1495 // to it has unknown offset (unknown element of an array of objects). |
|
1496 // |
|
1497 if (offset == Type::OffsetBot) { |
|
1498 uint e_cnt = ptn->edge_count(); |
|
1499 for (uint ei = 0; ei < e_cnt; ei++) { |
|
1500 uint npi = ptn->edge_target(ei); |
|
1501 set_escape_state(npi, PointsToNode::ArgEscape); |
|
1502 ptnode_adr(npi)->_scalar_replaceable = false; |
|
1503 } |
|
1504 } |
|
1505 |
|
1506 // Currently an object is not scalar replaceable if a LoadStore node |
|
1507 // access its field since the field value is unknown after it. |
|
1508 // |
|
1509 bool has_LoadStore = false; |
|
1510 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
|
1511 Node *use = n->fast_out(i); |
|
1512 if (use->is_LoadStore()) { |
|
1513 has_LoadStore = true; |
|
1514 break; |
|
1515 } |
|
1516 } |
|
1517 // An object is not scalar replaceable if the address points |
|
1518 // to unknown field (unknown element for arrays, offset is OffsetBot). |
|
1519 // |
|
1520 // Or the address may point to more then one object. This may produce |
|
1521 // the false positive result (set scalar_replaceable to false) |
|
1522 // since the flow-insensitive escape analysis can't separate |
|
1523 // the case when stores overwrite the field's value from the case |
|
1524 // when stores happened on different control branches. |
|
1525 // |
|
1526 if (ptset_size > 1 || ptset_size != 0 && |
|
1527 (has_LoadStore || offset == Type::OffsetBot)) { |
|
1528 for( VectorSetI j(&ptset); j.test(); ++j ) { |
|
1529 set_escape_state(j.elem, PointsToNode::ArgEscape); |
|
1530 ptnode_adr(j.elem)->_scalar_replaceable = false; |
|
1531 } |
|
1532 } |
|
1533 } |
1460 } |
1534 } |
1461 } |
1535 } |
1462 } |
1536 |
1463 |
1537 // 6. Propagate escape states. |
1464 // 6. Propagate escape states. |
1644 #endif |
1571 #endif |
1645 } |
1572 } |
1646 return has_non_escaping_obj; |
1573 return has_non_escaping_obj; |
1647 } |
1574 } |
1648 |
1575 |
|
1576 // Search for objects which are not scalar replaceable. |
|
1577 void ConnectionGraph::verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase) { |
|
1578 PointsToNode* ptn = ptnode_adr(nidx); |
|
1579 Node* n = ptn->_node; |
|
1580 assert(n->is_AddP(), "Should be called for AddP nodes only"); |
|
1581 // Search for objects which are not scalar replaceable. |
|
1582 // Mark their escape state as ArgEscape to propagate the state |
|
1583 // to referenced objects. |
|
1584 // Note: currently there are no difference in compiler optimizations |
|
1585 // for ArgEscape objects and NoEscape objects which are not |
|
1586 // scalar replaceable. |
|
1587 |
|
1588 Compile* C = _compile; |
|
1589 |
|
1590 int offset = ptn->offset(); |
|
1591 Node* base = get_addp_base(n); |
|
1592 ptset.Clear(); |
|
1593 PointsTo(ptset, base, phase); |
|
1594 int ptset_size = ptset.Size(); |
|
1595 |
|
1596 // Check if a oop field's initializing value is recorded and add |
|
1597 // a corresponding NULL field's value if it is not recorded. |
|
1598 // Connection Graph does not record a default initialization by NULL |
|
1599 // captured by Initialize node. |
|
1600 // |
|
1601 // Note: it will disable scalar replacement in some cases: |
|
1602 // |
|
1603 // Point p[] = new Point[1]; |
|
1604 // p[0] = new Point(); // Will be not scalar replaced |
|
1605 // |
|
1606 // but it will save us from incorrect optimizations in next cases: |
|
1607 // |
|
1608 // Point p[] = new Point[1]; |
|
1609 // if ( x ) p[0] = new Point(); // Will be not scalar replaced |
|
1610 // |
|
1611 // Do a simple control flow analysis to distinguish above cases. |
|
1612 // |
|
1613 if (offset != Type::OffsetBot && ptset_size == 1) { |
|
1614 uint elem = ptset.getelem(); // Allocation node's index |
|
1615 // It does not matter if it is not Allocation node since |
|
1616 // only non-escaping allocations are scalar replaced. |
|
1617 if (ptnode_adr(elem)->_node->is_Allocate() && |
|
1618 ptnode_adr(elem)->escape_state() == PointsToNode::NoEscape) { |
|
1619 AllocateNode* alloc = ptnode_adr(elem)->_node->as_Allocate(); |
|
1620 InitializeNode* ini = alloc->initialization(); |
|
1621 |
|
1622 // Check only oop fields. |
|
1623 const Type* adr_type = n->as_AddP()->bottom_type(); |
|
1624 BasicType basic_field_type = T_INT; |
|
1625 if (adr_type->isa_instptr()) { |
|
1626 ciField* field = C->alias_type(adr_type->isa_instptr())->field(); |
|
1627 if (field != NULL) { |
|
1628 basic_field_type = field->layout_type(); |
|
1629 } else { |
|
1630 // Ignore non field load (for example, klass load) |
|
1631 } |
|
1632 } else if (adr_type->isa_aryptr()) { |
|
1633 const Type* elemtype = adr_type->isa_aryptr()->elem(); |
|
1634 basic_field_type = elemtype->array_element_basic_type(); |
|
1635 } else { |
|
1636 // Raw pointers are used for initializing stores so skip it. |
|
1637 assert(adr_type->isa_rawptr() && base->is_Proj() && |
|
1638 (base->in(0) == alloc),"unexpected pointer type"); |
|
1639 } |
|
1640 if (basic_field_type == T_OBJECT || |
|
1641 basic_field_type == T_NARROWOOP || |
|
1642 basic_field_type == T_ARRAY) { |
|
1643 Node* value = NULL; |
|
1644 if (ini != NULL) { |
|
1645 BasicType ft = UseCompressedOops ? T_NARROWOOP : T_OBJECT; |
|
1646 Node* store = ini->find_captured_store(offset, type2aelembytes(ft), phase); |
|
1647 if (store != NULL && store->is_Store()) { |
|
1648 value = store->in(MemNode::ValueIn); |
|
1649 } else if (ptn->edge_count() > 0) { // Are there oop stores? |
|
1650 // Check for a store which follows allocation without branches. |
|
1651 // For example, a volatile field store is not collected |
|
1652 // by Initialize node. TODO: it would be nice to use idom() here. |
|
1653 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
|
1654 store = n->fast_out(i); |
|
1655 if (store->is_Store() && store->in(0) != NULL) { |
|
1656 Node* ctrl = store->in(0); |
|
1657 while(!(ctrl == ini || ctrl == alloc || ctrl == NULL || |
|
1658 ctrl == C->root() || ctrl == C->top() || ctrl->is_Region() || |
|
1659 ctrl->is_IfTrue() || ctrl->is_IfFalse())) { |
|
1660 ctrl = ctrl->in(0); |
|
1661 } |
|
1662 if (ctrl == ini || ctrl == alloc) { |
|
1663 value = store->in(MemNode::ValueIn); |
|
1664 break; |
|
1665 } |
|
1666 } |
|
1667 } |
|
1668 } |
|
1669 } |
|
1670 if (value == NULL || value != ptnode_adr(value->_idx)->_node) { |
|
1671 // A field's initializing value was not recorded. Add NULL. |
|
1672 uint null_idx = UseCompressedOops ? _noop_null : _oop_null; |
|
1673 add_pointsto_edge(nidx, null_idx); |
|
1674 } |
|
1675 } |
|
1676 } |
|
1677 } |
|
1678 |
|
1679 // An object is not scalar replaceable if the field which may point |
|
1680 // to it has unknown offset (unknown element of an array of objects). |
|
1681 // |
|
1682 if (offset == Type::OffsetBot) { |
|
1683 uint e_cnt = ptn->edge_count(); |
|
1684 for (uint ei = 0; ei < e_cnt; ei++) { |
|
1685 uint npi = ptn->edge_target(ei); |
|
1686 set_escape_state(npi, PointsToNode::ArgEscape); |
|
1687 ptnode_adr(npi)->_scalar_replaceable = false; |
|
1688 } |
|
1689 } |
|
1690 |
|
1691 // Currently an object is not scalar replaceable if a LoadStore node |
|
1692 // access its field since the field value is unknown after it. |
|
1693 // |
|
1694 bool has_LoadStore = false; |
|
1695 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
|
1696 Node *use = n->fast_out(i); |
|
1697 if (use->is_LoadStore()) { |
|
1698 has_LoadStore = true; |
|
1699 break; |
|
1700 } |
|
1701 } |
|
1702 // An object is not scalar replaceable if the address points |
|
1703 // to unknown field (unknown element for arrays, offset is OffsetBot). |
|
1704 // |
|
1705 // Or the address may point to more then one object. This may produce |
|
1706 // the false positive result (set scalar_replaceable to false) |
|
1707 // since the flow-insensitive escape analysis can't separate |
|
1708 // the case when stores overwrite the field's value from the case |
|
1709 // when stores happened on different control branches. |
|
1710 // |
|
1711 if (ptset_size > 1 || ptset_size != 0 && |
|
1712 (has_LoadStore || offset == Type::OffsetBot)) { |
|
1713 for( VectorSetI j(&ptset); j.test(); ++j ) { |
|
1714 set_escape_state(j.elem, PointsToNode::ArgEscape); |
|
1715 ptnode_adr(j.elem)->_scalar_replaceable = false; |
|
1716 } |
|
1717 } |
|
1718 } |
|
1719 |
1649 void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *phase) { |
1720 void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *phase) { |
1650 |
1721 |
1651 switch (call->Opcode()) { |
1722 switch (call->Opcode()) { |
1652 #ifdef ASSERT |
1723 #ifdef ASSERT |
1653 case Op_Allocate: |
1724 case Op_Allocate: |
1655 case Op_Lock: |
1726 case Op_Lock: |
1656 case Op_Unlock: |
1727 case Op_Unlock: |
1657 assert(false, "should be done already"); |
1728 assert(false, "should be done already"); |
1658 break; |
1729 break; |
1659 #endif |
1730 #endif |
|
1731 case Op_CallLeaf: |
1660 case Op_CallLeafNoFP: |
1732 case Op_CallLeafNoFP: |
1661 { |
1733 { |
1662 // Stub calls, objects do not escape but they are not scale replaceable. |
1734 // Stub calls, objects do not escape but they are not scale replaceable. |
1663 // Adjust escape state for outgoing arguments. |
1735 // Adjust escape state for outgoing arguments. |
1664 const TypeTuple * d = call->tf()->domain(); |
1736 const TypeTuple * d = call->tf()->domain(); |
1665 VectorSet ptset(Thread::current()->resource_area()); |
1737 VectorSet ptset(Thread::current()->resource_area()); |
1666 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { |
1738 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { |
1667 const Type* at = d->field_at(i); |
1739 const Type* at = d->field_at(i); |
1668 Node *arg = call->in(i)->uncast(); |
1740 Node *arg = call->in(i)->uncast(); |
1669 const Type *aat = phase->type(arg); |
1741 const Type *aat = phase->type(arg); |
1670 if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr()) { |
1742 if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr() && |
|
1743 ptnode_adr(arg->_idx)->escape_state() < PointsToNode::ArgEscape) { |
|
1744 |
1671 assert(aat == Type::TOP || aat == TypePtr::NULL_PTR || |
1745 assert(aat == Type::TOP || aat == TypePtr::NULL_PTR || |
1672 aat->isa_ptr() != NULL, "expecting an Ptr"); |
1746 aat->isa_ptr() != NULL, "expecting an Ptr"); |
|
1747 #ifdef ASSERT |
|
1748 if (!(call->Opcode() == Op_CallLeafNoFP && |
|
1749 call->as_CallLeaf()->_name != NULL && |
|
1750 (strstr(call->as_CallLeaf()->_name, "arraycopy") != 0) || |
|
1751 call->as_CallLeaf()->_name != NULL && |
|
1752 (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre") == 0 || |
|
1753 strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 )) |
|
1754 ) { |
|
1755 call->dump(); |
|
1756 assert(false, "EA: unexpected CallLeaf"); |
|
1757 } |
|
1758 #endif |
1673 set_escape_state(arg->_idx, PointsToNode::ArgEscape); |
1759 set_escape_state(arg->_idx, PointsToNode::ArgEscape); |
1674 if (arg->is_AddP()) { |
1760 if (arg->is_AddP()) { |
1675 // |
1761 // |
1676 // The inline_native_clone() case when the arraycopy stub is called |
1762 // The inline_native_clone() case when the arraycopy stub is called |
1677 // after the allocation before Initialize and CheckCastPP nodes. |
1763 // after the allocation before Initialize and CheckCastPP nodes. |
1704 VectorSet ptset(Thread::current()->resource_area()); |
1790 VectorSet ptset(Thread::current()->resource_area()); |
1705 bool copy_dependencies = false; |
1791 bool copy_dependencies = false; |
1706 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { |
1792 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { |
1707 const Type* at = d->field_at(i); |
1793 const Type* at = d->field_at(i); |
1708 int k = i - TypeFunc::Parms; |
1794 int k = i - TypeFunc::Parms; |
1709 |
1795 Node *arg = call->in(i)->uncast(); |
1710 if (at->isa_oopptr() != NULL) { |
1796 |
1711 Node *arg = call->in(i)->uncast(); |
1797 if (at->isa_oopptr() != NULL && |
|
1798 ptnode_adr(arg->_idx)->escape_state() < PointsToNode::ArgEscape) { |
1712 |
1799 |
1713 bool global_escapes = false; |
1800 bool global_escapes = false; |
1714 bool fields_escapes = false; |
1801 bool fields_escapes = false; |
1715 if (!call_analyzer->is_arg_stack(k)) { |
1802 if (!call_analyzer->is_arg_stack(k)) { |
1716 // The argument global escapes, mark everything it could point to |
1803 // The argument global escapes, mark everything it could point to |
1940 // Put Lock and Unlock nodes on IGVN worklist to process them during |
2027 // Put Lock and Unlock nodes on IGVN worklist to process them during |
1941 // the first IGVN optimization when escape information is still available. |
2028 // the first IGVN optimization when escape information is still available. |
1942 record_for_optimizer(n); |
2029 record_for_optimizer(n); |
1943 _processed.set(n->_idx); |
2030 _processed.set(n->_idx); |
1944 } else { |
2031 } else { |
1945 // Have to process call's arguments first. |
2032 // Don't mark as processed since call's arguments have to be processed. |
1946 PointsToNode::NodeType nt = PointsToNode::UnknownType; |
2033 PointsToNode::NodeType nt = PointsToNode::UnknownType; |
|
2034 PointsToNode::EscapeState es = PointsToNode::UnknownEscape; |
1947 |
2035 |
1948 // Check if a call returns an object. |
2036 // Check if a call returns an object. |
1949 const TypeTuple *r = n->as_Call()->tf()->range(); |
2037 const TypeTuple *r = n->as_Call()->tf()->range(); |
1950 if (n->is_CallStaticJava() && r->cnt() > TypeFunc::Parms && |
2038 if (r->cnt() > TypeFunc::Parms && |
|
2039 r->field_at(TypeFunc::Parms)->isa_ptr() && |
1951 n->as_Call()->proj_out(TypeFunc::Parms) != NULL) { |
2040 n->as_Call()->proj_out(TypeFunc::Parms) != NULL) { |
1952 // Note: use isa_ptr() instead of isa_oopptr() here because |
2041 nt = PointsToNode::JavaObject; |
1953 // the _multianewarray functions return a TypeRawPtr. |
2042 if (!n->is_CallStaticJava()) { |
1954 if (r->field_at(TypeFunc::Parms)->isa_ptr() != NULL) { |
2043 // Since the called mathod is statically unknown assume |
1955 nt = PointsToNode::JavaObject; |
2044 // the worst case that the returned value globally escapes. |
1956 } |
2045 es = PointsToNode::GlobalEscape; |
1957 } |
2046 } |
1958 add_node(n, nt, PointsToNode::UnknownEscape, false); |
2047 } |
|
2048 add_node(n, nt, es, false); |
1959 } |
2049 } |
1960 return; |
2050 return; |
1961 } |
2051 } |
1962 |
2052 |
1963 // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because |
2053 // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because |
2086 _delayed_worklist.push(n); |
2176 _delayed_worklist.push(n); |
2087 break; |
2177 break; |
2088 } |
2178 } |
2089 case Op_Proj: |
2179 case Op_Proj: |
2090 { |
2180 { |
2091 // we are only interested in the result projection from a call |
2181 // we are only interested in the oop result projection from a call |
2092 if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() ) { |
2182 if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() ) { |
2093 add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false); |
2183 const TypeTuple *r = n->in(0)->as_Call()->tf()->range(); |
2094 process_call_result(n->as_Proj(), phase); |
2184 assert(r->cnt() > TypeFunc::Parms, "sanity"); |
2095 if (!_processed.test(n->_idx)) { |
2185 if (r->field_at(TypeFunc::Parms)->isa_ptr() != NULL) { |
2096 // The call's result may need to be processed later if the call |
2186 add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false); |
2097 // returns it's argument and the argument is not processed yet. |
2187 int ti = n->in(0)->_idx; |
2098 _delayed_worklist.push(n); |
2188 // The call may not be registered yet (since not all its inputs are registered) |
2099 } |
2189 // if this is the projection from backbranch edge of Phi. |
2100 } else { |
2190 if (ptnode_adr(ti)->node_type() != PointsToNode::UnknownType) { |
2101 _processed.set(n->_idx); |
2191 process_call_result(n->as_Proj(), phase); |
2102 } |
2192 } |
|
2193 if (!_processed.test(n->_idx)) { |
|
2194 // The call's result may need to be processed later if the call |
|
2195 // returns it's argument and the argument is not processed yet. |
|
2196 _delayed_worklist.push(n); |
|
2197 } |
|
2198 break; |
|
2199 } |
|
2200 } |
|
2201 _processed.set(n->_idx); |
2103 break; |
2202 break; |
2104 } |
2203 } |
2105 case Op_Return: |
2204 case Op_Return: |
2106 { |
2205 { |
2107 if( n->req() > TypeFunc::Parms && |
2206 if( n->req() > TypeFunc::Parms && |
2352 uint pt = i.elem; |
2468 uint pt = i.elem; |
2353 add_edge_from_fields(pt, val->_idx, address_offset(adr, phase)); |
2469 add_edge_from_fields(pt, val->_idx, address_offset(adr, phase)); |
2354 } |
2470 } |
2355 break; |
2471 break; |
2356 } |
2472 } |
|
2473 case Op_AryEq: |
|
2474 case Op_StrComp: |
|
2475 case Op_StrEquals: |
|
2476 case Op_StrIndexOf: |
|
2477 { |
|
2478 // char[] arrays passed to string intrinsic do not escape but |
|
2479 // they are not scalar replaceable. Adjust escape state for them. |
|
2480 // Start from in(2) edge since in(1) is memory edge. |
|
2481 for (uint i = 2; i < n->req(); i++) { |
|
2482 Node* adr = n->in(i)->uncast(); |
|
2483 const Type *at = phase->type(adr); |
|
2484 if (!adr->is_top() && at->isa_ptr()) { |
|
2485 assert(at == Type::TOP || at == TypePtr::NULL_PTR || |
|
2486 at->isa_ptr() != NULL, "expecting an Ptr"); |
|
2487 if (adr->is_AddP()) { |
|
2488 adr = get_addp_base(adr); |
|
2489 } |
|
2490 // Mark as ArgEscape everything "adr" could point to. |
|
2491 set_escape_state(adr->_idx, PointsToNode::ArgEscape); |
|
2492 } |
|
2493 } |
|
2494 _processed.set(n_idx); |
|
2495 break; |
|
2496 } |
2357 case Op_ThreadLocal: |
2497 case Op_ThreadLocal: |
2358 { |
2498 { |
2359 assert(false, "Op_ThreadLocal"); |
2499 assert(false, "Op_ThreadLocal"); |
2360 break; |
2500 break; |
2361 } |
2501 } |
2362 default: |
2502 default: |
2363 ; |
2503 // This method should be called only for EA specific nodes. |
2364 // nothing to do |
2504 ShouldNotReachHere(); |
2365 } |
2505 } |
2366 } |
2506 } |
2367 |
2507 |
2368 #ifndef PRODUCT |
2508 #ifndef PRODUCT |
2369 void ConnectionGraph::dump() { |
2509 void ConnectionGraph::dump() { |