6711100: 64bit fastdebug server vm crashes with assert(_base == Int,"Not an Int")

Wed, 17 Sep 2008 08:29:17 -0700

author
rasbold
date
Wed, 17 Sep 2008 08:29:17 -0700
changeset 801
8261ee795323
parent 768
7484fa4b8825
child 802
194b8e3a2fc4

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

src/share/vm/opto/callnode.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/callnode.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/graphKit.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/memnode.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/memnode.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/parse2.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/type.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/type.hpp file | annotate | diff | comparison | revisions
test/compiler/6711100/Test.java file | annotate | diff | comparison | revisions
     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 +

mercurial