comparison src/share/vm/opto/macro.cpp @ 4763:1dc233a8c7fe

7121140: Allocation paths require explicit memory synchronization operations for RMO systems Summary: adds store store barrier after initialization of header and body of objects. Reviewed-by: never, kvn
author roland
date Tue, 20 Dec 2011 16:56:50 +0100
parents 069ab3f976d3
children d12a66fa3820
comparison
equal deleted inserted replaced
4762:069ab3f976d3 4763:1dc233a8c7fe
1086 Node* i_o = alloc->in(TypeFunc::I_O); 1086 Node* i_o = alloc->in(TypeFunc::I_O);
1087 Node* size_in_bytes = alloc->in(AllocateNode::AllocSize); 1087 Node* size_in_bytes = alloc->in(AllocateNode::AllocSize);
1088 Node* klass_node = alloc->in(AllocateNode::KlassNode); 1088 Node* klass_node = alloc->in(AllocateNode::KlassNode);
1089 Node* initial_slow_test = alloc->in(AllocateNode::InitialTest); 1089 Node* initial_slow_test = alloc->in(AllocateNode::InitialTest);
1090 1090
1091 Node* storestore = alloc->storestore();
1092 if (storestore != NULL) {
1093 // Break this link that is no longer useful and confuses register allocation
1094 storestore->set_req(MemBarNode::Precedent, top());
1095 }
1096
1091 assert(ctrl != NULL, "must have control"); 1097 assert(ctrl != NULL, "must have control");
1092 // We need a Region and corresponding Phi's to merge the slow-path and fast-path results. 1098 // We need a Region and corresponding Phi's to merge the slow-path and fast-path results.
1093 // they will not be used if "always_slow" is set 1099 // they will not be used if "always_slow" is set
1094 enum { slow_result_path = 1, fast_result_path = 2 }; 1100 enum { slow_result_path = 1, fast_result_path = 2 };
1095 Node *result_region; 1101 Node *result_region;
1287 transform_later(new_alloc_bytes); 1293 transform_later(new_alloc_bytes);
1288 fast_oop_rawmem = make_store(fast_oop_ctrl, store_eden_top, alloc_bytes_adr, 1294 fast_oop_rawmem = make_store(fast_oop_ctrl, store_eden_top, alloc_bytes_adr,
1289 0, new_alloc_bytes, T_LONG); 1295 0, new_alloc_bytes, T_LONG);
1290 } 1296 }
1291 1297
1298 InitializeNode* init = alloc->initialization();
1292 fast_oop_rawmem = initialize_object(alloc, 1299 fast_oop_rawmem = initialize_object(alloc,
1293 fast_oop_ctrl, fast_oop_rawmem, fast_oop, 1300 fast_oop_ctrl, fast_oop_rawmem, fast_oop,
1294 klass_node, length, size_in_bytes); 1301 klass_node, length, size_in_bytes);
1302
1303 // If initialization is performed by an array copy, any required
1304 // MemBarStoreStore was already added. If the object does not
1305 // escape no need for a MemBarStoreStore. Otherwise we need a
1306 // MemBarStoreStore so that stores that initialize this object
1307 // can't be reordered with a subsequent store that makes this
1308 // object accessible by other threads.
1309 if (init == NULL || (!init->is_complete_with_arraycopy() && !init->does_not_escape())) {
1310 if (init == NULL || init->req() < InitializeNode::RawStores) {
1311 // No InitializeNode or no stores captured by zeroing
1312 // elimination. Simply add the MemBarStoreStore after object
1313 // initialization.
1314 MemBarNode* mb = MemBarNode::make(C, Op_MemBarStoreStore, Compile::AliasIdxBot, fast_oop_rawmem);
1315 transform_later(mb);
1316
1317 mb->init_req(TypeFunc::Memory, fast_oop_rawmem);
1318 mb->init_req(TypeFunc::Control, fast_oop_ctrl);
1319 fast_oop_ctrl = new (C, 1) ProjNode(mb,TypeFunc::Control);
1320 transform_later(fast_oop_ctrl);
1321 fast_oop_rawmem = new (C, 1) ProjNode(mb,TypeFunc::Memory);
1322 transform_later(fast_oop_rawmem);
1323 } else {
1324 // Add the MemBarStoreStore after the InitializeNode so that
1325 // all stores performing the initialization that were moved
1326 // before the InitializeNode happen before the storestore
1327 // barrier.
1328
1329 Node* init_ctrl = init->proj_out(TypeFunc::Control);
1330 Node* init_mem = init->proj_out(TypeFunc::Memory);
1331
1332 MemBarNode* mb = MemBarNode::make(C, Op_MemBarStoreStore, Compile::AliasIdxBot);
1333 transform_later(mb);
1334
1335 Node* ctrl = new (C, 1) ProjNode(init,TypeFunc::Control);
1336 transform_later(ctrl);
1337 Node* mem = new (C, 1) ProjNode(init,TypeFunc::Memory);
1338 transform_later(mem);
1339
1340 // The MemBarStoreStore depends on control and memory coming
1341 // from the InitializeNode
1342 mb->init_req(TypeFunc::Memory, mem);
1343 mb->init_req(TypeFunc::Control, ctrl);
1344
1345 ctrl = new (C, 1) ProjNode(mb,TypeFunc::Control);
1346 transform_later(ctrl);
1347 mem = new (C, 1) ProjNode(mb,TypeFunc::Memory);
1348 transform_later(mem);
1349
1350 // All nodes that depended on the InitializeNode for control
1351 // and memory must now depend on the MemBarNode that itself
1352 // depends on the InitializeNode
1353 _igvn.replace_node(init_ctrl, ctrl);
1354 _igvn.replace_node(init_mem, mem);
1355 }
1356 }
1295 1357
1296 if (C->env()->dtrace_extended_probes()) { 1358 if (C->env()->dtrace_extended_probes()) {
1297 // Slow-path call 1359 // Slow-path call
1298 int size = TypeFunc::Parms + 2; 1360 int size = TypeFunc::Parms + 2;
1299 CallLeafNode *call = new (C, size) CallLeafNode(OptoRuntime::dtrace_object_alloc_Type(), 1361 CallLeafNode *call = new (C, size) CallLeafNode(OptoRuntime::dtrace_object_alloc_Type(),