Wed, 17 Sep 2008 08:29:17 -0700
6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")
Summary: insert CastII nodes to narrow type of load_array_length() node
Reviewed-by: never, kvn
1.1 --- a/src/share/vm/opto/callnode.cpp Mon Sep 15 09:58:26 2008 -0700 1.2 +++ b/src/share/vm/opto/callnode.cpp Wed Sep 17 08:29:17 2008 -0700 1.3 @@ -1034,6 +1034,39 @@ 1.4 //============================================================================= 1.5 uint AllocateArrayNode::size_of() const { return sizeof(*this); } 1.6 1.7 +// Retrieve the length from the AllocateArrayNode. Narrow the type with a 1.8 +// CastII, if appropriate. If we are not allowed to create new nodes, and 1.9 +// a CastII is appropriate, return NULL. 1.10 +Node *AllocateArrayNode::make_ideal_length(const TypeOopPtr* oop_type, PhaseTransform *phase, bool allow_new_nodes) { 1.11 + Node *length = in(AllocateNode::ALength); 1.12 + assert(length != NULL, "length is not null"); 1.13 + 1.14 + const TypeInt* length_type = phase->find_int_type(length); 1.15 + const TypeAryPtr* ary_type = oop_type->isa_aryptr(); 1.16 + 1.17 + if (ary_type != NULL && length_type != NULL) { 1.18 + const TypeInt* narrow_length_type = ary_type->narrow_size_type(length_type); 1.19 + if (narrow_length_type != length_type) { 1.20 + // Assert one of: 1.21 + // - the narrow_length is 0 1.22 + // - the narrow_length is not wider than length 1.23 + assert(narrow_length_type == TypeInt::ZERO || 1.24 + (narrow_length_type->_hi <= length_type->_hi && 1.25 + narrow_length_type->_lo >= length_type->_lo), 1.26 + "narrow type must be narrower than length type"); 1.27 + 1.28 + // Return NULL if new nodes are not allowed 1.29 + if (!allow_new_nodes) return NULL; 1.30 + // Create a cast which is control dependent on the initialization to 1.31 + // propagate the fact that the array length must be positive. 1.32 + length = new (phase->C, 2) CastIINode(length, narrow_length_type); 1.33 + length->set_req(0, initialization()->proj_out(0)); 1.34 + } 1.35 + } 1.36 + 1.37 + return length; 1.38 +} 1.39 + 1.40 //============================================================================= 1.41 uint LockNode::size_of() const { return sizeof(*this); } 1.42
2.1 --- a/src/share/vm/opto/callnode.hpp Mon Sep 15 09:58:26 2008 -0700 2.2 +++ b/src/share/vm/opto/callnode.hpp Wed Sep 17 08:29:17 2008 -0700 2.3 @@ -755,6 +755,15 @@ 2.4 virtual int Opcode() const; 2.5 virtual uint size_of() const; // Size is bigger 2.6 2.7 + // Dig the length operand out of a array allocation site. 2.8 + Node* Ideal_length() { 2.9 + return in(AllocateNode::ALength); 2.10 + } 2.11 + 2.12 + // Dig the length operand out of a array allocation site and narrow the 2.13 + // type with a CastII, if necesssary 2.14 + Node* make_ideal_length(const TypeOopPtr* ary_type, PhaseTransform *phase, bool can_create = true); 2.15 + 2.16 // Pattern-match a possible usage of AllocateArrayNode. 2.17 // Return null if no allocation is recognized. 2.18 static AllocateArrayNode* Ideal_array_allocation(Node* ptr, PhaseTransform* phase) { 2.19 @@ -762,12 +771,6 @@ 2.20 return (allo == NULL || !allo->is_AllocateArray()) 2.21 ? NULL : allo->as_AllocateArray(); 2.22 } 2.23 - 2.24 - // Dig the length operand out of a (possible) array allocation site. 2.25 - static Node* Ideal_length(Node* ptr, PhaseTransform* phase) { 2.26 - AllocateArrayNode* allo = Ideal_array_allocation(ptr, phase); 2.27 - return (allo == NULL) ? NULL : allo->in(AllocateNode::ALength); 2.28 - } 2.29 }; 2.30 2.31 //------------------------------AbstractLockNode-----------------------------------
3.1 --- a/src/share/vm/opto/graphKit.cpp Mon Sep 15 09:58:26 2008 -0700 3.2 +++ b/src/share/vm/opto/graphKit.cpp Wed Sep 17 08:29:17 2008 -0700 3.3 @@ -1049,10 +1049,19 @@ 3.4 //-------------------------load_array_length----------------------------------- 3.5 Node* GraphKit::load_array_length(Node* array) { 3.6 // Special-case a fresh allocation to avoid building nodes: 3.7 - Node* alen = AllocateArrayNode::Ideal_length(array, &_gvn); 3.8 - if (alen != NULL) return alen; 3.9 - Node *r_adr = basic_plus_adr(array, arrayOopDesc::length_offset_in_bytes()); 3.10 - return _gvn.transform( new (C, 3) LoadRangeNode(0, immutable_memory(), r_adr, TypeInt::POS)); 3.11 + AllocateArrayNode* alloc = AllocateArrayNode::Ideal_array_allocation(array, &_gvn); 3.12 + Node *alen; 3.13 + if (alloc == NULL) { 3.14 + Node *r_adr = basic_plus_adr(array, arrayOopDesc::length_offset_in_bytes()); 3.15 + alen = _gvn.transform( new (C, 3) LoadRangeNode(0, immutable_memory(), r_adr, TypeInt::POS)); 3.16 + } else { 3.17 + alen = alloc->Ideal_length(); 3.18 + Node* ccast = alloc->make_ideal_length(_gvn.type(array)->is_aryptr(), &_gvn); 3.19 + if (ccast != alen) { 3.20 + alen = _gvn.transform(ccast); 3.21 + } 3.22 + } 3.23 + return alen; 3.24 } 3.25 3.26 //------------------------------do_null_check---------------------------------- 3.27 @@ -2833,20 +2842,18 @@ 3.28 assert(just_allocated_object(control()) == javaoop, "just allocated"); 3.29 3.30 #ifdef ASSERT 3.31 - { // Verify that the AllocateNode::Ideal_foo recognizers work: 3.32 - Node* kn = alloc->in(AllocateNode::KlassNode); 3.33 - Node* ln = alloc->in(AllocateNode::ALength); 3.34 - assert(AllocateNode::Ideal_klass(rawoop, &_gvn) == kn, 3.35 - "Ideal_klass works"); 3.36 - assert(AllocateNode::Ideal_klass(javaoop, &_gvn) == kn, 3.37 - "Ideal_klass works"); 3.38 + { // Verify that the AllocateNode::Ideal_allocation recognizers work: 3.39 + assert(AllocateNode::Ideal_allocation(rawoop, &_gvn) == alloc, 3.40 + "Ideal_allocation works"); 3.41 + assert(AllocateNode::Ideal_allocation(javaoop, &_gvn) == alloc, 3.42 + "Ideal_allocation works"); 3.43 if (alloc->is_AllocateArray()) { 3.44 - assert(AllocateArrayNode::Ideal_length(rawoop, &_gvn) == ln, 3.45 - "Ideal_length works"); 3.46 - assert(AllocateArrayNode::Ideal_length(javaoop, &_gvn) == ln, 3.47 - "Ideal_length works"); 3.48 + assert(AllocateArrayNode::Ideal_array_allocation(rawoop, &_gvn) == alloc->as_AllocateArray(), 3.49 + "Ideal_allocation works"); 3.50 + assert(AllocateArrayNode::Ideal_array_allocation(javaoop, &_gvn) == alloc->as_AllocateArray(), 3.51 + "Ideal_allocation works"); 3.52 } else { 3.53 - assert(ln->is_top(), "no length, please"); 3.54 + assert(alloc->in(AllocateNode::ALength)->is_top(), "no length, please"); 3.55 } 3.56 } 3.57 #endif //ASSERT 3.58 @@ -3095,25 +3102,20 @@ 3.59 // (This happens via a non-constant argument to inline_native_newArray.) 3.60 // In any case, the value of klass_node provides the desired array type. 3.61 const TypeInt* length_type = _gvn.find_int_type(length); 3.62 - const TypeInt* narrow_length_type = NULL; 3.63 const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type(); 3.64 if (ary_type->isa_aryptr() && length_type != NULL) { 3.65 // Try to get a better type than POS for the size 3.66 ary_type = ary_type->is_aryptr()->cast_to_size(length_type); 3.67 - narrow_length_type = ary_type->is_aryptr()->size(); 3.68 - if (narrow_length_type == length_type) 3.69 - narrow_length_type = NULL; 3.70 } 3.71 3.72 Node* javaoop = set_output_for_allocation(alloc, ary_type, raw_mem_only); 3.73 3.74 - // Cast length on remaining path to be positive: 3.75 - if (narrow_length_type != NULL) { 3.76 - Node* ccast = new (C, 2) CastIINode(length, narrow_length_type); 3.77 - ccast->set_req(0, control()); 3.78 - _gvn.set_type_bottom(ccast); 3.79 - record_for_igvn(ccast); 3.80 - if (map()->find_edge(length) >= 0) { 3.81 + // Cast length on remaining path to be as narrow as possible 3.82 + if (map()->find_edge(length) >= 0) { 3.83 + Node* ccast = alloc->make_ideal_length(ary_type, &_gvn); 3.84 + if (ccast != length) { 3.85 + _gvn.set_type_bottom(ccast); 3.86 + record_for_igvn(ccast); 3.87 replace_in_map(length, ccast); 3.88 } 3.89 }
4.1 --- a/src/share/vm/opto/memnode.cpp Mon Sep 15 09:58:26 2008 -0700 4.2 +++ b/src/share/vm/opto/memnode.cpp Wed Sep 17 08:29:17 2008 -0700 4.3 @@ -1887,6 +1887,38 @@ 4.4 return tap->size(); 4.5 } 4.6 4.7 +//-------------------------------Ideal--------------------------------------- 4.8 +// Feed through the length in AllocateArray(...length...)._length. 4.9 +Node *LoadRangeNode::Ideal(PhaseGVN *phase, bool can_reshape) { 4.10 + Node* p = MemNode::Ideal_common(phase, can_reshape); 4.11 + if (p) return (p == NodeSentinel) ? NULL : p; 4.12 + 4.13 + // Take apart the address into an oop and and offset. 4.14 + // Return 'this' if we cannot. 4.15 + Node* adr = in(MemNode::Address); 4.16 + intptr_t offset = 0; 4.17 + Node* base = AddPNode::Ideal_base_and_offset(adr, phase, offset); 4.18 + if (base == NULL) return NULL; 4.19 + const TypeAryPtr* tary = phase->type(adr)->isa_aryptr(); 4.20 + if (tary == NULL) return NULL; 4.21 + 4.22 + // We can fetch the length directly through an AllocateArrayNode. 4.23 + // This works even if the length is not constant (clone or newArray). 4.24 + if (offset == arrayOopDesc::length_offset_in_bytes()) { 4.25 + AllocateArrayNode* alloc = AllocateArrayNode::Ideal_array_allocation(base, phase); 4.26 + if (alloc != NULL) { 4.27 + Node* allocated_length = alloc->Ideal_length(); 4.28 + Node* len = alloc->make_ideal_length(tary, phase); 4.29 + if (allocated_length != len) { 4.30 + // New CastII improves on this. 4.31 + return len; 4.32 + } 4.33 + } 4.34 + } 4.35 + 4.36 + return NULL; 4.37 +} 4.38 + 4.39 //------------------------------Identity--------------------------------------- 4.40 // Feed through the length in AllocateArray(...length...)._length. 4.41 Node* LoadRangeNode::Identity( PhaseTransform *phase ) { 4.42 @@ -1905,15 +1937,22 @@ 4.43 // We can fetch the length directly through an AllocateArrayNode. 4.44 // This works even if the length is not constant (clone or newArray). 4.45 if (offset == arrayOopDesc::length_offset_in_bytes()) { 4.46 - Node* allocated_length = AllocateArrayNode::Ideal_length(base, phase); 4.47 - if (allocated_length != NULL) { 4.48 - return allocated_length; 4.49 + AllocateArrayNode* alloc = AllocateArrayNode::Ideal_array_allocation(base, phase); 4.50 + if (alloc != NULL) { 4.51 + Node* allocated_length = alloc->Ideal_length(); 4.52 + // Do not allow make_ideal_length to allocate a CastII node. 4.53 + Node* len = alloc->make_ideal_length(tary, phase, false); 4.54 + if (allocated_length == len) { 4.55 + // Return allocated_length only if it would not be improved by a CastII. 4.56 + return allocated_length; 4.57 + } 4.58 } 4.59 } 4.60 4.61 return this; 4.62 4.63 } 4.64 + 4.65 //============================================================================= 4.66 //---------------------------StoreNode::make----------------------------------- 4.67 // Polymorphic factory method:
5.1 --- a/src/share/vm/opto/memnode.hpp Mon Sep 15 09:58:26 2008 -0700 5.2 +++ b/src/share/vm/opto/memnode.hpp Wed Sep 17 08:29:17 2008 -0700 5.3 @@ -241,6 +241,7 @@ 5.4 virtual int Opcode() const; 5.5 virtual const Type *Value( PhaseTransform *phase ) const; 5.6 virtual Node *Identity( PhaseTransform *phase ); 5.7 + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 5.8 }; 5.9 5.10 //------------------------------LoadLNode--------------------------------------
6.1 --- a/src/share/vm/opto/parse2.cpp Mon Sep 15 09:58:26 2008 -0700 6.2 +++ b/src/share/vm/opto/parse2.cpp Wed Sep 17 08:29:17 2008 -0700 6.3 @@ -100,16 +100,17 @@ 6.4 6.5 // Do the range check 6.6 if (GenerateRangeChecks && need_range_check) { 6.7 - // Range is constant in array-oop, so we can use the original state of mem 6.8 - Node* len = load_array_length(ary); 6.9 Node* tst; 6.10 if (sizetype->_hi <= 0) { 6.11 - // If the greatest array bound is negative, we can conclude that we're 6.12 + // The greatest array bound is negative, so we can conclude that we're 6.13 // compiling unreachable code, but the unsigned compare trick used below 6.14 // only works with non-negative lengths. Instead, hack "tst" to be zero so 6.15 // the uncommon_trap path will always be taken. 6.16 tst = _gvn.intcon(0); 6.17 } else { 6.18 + // Range is constant in array-oop, so we can use the original state of mem 6.19 + Node* len = load_array_length(ary); 6.20 + 6.21 // Test length vs index (standard trick using unsigned compare) 6.22 Node* chk = _gvn.transform( new (C, 3) CmpUNode(idx, len) ); 6.23 BoolTest::mask btest = BoolTest::lt; 6.24 @@ -137,9 +138,12 @@ 6.25 // Check for always knowing you are throwing a range-check exception 6.26 if (stopped()) return top(); 6.27 6.28 - Node* ptr = array_element_address( ary, idx, type, sizetype); 6.29 + Node* ptr = array_element_address(ary, idx, type, sizetype); 6.30 6.31 if (result2 != NULL) *result2 = elemtype; 6.32 + 6.33 + assert(ptr != top(), "top should go hand-in-hand with stopped"); 6.34 + 6.35 return ptr; 6.36 } 6.37
7.1 --- a/src/share/vm/opto/type.cpp Mon Sep 15 09:58:26 2008 -0700 7.2 +++ b/src/share/vm/opto/type.cpp Wed Sep 17 08:29:17 2008 -0700 7.3 @@ -3157,17 +3157,18 @@ 7.4 7.5 // Narrow the given size type to the index range for the given array base type. 7.6 // Return NULL if the resulting int type becomes empty. 7.7 -const TypeInt* TypeAryPtr::narrow_size_type(const TypeInt* size, BasicType elem) { 7.8 +const TypeInt* TypeAryPtr::narrow_size_type(const TypeInt* size) const { 7.9 jint hi = size->_hi; 7.10 jint lo = size->_lo; 7.11 jint min_lo = 0; 7.12 - jint max_hi = max_array_length(elem); 7.13 + jint max_hi = max_array_length(elem()->basic_type()); 7.14 //if (index_not_size) --max_hi; // type of a valid array index, FTR 7.15 bool chg = false; 7.16 if (lo < min_lo) { lo = min_lo; chg = true; } 7.17 if (hi > max_hi) { hi = max_hi; chg = true; } 7.18 + // Negative length arrays will produce weird intermediate dead fath-path code 7.19 if (lo > hi) 7.20 - return NULL; 7.21 + return TypeInt::ZERO; 7.22 if (!chg) 7.23 return size; 7.24 return TypeInt::make(lo, hi, Type::WidenMin); 7.25 @@ -3176,9 +3177,7 @@ 7.26 //-------------------------------cast_to_size---------------------------------- 7.27 const TypeAryPtr* TypeAryPtr::cast_to_size(const TypeInt* new_size) const { 7.28 assert(new_size != NULL, ""); 7.29 - new_size = narrow_size_type(new_size, elem()->basic_type()); 7.30 - if (new_size == NULL) // Negative length arrays will produce weird 7.31 - new_size = TypeInt::ZERO; // intermediate dead fast-path goo 7.32 + new_size = narrow_size_type(new_size); 7.33 if (new_size == size()) return this; 7.34 const TypeAry* new_ary = TypeAry::make(elem(), new_size); 7.35 return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id);
8.1 --- a/src/share/vm/opto/type.hpp Mon Sep 15 09:58:26 2008 -0700 8.2 +++ b/src/share/vm/opto/type.hpp Wed Sep 17 08:29:17 2008 -0700 8.3 @@ -840,6 +840,7 @@ 8.4 virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const; 8.5 8.6 virtual const TypeAryPtr* cast_to_size(const TypeInt* size) const; 8.7 + virtual const TypeInt* narrow_size_type(const TypeInt* size) const; 8.8 8.9 virtual bool empty(void) const; // TRUE if type is vacuous 8.10 virtual const TypePtr *add_offset( intptr_t offset ) const; 8.11 @@ -865,7 +866,6 @@ 8.12 } 8.13 static const TypeAryPtr *_array_body_type[T_CONFLICT+1]; 8.14 // sharpen the type of an int which is used as an array size 8.15 - static const TypeInt* narrow_size_type(const TypeInt* size, BasicType elem); 8.16 #ifndef PRODUCT 8.17 virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping 8.18 #endif
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/test/compiler/6711100/Test.java Wed Sep 17 08:29:17 2008 -0700 9.3 @@ -0,0 +1,53 @@ 9.4 +/* 9.5 + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. 9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 9.7 + * 9.8 + * This code is free software; you can redistribute it and/or modify it 9.9 + * under the terms of the GNU General Public License version 2 only, as 9.10 + * published by the Free Software Foundation. 9.11 + * 9.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 9.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 9.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 9.15 + * version 2 for more details (a copy is included in the LICENSE file that 9.16 + * accompanied this code). 9.17 + * 9.18 + * You should have received a copy of the GNU General Public License version 9.19 + * 2 along with this work; if not, write to the Free Software Foundation, 9.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 9.21 + * 9.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 9.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 9.24 + * have any questions. 9.25 + */ 9.26 + 9.27 +/* 9.28 + * @test 9.29 + * @bug 6711100 9.30 + * @summary 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int") 9.31 + * @run main/othervm -Xcomp -XX:CompileOnly=Test.<init> Test 9.32 + */ 9.33 + 9.34 +public class Test { 9.35 + 9.36 + static byte b; 9.37 + 9.38 + // The server compiler chokes on compiling 9.39 + // this method when f() is not inlined 9.40 + public Test() { 9.41 + b = (new byte[1])[(new byte[f()])[-1]]; 9.42 + } 9.43 + 9.44 + protected static int f() { 9.45 + return 1; 9.46 + } 9.47 + 9.48 + public static void main(String[] args) { 9.49 + try { 9.50 + Test t = new Test(); 9.51 + } catch (ArrayIndexOutOfBoundsException e) { 9.52 + } 9.53 + } 9.54 +} 9.55 + 9.56 +