From ddcb02c030b9a46da185f1f630aedf29eb49ce4f Mon Sep 17 00:00:00 2001 From: kvn Date: Thu, 9 May 2013 17:28:04 -0700 Subject: [PATCH] 8014189: JVM crash with SEGV in ConnectionGraph::record_for_escape_analysis() Summary: Add NULL checks and asserts for Type::make_ptr() returned value. Reviewed-by: twisti --- src/share/vm/opto/escape.cpp | 24 +++++++++++++++--------- src/share/vm/opto/lcm.cpp | 5 +++-- src/share/vm/opto/library_call.cpp | 2 +- src/share/vm/opto/machnode.cpp | 4 ++-- src/share/vm/opto/macro.cpp | 2 +- src/share/vm/opto/node.cpp | 15 +++++++++++++++ src/share/vm/opto/node.hpp | 2 ++ src/share/vm/opto/output.cpp | 2 +- src/share/vm/opto/subnode.cpp | 7 ++++--- 9 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/share/vm/opto/escape.cpp b/src/share/vm/opto/escape.cpp index aa730f255..8e9a43508 100644 --- a/src/share/vm/opto/escape.cpp +++ b/src/share/vm/opto/escape.cpp @@ -484,6 +484,9 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de Node* adr = n->in(MemNode::Address); const Type *adr_type = igvn->type(adr); adr_type = adr_type->make_ptr(); + if (adr_type == NULL) { + break; // skip dead nodes + } if (adr_type->isa_oopptr() || (opcode == Op_StoreP || opcode == Op_StoreN || opcode == Op_StoreNKlass) && (adr_type == TypeRawPtr::NOTNULL && @@ -676,14 +679,18 @@ void ConnectionGraph::add_final_edges(Node *n) { case Op_GetAndSetP: case Op_GetAndSetN: { Node* adr = n->in(MemNode::Address); - if (opcode == Op_GetAndSetP || opcode == Op_GetAndSetN) { - const Type* t = _igvn->type(n); - if (t->make_ptr() != NULL) { - add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL); - } - } const Type *adr_type = _igvn->type(adr); adr_type = adr_type->make_ptr(); +#ifdef ASSERT + if (adr_type == NULL) { + n->dump(1); + assert(adr_type != NULL, "dead node should not be on list"); + break; + } +#endif + if (opcode == Op_GetAndSetP || opcode == Op_GetAndSetN) { + add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL); + } if (adr_type->isa_oopptr() || (opcode == Op_StoreP || opcode == Op_StoreN || opcode == Op_StoreNKlass) && (adr_type == TypeRawPtr::NOTNULL && @@ -1813,9 +1820,8 @@ Node* ConnectionGraph::optimize_ptr_compare(Node* n) { jobj2->ideal_node()->is_Con()) { // Klass or String constants compare. Need to be careful with // compressed pointers - compare types of ConN and ConP instead of nodes. - const Type* t1 = jobj1->ideal_node()->bottom_type()->make_ptr(); - const Type* t2 = jobj2->ideal_node()->bottom_type()->make_ptr(); - assert(t1 != NULL && t2 != NULL, "sanity"); + const Type* t1 = jobj1->ideal_node()->get_ptr_type(); + const Type* t2 = jobj2->ideal_node()->get_ptr_type(); if (t1->make_ptr() == t2->make_ptr()) { return _pcmp_eq; } else { diff --git a/src/share/vm/opto/lcm.cpp b/src/share/vm/opto/lcm.cpp index ddb55d30e..2b3eca478 100644 --- a/src/share/vm/opto/lcm.cpp +++ b/src/share/vm/opto/lcm.cpp @@ -219,9 +219,10 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe // cannot reason about it; is probably not implicit null exception } else { const TypePtr* tptr; - if (UseCompressedOops && Universe::narrow_oop_shift() == 0) { + if (UseCompressedOops && (Universe::narrow_oop_shift() == 0 || + Universe::narrow_klass_shift() == 0)) { // 32-bits narrow oop can be the base of address expressions - tptr = base->bottom_type()->make_ptr(); + tptr = base->get_ptr_type(); } else { // only regular oops are expected here tptr = base->bottom_type()->is_ptr(); diff --git a/src/share/vm/opto/library_call.cpp b/src/share/vm/opto/library_call.cpp index 53afe14be..609b70226 100644 --- a/src/share/vm/opto/library_call.cpp +++ b/src/share/vm/opto/library_call.cpp @@ -2783,7 +2783,7 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind #ifdef _LP64 if (type == T_OBJECT && adr->bottom_type()->is_ptr_to_narrowoop() && kind == LS_xchg) { - load_store = _gvn.transform(new (C) DecodeNNode(load_store, load_store->bottom_type()->make_ptr())); + load_store = _gvn.transform(new (C) DecodeNNode(load_store, load_store->get_ptr_type())); } #endif diff --git a/src/share/vm/opto/machnode.cpp b/src/share/vm/opto/machnode.cpp index b9b014e05..0d6ddf9ae 100644 --- a/src/share/vm/opto/machnode.cpp +++ b/src/share/vm/opto/machnode.cpp @@ -349,11 +349,11 @@ const class TypePtr *MachNode::adr_type() const { if (base == NodeSentinel) return TypePtr::BOTTOM; const Type* t = base->bottom_type(); - if (UseCompressedOops && Universe::narrow_oop_shift() == 0) { + if (t->isa_narrowoop() && Universe::narrow_oop_shift() == 0) { // 32-bit unscaled narrow oop can be the base of any address expression t = t->make_ptr(); } - if (UseCompressedKlassPointers && Universe::narrow_klass_shift() == 0) { + if (t->isa_narrowklass() && Universe::narrow_klass_shift() == 0) { // 32-bit unscaled narrow oop can be the base of any address expression t = t->make_ptr(); } diff --git a/src/share/vm/opto/macro.cpp b/src/share/vm/opto/macro.cpp index 5271ddb9d..56b9c9391 100644 --- a/src/share/vm/opto/macro.cpp +++ b/src/share/vm/opto/macro.cpp @@ -834,7 +834,7 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray is_EncodeP()) { field_val = field_val->in(1); } else { - field_val = transform_later(new (C) DecodeNNode(field_val, field_val->bottom_type()->make_ptr())); + field_val = transform_later(new (C) DecodeNNode(field_val, field_val->get_ptr_type())); } } sfpt->add_req(field_val); diff --git a/src/share/vm/opto/node.cpp b/src/share/vm/opto/node.cpp index 463604bac..f2100040f 100644 --- a/src/share/vm/opto/node.cpp +++ b/src/share/vm/opto/node.cpp @@ -1398,6 +1398,21 @@ const TypeLong* Node::find_long_type() const { return NULL; } + +/** + * Return a ptr type for nodes which should have it. + */ +const TypePtr* Node::get_ptr_type() const { + const TypePtr* tp = this->bottom_type()->make_ptr(); +#ifdef ASSERT + if (tp == NULL) { + this->dump(1); + assert((tp != NULL), "unexpected node type"); + } +#endif + return tp; +} + // Get a double constant from a ConstNode. // Returns the constant if it is a double ConstNode jdouble Node::getd() const { diff --git a/src/share/vm/opto/node.hpp b/src/share/vm/opto/node.hpp index 18e4182d1..bb5e8f200 100644 --- a/src/share/vm/opto/node.hpp +++ b/src/share/vm/opto/node.hpp @@ -965,6 +965,8 @@ public: } const TypeLong* find_long_type() const; + const TypePtr* get_ptr_type() const; + // These guys are called by code generated by ADLC: intptr_t get_ptr() const; intptr_t get_narrowcon() const; diff --git a/src/share/vm/opto/output.cpp b/src/share/vm/opto/output.cpp index f5a1e08e1..f04ab721b 100644 --- a/src/share/vm/opto/output.cpp +++ b/src/share/vm/opto/output.cpp @@ -929,7 +929,7 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { scval = new_loc_value( _regalloc, obj_reg, Location::oop ); } } else { - const TypePtr *tp = obj_node->bottom_type()->make_ptr(); + const TypePtr *tp = obj_node->get_ptr_type(); scval = new ConstantOopWriteValue(tp->is_oopptr()->const_oop()->constant_encoding()); } diff --git a/src/share/vm/opto/subnode.cpp b/src/share/vm/opto/subnode.cpp index 70a64ba70..275b4d80d 100644 --- a/src/share/vm/opto/subnode.cpp +++ b/src/share/vm/opto/subnode.cpp @@ -863,10 +863,11 @@ const Type *CmpNNode::sub( const Type *t1, const Type *t2 ) const { const TypePtr *r1 = t2->make_ptr(); // Undefined inputs makes for an undefined result - if( TypePtr::above_centerline(r0->_ptr) || - TypePtr::above_centerline(r1->_ptr) ) + if ((r0 == NULL) || (r1 == NULL) || + TypePtr::above_centerline(r0->_ptr) || + TypePtr::above_centerline(r1->_ptr)) { return Type::TOP; - + } if (r0 == r1 && r0->singleton()) { // Equal pointer constants (klasses, nulls, etc.) return TypeInt::CC_EQ; -- GitLab