8002069: Assert failed in C2: assert(field->edge_count() > 0) failed: sanity

Tue, 06 Nov 2012 15:16:32 -0800

author
kvn
date
Tue, 06 Nov 2012 15:16:32 -0800
changeset 4255
f3da5ff1514c
parent 4254
dbeaeee28bc2
child 4256
a4e1bd941ded

8002069: Assert failed in C2: assert(field->edge_count() > 0) failed: sanity
Summary: Added missed type check of initializing store in ConnectionGraph::find_init_values().
Reviewed-by: roland, twisti, vlivanov

src/share/vm/opto/escape.cpp file | annotate | diff | comparison | revisions
test/compiler/8002069/Test8002069.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/opto/escape.cpp	Tue Nov 06 09:22:55 2012 -0800
     1.2 +++ b/src/share/vm/opto/escape.cpp	Tue Nov 06 15:16:32 2012 -0800
     1.3 @@ -1386,12 +1386,12 @@
     1.4      // Non-escaped allocation returned from Java or runtime call have
     1.5      // unknown values in fields.
     1.6      for (EdgeIterator i(pta); i.has_next(); i.next()) {
     1.7 -      PointsToNode* ptn = i.get();
     1.8 -      if (ptn->is_Field() && ptn->as_Field()->is_oop()) {
     1.9 -        if (add_edge(ptn, phantom_obj)) {
    1.10 +      PointsToNode* field = i.get();
    1.11 +      if (field->is_Field() && field->as_Field()->is_oop()) {
    1.12 +        if (add_edge(field, phantom_obj)) {
    1.13            // New edge was added
    1.14            new_edges++;
    1.15 -          add_field_uses_to_worklist(ptn->as_Field());
    1.16 +          add_field_uses_to_worklist(field->as_Field());
    1.17          }
    1.18        }
    1.19      }
    1.20 @@ -1413,30 +1413,30 @@
    1.21    // captured by Initialize node.
    1.22    //
    1.23    for (EdgeIterator i(pta); i.has_next(); i.next()) {
    1.24 -    PointsToNode* ptn = i.get(); // Field (AddP)
    1.25 -    if (!ptn->is_Field() || !ptn->as_Field()->is_oop())
    1.26 +    PointsToNode* field = i.get(); // Field (AddP)
    1.27 +    if (!field->is_Field() || !field->as_Field()->is_oop())
    1.28        continue; // Not oop field
    1.29 -    int offset = ptn->as_Field()->offset();
    1.30 +    int offset = field->as_Field()->offset();
    1.31      if (offset == Type::OffsetBot) {
    1.32        if (!visited_bottom_offset) {
    1.33          // OffsetBot is used to reference array's element,
    1.34          // always add reference to NULL to all Field nodes since we don't
    1.35          // known which element is referenced.
    1.36 -        if (add_edge(ptn, null_obj)) {
    1.37 +        if (add_edge(field, null_obj)) {
    1.38            // New edge was added
    1.39            new_edges++;
    1.40 -          add_field_uses_to_worklist(ptn->as_Field());
    1.41 +          add_field_uses_to_worklist(field->as_Field());
    1.42            visited_bottom_offset = true;
    1.43          }
    1.44        }
    1.45      } else {
    1.46        // Check only oop fields.
    1.47 -      const Type* adr_type = ptn->ideal_node()->as_AddP()->bottom_type();
    1.48 +      const Type* adr_type = field->ideal_node()->as_AddP()->bottom_type();
    1.49        if (adr_type->isa_rawptr()) {
    1.50  #ifdef ASSERT
    1.51          // Raw pointers are used for initializing stores so skip it
    1.52          // since it should be recorded already
    1.53 -        Node* base = get_addp_base(ptn->ideal_node());
    1.54 +        Node* base = get_addp_base(field->ideal_node());
    1.55          assert(adr_type->isa_rawptr() && base->is_Proj() &&
    1.56                 (base->in(0) == alloc),"unexpected pointer type");
    1.57  #endif
    1.58 @@ -1446,10 +1446,54 @@
    1.59          offsets_worklist.append(offset);
    1.60          Node* value = NULL;
    1.61          if (ini != NULL) {
    1.62 -          BasicType ft = UseCompressedOops ? T_NARROWOOP : T_OBJECT;
    1.63 -          Node* store = ini->find_captured_store(offset, type2aelembytes(ft), phase);
    1.64 -          if (store != NULL && store->is_Store()) {
    1.65 +          // StoreP::memory_type() == T_ADDRESS
    1.66 +          BasicType ft = UseCompressedOops ? T_NARROWOOP : T_ADDRESS;
    1.67 +          Node* store = ini->find_captured_store(offset, type2aelembytes(ft, true), phase);
    1.68 +          // Make sure initializing store has the same type as this AddP.
    1.69 +          // This AddP may reference non existing field because it is on a
    1.70 +          // dead branch of bimorphic call which is not eliminated yet.
    1.71 +          if (store != NULL && store->is_Store() &&
    1.72 +              store->as_Store()->memory_type() == ft) {
    1.73              value = store->in(MemNode::ValueIn);
    1.74 +#ifdef ASSERT
    1.75 +            if (VerifyConnectionGraph) {
    1.76 +              // Verify that AddP already points to all objects the value points to.
    1.77 +              PointsToNode* val = ptnode_adr(value->_idx);
    1.78 +              assert((val != NULL), "should be processed already");
    1.79 +              PointsToNode* missed_obj = NULL;
    1.80 +              if (val->is_JavaObject()) {
    1.81 +                if (!field->points_to(val->as_JavaObject())) {
    1.82 +                  missed_obj = val;
    1.83 +                }
    1.84 +              } else {
    1.85 +                if (!val->is_LocalVar() || (val->edge_count() == 0)) {
    1.86 +                  tty->print_cr("----------init store has invalid value -----");
    1.87 +                  store->dump();
    1.88 +                  val->dump();
    1.89 +                  assert(val->is_LocalVar() && (val->edge_count() > 0), "should be processed already");
    1.90 +                }
    1.91 +                for (EdgeIterator j(val); j.has_next(); j.next()) {
    1.92 +                  PointsToNode* obj = j.get();
    1.93 +                  if (obj->is_JavaObject()) {
    1.94 +                    if (!field->points_to(obj->as_JavaObject())) {
    1.95 +                      missed_obj = obj;
    1.96 +                      break;
    1.97 +                    }
    1.98 +                  }
    1.99 +                }
   1.100 +              }
   1.101 +              if (missed_obj != NULL) {
   1.102 +                tty->print_cr("----------field---------------------------------");
   1.103 +                field->dump();
   1.104 +                tty->print_cr("----------missed referernce to object-----------");
   1.105 +                missed_obj->dump();
   1.106 +                tty->print_cr("----------object referernced by init store -----");
   1.107 +                store->dump();
   1.108 +                val->dump();
   1.109 +                assert(!field->points_to(missed_obj->as_JavaObject()), "missed JavaObject reference");
   1.110 +              }
   1.111 +            }
   1.112 +#endif
   1.113            } else {
   1.114              // There could be initializing stores which follow allocation.
   1.115              // For example, a volatile field store is not collected
   1.116 @@ -1462,10 +1506,10 @@
   1.117          }
   1.118          if (value == NULL) {
   1.119            // A field's initializing value was not recorded. Add NULL.
   1.120 -          if (add_edge(ptn, null_obj)) {
   1.121 +          if (add_edge(field, null_obj)) {
   1.122              // New edge was added
   1.123              new_edges++;
   1.124 -            add_field_uses_to_worklist(ptn->as_Field());
   1.125 +            add_field_uses_to_worklist(field->as_Field());
   1.126            }
   1.127          }
   1.128        }
   1.129 @@ -1607,7 +1651,26 @@
   1.130        }
   1.131        // Verify that all fields have initializing values.
   1.132        if (field->edge_count() == 0) {
   1.133 +        tty->print_cr("----------field does not have references----------");
   1.134          field->dump();
   1.135 +        for (BaseIterator i(field); i.has_next(); i.next()) {
   1.136 +          PointsToNode* base = i.get();
   1.137 +          tty->print_cr("----------field has next base---------------------");
   1.138 +          base->dump();
   1.139 +          if (base->is_JavaObject() && (base != phantom_obj) && (base != null_obj)) {
   1.140 +            tty->print_cr("----------base has fields-------------------------");
   1.141 +            for (EdgeIterator j(base); j.has_next(); j.next()) {
   1.142 +              j.get()->dump();
   1.143 +            }
   1.144 +            tty->print_cr("----------base has references---------------------");
   1.145 +            for (UseIterator j(base); j.has_next(); j.next()) {
   1.146 +              j.get()->dump();
   1.147 +            }
   1.148 +          }
   1.149 +        }
   1.150 +        for (UseIterator i(field); i.has_next(); i.next()) {
   1.151 +          i.get()->dump();
   1.152 +        }
   1.153          assert(field->edge_count() > 0, "sanity");
   1.154        }
   1.155      }
   1.156 @@ -1967,7 +2030,7 @@
   1.157    if (is_JavaObject()) {
   1.158      return (this == ptn);
   1.159    }
   1.160 -  assert(is_LocalVar(), "sanity");
   1.161 +  assert(is_LocalVar() || is_Field(), "sanity");
   1.162    for (EdgeIterator i(this); i.has_next(); i.next()) {
   1.163      if (i.get() == ptn)
   1.164        return true;
   1.165 @@ -3127,10 +3190,14 @@
   1.166      EscapeState fields_es = fields_escape_state();
   1.167      tty->print("%s(%s) ", esc_names[(int)es], esc_names[(int)fields_es]);
   1.168      if (nt == PointsToNode::JavaObject && !this->scalar_replaceable())
   1.169 -      tty->print("NSR");
   1.170 +      tty->print("NSR ");
   1.171    }
   1.172    if (is_Field()) {
   1.173      FieldNode* f = (FieldNode*)this;
   1.174 +    if (f->is_oop())
   1.175 +      tty->print("oop ");
   1.176 +    if (f->offset() > 0)
   1.177 +      tty->print("+%d ", f->offset());
   1.178      tty->print("(");
   1.179      for (BaseIterator i(f); i.has_next(); i.next()) {
   1.180        PointsToNode* b = i.get();
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/test/compiler/8002069/Test8002069.java	Tue Nov 06 15:16:32 2012 -0800
     2.3 @@ -0,0 +1,98 @@
     2.4 +/*
     2.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
     2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.7 + *
     2.8 + * This code is free software; you can redistribute it and/or modify it
     2.9 + * under the terms of the GNU General Public License version 2 only, as
    2.10 + * published by the Free Software Foundation.
    2.11 + *
    2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    2.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    2.15 + * version 2 for more details (a copy is included in the LICENSE file that
    2.16 + * accompanied this code).
    2.17 + *
    2.18 + * You should have received a copy of the GNU General Public License version
    2.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    2.21 + *
    2.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    2.23 + * or visit www.oracle.com if you need additional information or have any
    2.24 + * questions.
    2.25 + *
    2.26 + */
    2.27 +
    2.28 +/**
    2.29 + * @test
    2.30 + * @bug 8002069
    2.31 + * @summary Assert failed in C2: assert(field->edge_count() > 0) failed: sanity
    2.32 + *
    2.33 + * @run main/othervm -Xmx32m -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:CompileCommand=exclude,Test8002069.dummy Test8002069
    2.34 + */
    2.35 +
    2.36 +abstract class O {
    2.37 +  int f;
    2.38 +  public O() { f = 5; }
    2.39 +  abstract void put(int i);
    2.40 +  public int foo(int i) {
    2.41 +    put(i);
    2.42 +    return i;
    2.43 +  }
    2.44 +};
    2.45 +
    2.46 +class A extends O {
    2.47 +  int[] a;
    2.48 +  public A(int s) {
    2.49 +    a = new int[s];
    2.50 +  }
    2.51 +  public void put(int i) {
    2.52 +    a[i%a.length] = i;
    2.53 +  }
    2.54 +}
    2.55 +
    2.56 +class B extends O {
    2.57 +  int sz;
    2.58 +  int[] a;
    2.59 +  public B(int s) {
    2.60 +    sz = s;
    2.61 +    a = new int[s];
    2.62 +  }
    2.63 +  public void put(int i) {
    2.64 +    a[i%sz] = i;
    2.65 +  }
    2.66 +}
    2.67 +
    2.68 +public class Test8002069 {
    2.69 +  public static void main(String args[]) {
    2.70 +    int sum = 0;
    2.71 +    for (int i=0; i<8000; i++) {
    2.72 +      sum += test1(i);
    2.73 +    }
    2.74 +    for (int i=0; i<100000; i++) {
    2.75 +      sum += test2(i);
    2.76 +    }
    2.77 +    System.out.println("PASSED. sum = " + sum);
    2.78 +  }
    2.79 +
    2.80 +  private O o;
    2.81 +
    2.82 +  private int foo(int i) {
    2.83 +    return o.foo(i);
    2.84 +  }
    2.85 +  static int test1(int i) {
    2.86 +    Test8002069 t = new Test8002069();
    2.87 +    t.o = new A(5);
    2.88 +    return t.foo(i);
    2.89 +  }
    2.90 +  static int test2(int i) {
    2.91 +    Test8002069 t = new Test8002069();
    2.92 +    t.o = new B(5);
    2.93 +    dummy(i);
    2.94 +    return t.foo(i);
    2.95 +  }
    2.96 +
    2.97 +  static int dummy(int i) {
    2.98 +    return i*2;
    2.99 +  }
   2.100 +}
   2.101 +

mercurial