Mercurial > hg > graal-compiler
comparison src/share/vm/opto/memnode.cpp @ 8116:6931f425c517
8007294: ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution
Summary: InitializeNode::can_capture_store() must check that the captured store doesn't overwrite a memory location that is loaded before the store.
Reviewed-by: kvn
author | roland |
---|---|
date | Mon, 25 Feb 2013 14:13:04 +0100 |
parents | b30b3c2a0cf2 |
children | ff55877839bc |
comparison
equal
deleted
inserted
replaced
8097:be1fbee20765 | 8116:6931f425c517 |
---|---|
318 mem = step_through_mergemem(phase, mmem, tp, adr_type(), tty); | 318 mem = step_through_mergemem(phase, mmem, tp, adr_type(), tty); |
319 } | 319 } |
320 | 320 |
321 if (mem != old_mem) { | 321 if (mem != old_mem) { |
322 set_req(MemNode::Memory, mem); | 322 set_req(MemNode::Memory, mem); |
323 if (can_reshape && old_mem->outcnt() == 0) { | |
324 igvn->_worklist.push(old_mem); | |
325 } | |
323 if (phase->type( mem ) == Type::TOP) return NodeSentinel; | 326 if (phase->type( mem ) == Type::TOP) return NodeSentinel; |
324 return this; | 327 return this; |
325 } | 328 } |
326 | 329 |
327 // let the subclass continue analyzing... | 330 // let the subclass continue analyzing... |
2317 // Capture an unaliased, unconditional, simple store into an initializer. | 2320 // Capture an unaliased, unconditional, simple store into an initializer. |
2318 // Or, if it is independent of the allocation, hoist it above the allocation. | 2321 // Or, if it is independent of the allocation, hoist it above the allocation. |
2319 if (ReduceFieldZeroing && /*can_reshape &&*/ | 2322 if (ReduceFieldZeroing && /*can_reshape &&*/ |
2320 mem->is_Proj() && mem->in(0)->is_Initialize()) { | 2323 mem->is_Proj() && mem->in(0)->is_Initialize()) { |
2321 InitializeNode* init = mem->in(0)->as_Initialize(); | 2324 InitializeNode* init = mem->in(0)->as_Initialize(); |
2322 intptr_t offset = init->can_capture_store(this, phase); | 2325 intptr_t offset = init->can_capture_store(this, phase, can_reshape); |
2323 if (offset > 0) { | 2326 if (offset > 0) { |
2324 Node* moved = init->capture_store(this, offset, phase); | 2327 Node* moved = init->capture_store(this, offset, phase, can_reshape); |
2325 // If the InitializeNode captured me, it made a raw copy of me, | 2328 // If the InitializeNode captured me, it made a raw copy of me, |
2326 // and I need to disappear. | 2329 // and I need to disappear. |
2327 if (moved != NULL) { | 2330 if (moved != NULL) { |
2328 // %%% hack to ensure that Ideal returns a new node: | 2331 // %%% hack to ensure that Ideal returns a new node: |
2329 mem = MergeMemNode::make(phase->C, mem); | 2332 mem = MergeMemNode::make(phase->C, mem); |
3132 | 3135 |
3133 // Here are all the checks a Store must pass before it can be moved into | 3136 // Here are all the checks a Store must pass before it can be moved into |
3134 // an initialization. Returns zero if a check fails. | 3137 // an initialization. Returns zero if a check fails. |
3135 // On success, returns the (constant) offset to which the store applies, | 3138 // On success, returns the (constant) offset to which the store applies, |
3136 // within the initialized memory. | 3139 // within the initialized memory. |
3137 intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase) { | 3140 intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase, bool can_reshape) { |
3138 const int FAIL = 0; | 3141 const int FAIL = 0; |
3139 if (st->req() != MemNode::ValueIn + 1) | 3142 if (st->req() != MemNode::ValueIn + 1) |
3140 return FAIL; // an inscrutable StoreNode (card mark?) | 3143 return FAIL; // an inscrutable StoreNode (card mark?) |
3141 Node* ctl = st->in(MemNode::Control); | 3144 Node* ctl = st->in(MemNode::Control); |
3142 if (!(ctl != NULL && ctl->is_Proj() && ctl->in(0) == this)) | 3145 if (!(ctl != NULL && ctl->is_Proj() && ctl->in(0) == this)) |
3154 Node* val = st->in(MemNode::ValueIn); | 3157 Node* val = st->in(MemNode::ValueIn); |
3155 int complexity_count = 0; | 3158 int complexity_count = 0; |
3156 if (!detect_init_independence(val, true, complexity_count)) | 3159 if (!detect_init_independence(val, true, complexity_count)) |
3157 return FAIL; // stored value must be 'simple enough' | 3160 return FAIL; // stored value must be 'simple enough' |
3158 | 3161 |
3162 // The Store can be captured only if nothing after the allocation | |
3163 // and before the Store is using the memory location that the store | |
3164 // overwrites. | |
3165 bool failed = false; | |
3166 // If is_complete_with_arraycopy() is true the shape of the graph is | |
3167 // well defined and is safe so no need for extra checks. | |
3168 if (!is_complete_with_arraycopy()) { | |
3169 // We are going to look at each use of the memory state following | |
3170 // the allocation to make sure nothing reads the memory that the | |
3171 // Store writes. | |
3172 const TypePtr* t_adr = phase->type(adr)->isa_ptr(); | |
3173 int alias_idx = phase->C->get_alias_index(t_adr); | |
3174 ResourceMark rm; | |
3175 Unique_Node_List mems; | |
3176 mems.push(mem); | |
3177 Node* unique_merge = NULL; | |
3178 for (uint next = 0; next < mems.size(); ++next) { | |
3179 Node *m = mems.at(next); | |
3180 for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) { | |
3181 Node *n = m->fast_out(j); | |
3182 if (n->outcnt() == 0) { | |
3183 continue; | |
3184 } | |
3185 if (n == st) { | |
3186 continue; | |
3187 } else if (n->in(0) != NULL && n->in(0) != ctl) { | |
3188 // If the control of this use is different from the control | |
3189 // of the Store which is right after the InitializeNode then | |
3190 // this node cannot be between the InitializeNode and the | |
3191 // Store. | |
3192 continue; | |
3193 } else if (n->is_MergeMem()) { | |
3194 if (n->as_MergeMem()->memory_at(alias_idx) == m) { | |
3195 // We can hit a MergeMemNode (that will likely go away | |
3196 // later) that is a direct use of the memory state | |
3197 // following the InitializeNode on the same slice as the | |
3198 // store node that we'd like to capture. We need to check | |
3199 // the uses of the MergeMemNode. | |
3200 mems.push(n); | |
3201 } | |
3202 } else if (n->is_Mem()) { | |
3203 Node* other_adr = n->in(MemNode::Address); | |
3204 if (other_adr == adr) { | |
3205 failed = true; | |
3206 break; | |
3207 } else { | |
3208 const TypePtr* other_t_adr = phase->type(other_adr)->isa_ptr(); | |
3209 if (other_t_adr != NULL) { | |
3210 int other_alias_idx = phase->C->get_alias_index(other_t_adr); | |
3211 if (other_alias_idx == alias_idx) { | |
3212 // A load from the same memory slice as the store right | |
3213 // after the InitializeNode. We check the control of the | |
3214 // object/array that is loaded from. If it's the same as | |
3215 // the store control then we cannot capture the store. | |
3216 assert(!n->is_Store(), "2 stores to same slice on same control?"); | |
3217 Node* base = other_adr; | |
3218 assert(base->is_AddP(), err_msg_res("should be addp but is %s", base->Name())); | |
3219 base = base->in(AddPNode::Base); | |
3220 if (base != NULL) { | |
3221 base = base->uncast(); | |
3222 if (base->is_Proj() && base->in(0) == alloc) { | |
3223 failed = true; | |
3224 break; | |
3225 } | |
3226 } | |
3227 } | |
3228 } | |
3229 } | |
3230 } else { | |
3231 failed = true; | |
3232 break; | |
3233 } | |
3234 } | |
3235 } | |
3236 } | |
3237 if (failed) { | |
3238 if (!can_reshape) { | |
3239 // We decided we couldn't capture the store during parsing. We | |
3240 // should try again during the next IGVN once the graph is | |
3241 // cleaner. | |
3242 phase->C->record_for_igvn(st); | |
3243 } | |
3244 return FAIL; | |
3245 } | |
3246 | |
3159 return offset; // success | 3247 return offset; // success |
3160 } | 3248 } |
3161 | 3249 |
3162 // Find the captured store in(i) which corresponds to the range | 3250 // Find the captured store in(i) which corresponds to the range |
3163 // [start..start+size) in the initialized object. | 3251 // [start..start+size) in the initialized object. |
3264 // rawstore2 = (StoreC alloc.Control alloc.Memory (+ rawoop 14) 2) | 3352 // rawstore2 = (StoreC alloc.Control alloc.Memory (+ rawoop 14) 2) |
3265 // init = (Initialize alloc.Control alloc.Memory rawoop | 3353 // init = (Initialize alloc.Control alloc.Memory rawoop |
3266 // rawstore1 rawstore2) | 3354 // rawstore1 rawstore2) |
3267 // | 3355 // |
3268 Node* InitializeNode::capture_store(StoreNode* st, intptr_t start, | 3356 Node* InitializeNode::capture_store(StoreNode* st, intptr_t start, |
3269 PhaseTransform* phase) { | 3357 PhaseTransform* phase, bool can_reshape) { |
3270 assert(stores_are_sane(phase), ""); | 3358 assert(stores_are_sane(phase), ""); |
3271 | 3359 |
3272 if (start < 0) return NULL; | 3360 if (start < 0) return NULL; |
3273 assert(can_capture_store(st, phase) == start, "sanity"); | 3361 assert(can_capture_store(st, phase, can_reshape) == start, "sanity"); |
3274 | 3362 |
3275 Compile* C = phase->C; | 3363 Compile* C = phase->C; |
3276 int size_in_bytes = st->memory_size(); | 3364 int size_in_bytes = st->memory_size(); |
3277 int i = captured_store_insertion_point(start, size_in_bytes, phase); | 3365 int i = captured_store_insertion_point(start, size_in_bytes, phase); |
3278 if (i == 0) return NULL; // bail out | 3366 if (i == 0) return NULL; // bail out |