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();