--- old/src/share/vm/opto/compile.cpp 2013-10-17 18:54:49.992434867 +0200 +++ new/src/share/vm/opto/compile.cpp 2013-10-17 18:54:49.638832172 +0200 @@ -1360,7 +1360,7 @@ // During the 2nd round of IterGVN, NotNull castings are removed. // Make sure the Bottom and NotNull variants alias the same. // Also, make sure exact and non-exact variants alias the same. - if( ptr == TypePtr::NotNull || ta->klass_is_exact() ) { + if(ptr == TypePtr::NotNull || ta->klass_is_exact() || ta->speculative() != NULL) { tj = ta = TypeAryPtr::make(TypePtr::BotPTR,ta->ary(),ta->klass(),false,offset); } } @@ -1385,6 +1385,9 @@ // Also, make sure exact and non-exact variants alias the same. tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset); } + if (to->speculative() != NULL) { + tj = to = TypeInstPtr::make(to->ptr(),to->klass(),to->klass_is_exact(),to->const_oop(),to->offset(), to->instance_id()); + } // Canonicalize the holder of this field if (offset >= 0 && offset < instanceOopDesc::base_offset_in_bytes()) { // First handle header references such as a LoadKlassNode, even if the @@ -2013,6 +2016,12 @@ if (failing()) return; } + // Remove the speculative part of types and clean up the graph from + // the extra CheckCastPP nodes whose only purpose is to carry + // them. Do that early so that optimizations are not disrupted by + // the extra CheckCastPP nodes. + remove_speculative_types(igvn); + // No more new expensive nodes will be added to the list from here // so keep only the actual candidates for optimizations. cleanup_expensive_nodes(igvn); @@ -3794,6 +3803,42 @@ } } +// Remove the speculative part of types and clean up the graph +void Compile::remove_speculative_types(PhaseIterGVN &igvn) { + if (UseTypeSpeculation) { + Unique_Node_List tmp; + tmp.push(root()); + int modified = 0; + // Go over all CastPP nodes that carry a specultive taype, drop the + // speculative part of the type and enqueue the castPP node for an + // igvn which may optimize it out. + for (uint next = 0; next < tmp.size(); ++next) { + Node *n = tmp.at(next); + if (n->is_Type() && n->as_Type()->type()->isa_oopptr() != NULL && n->as_Type()->type()->is_oopptr()->speculative() != NULL) { + TypeNode* tn = n->as_Type(); + const TypeOopPtr* t = tn->type()->is_oopptr(); + bool in_hash = igvn.hash_delete(n); + assert(in_hash, "CastPP node should be in igvn hash table"); + tn->set_type(t->remove_speculative()); + igvn.hash_insert(n); + igvn._worklist.push(n); // give it a chance to go away + modified++; + } + uint max = n->len(); + for( uint i = 0; i < max; ++i ) { + Node *m = n->in(i); + if (not_a_node(m)) continue; + tmp.push(m); + } + } + // Drop the speculative part of all types in the igvn's type table + igvn.remove_speculative_types(); + if (modified > 0) { + igvn.optimize(); + } + } +} + // Auxiliary method to support randomized stressing/fuzzing. // // This method can be called the arbitrary number of times, with current count