Mercurial > hg > truffle
comparison src/share/vm/opto/parseHelper.cpp @ 20627:e7b3d177adda
8057622: java/util/stream/test/org/openjdk/tests/java/util/stream/InfiniteStreamWithLimitOpTest: SEGV inside compiled code (sparc)
Summary: In Parse::array_store_check(), add control edge FROM IfTrue branch of runtime type check of the destination array TO loading _element_klass from destination array.
Reviewed-by: kvn, roland, anoll
Contributed-by: Zoltan Majo <zoltan.majo@oracle.com>
author | zmajo |
---|---|
date | Mon, 10 Nov 2014 17:14:59 +0100 |
parents | 2113136690bc |
children | 7848fc12602b |
comparison
equal
deleted
inserted
replaced
20626:1a2069ede139 | 20627:e7b3d177adda |
---|---|
154 | 154 |
155 // Extract the array klass type | 155 // Extract the array klass type |
156 int klass_offset = oopDesc::klass_offset_in_bytes(); | 156 int klass_offset = oopDesc::klass_offset_in_bytes(); |
157 Node* p = basic_plus_adr( ary, ary, klass_offset ); | 157 Node* p = basic_plus_adr( ary, ary, klass_offset ); |
158 // p's type is array-of-OOPS plus klass_offset | 158 // p's type is array-of-OOPS plus klass_offset |
159 Node* array_klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS) ); | 159 Node* array_klass = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeInstPtr::KLASS)); |
160 // Get the array klass | 160 // Get the array klass |
161 const TypeKlassPtr *tak = _gvn.type(array_klass)->is_klassptr(); | 161 const TypeKlassPtr *tak = _gvn.type(array_klass)->is_klassptr(); |
162 | 162 |
163 // array_klass's type is generally INexact array-of-oop. Heroically | 163 // The type of array_klass is usually INexact array-of-oop. Heroically |
164 // cast the array klass to EXACT array and uncommon-trap if the cast | 164 // cast array_klass to EXACT array and uncommon-trap if the cast fails. |
165 // fails. | 165 // Make constant out of the inexact array klass, but use it only if the cast |
166 // succeeds. | |
166 bool always_see_exact_class = false; | 167 bool always_see_exact_class = false; |
167 if (MonomorphicArrayCheck | 168 if (MonomorphicArrayCheck |
168 && !too_many_traps(Deoptimization::Reason_array_check)) { | 169 && !too_many_traps(Deoptimization::Reason_array_check) |
170 && !tak->klass_is_exact() | |
171 && tak != TypeKlassPtr::OBJECT) { | |
172 // Regarding the fourth condition in the if-statement from above: | |
173 // | |
174 // If the compiler has determined that the type of array 'ary' (represented | |
175 // by 'array_klass') is java/lang/Object, the compiler must not assume that | |
176 // the array 'ary' is monomorphic. | |
177 // | |
178 // If 'ary' were of type java/lang/Object, this arraystore would have to fail, | |
179 // because it is not possible to perform a arraystore into an object that is not | |
180 // a "proper" array. | |
181 // | |
182 // Therefore, let's obtain at runtime the type of 'ary' and check if we can still | |
183 // successfully perform the store. | |
184 // | |
185 // The implementation reasons for the condition are the following: | |
186 // | |
187 // java/lang/Object is the superclass of all arrays, but it is represented by the VM | |
188 // as an InstanceKlass. The checks generated by gen_checkcast() (see below) expect | |
189 // 'array_klass' to be ObjArrayKlass, which can result in invalid memory accesses. | |
190 // | |
191 // See issue JDK-8057622 for details. | |
192 | |
169 always_see_exact_class = true; | 193 always_see_exact_class = true; |
170 // (If no MDO at all, hope for the best, until a trap actually occurs.) | 194 // (If no MDO at all, hope for the best, until a trap actually occurs.) |
171 } | 195 |
172 | |
173 // Is the array klass is exactly its defined type? | |
174 if (always_see_exact_class && !tak->klass_is_exact()) { | |
175 // Make a constant out of the inexact array klass | 196 // Make a constant out of the inexact array klass |
176 const TypeKlassPtr *extak = tak->cast_to_exactness(true)->is_klassptr(); | 197 const TypeKlassPtr *extak = tak->cast_to_exactness(true)->is_klassptr(); |
177 Node* con = makecon(extak); | 198 Node* con = makecon(extak); |
178 Node* cmp = _gvn.transform(new (C) CmpPNode( array_klass, con )); | 199 Node* cmp = _gvn.transform(new (C) CmpPNode( array_klass, con )); |
179 Node* bol = _gvn.transform(new (C) BoolNode( cmp, BoolTest::eq )); | 200 Node* bol = _gvn.transform(new (C) BoolNode( cmp, BoolTest::eq )); |
200 // Come here for polymorphic array klasses | 221 // Come here for polymorphic array klasses |
201 | 222 |
202 // Extract the array element class | 223 // Extract the array element class |
203 int element_klass_offset = in_bytes(ObjArrayKlass::element_klass_offset()); | 224 int element_klass_offset = in_bytes(ObjArrayKlass::element_klass_offset()); |
204 Node *p2 = basic_plus_adr(array_klass, array_klass, element_klass_offset); | 225 Node *p2 = basic_plus_adr(array_klass, array_klass, element_klass_offset); |
205 Node *a_e_klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p2, tak) ); | 226 // We are allowed to use the constant type only if cast succeeded. If always_see_exact_class is true, |
227 // we must set a control edge from the IfTrue node created by the uncommon_trap above to the | |
228 // LoadKlassNode. | |
229 Node* a_e_klass = _gvn.transform(LoadKlassNode::make(_gvn, always_see_exact_class ? control() : NULL, | |
230 immutable_memory(), p2, tak)); | |
206 | 231 |
207 // Check (the hard way) and throw if not a subklass. | 232 // Check (the hard way) and throw if not a subklass. |
208 // Result is ignored, we just need the CFG effects. | 233 // Result is ignored, we just need the CFG effects. |
209 gen_checkcast( obj, a_e_klass ); | 234 gen_checkcast(obj, a_e_klass); |
210 } | 235 } |
211 | 236 |
212 | 237 |
213 void Parse::emit_guard_for_new(ciInstanceKlass* klass) { | 238 void Parse::emit_guard_for_new(ciInstanceKlass* klass) { |
214 // Emit guarded new | 239 // Emit guarded new |