--- old/src/share/vm/opto/callnode.cpp 2013-05-06 18:14:18.000000000 -0700 +++ new/src/share/vm/opto/callnode.cpp 2013-05-06 18:14:18.000000000 -0700 @@ -523,7 +523,9 @@ void JVMState::dump_on(outputStream* st) const { - if (_map && !((uintptr_t)_map & 1)) { + bool print_map = _map && !((uintptr_t)_map & 1) && + ((caller() == NULL) || (caller()->map() != _map)); + if (print_map) { if (_map->len() > _map->req()) { // _map->has_exceptions() Node* ex = _map->in(_map->req()); // _map->next_exception() // skip the first one; it's already being printed @@ -532,7 +534,10 @@ ex->dump(1); } } - _map->dump(2); + _map->dump(Verbose ? 2 : 1); + } + if (caller() != NULL) { + caller()->dump_on(st); } st->print("JVMS depth=%d loc=%d stk=%d arg=%d mon=%d scalar=%d end=%d mondepth=%d sp=%d bci=%d reexecute=%s method=", depth(), locoff(), stkoff(), argoff(), monoff(), scloff(), endoff(), monitor_depth(), sp(), bci(), should_reexecute()?"true":"false"); @@ -546,9 +551,6 @@ _method->print_codes_on(bci(), bci()+1, st); } } - if (caller() != NULL) { - caller()->dump_on(st); - } } // Extra way to dump a jvms from the debugger, @@ -584,6 +586,15 @@ return n; } +/** + * Reset map for all callers + */ +void JVMState::set_map_deep(SafePointNode* map) { + for (JVMState* p = this; p->_caller != NULL; p = p->_caller) { + p->set_map(map); + } +} + //============================================================================= uint CallNode::cmp( const Node &n ) const { return _tf == ((CallNode&)n)._tf && _jvms == ((CallNode&)n)._jvms; } @@ -663,17 +674,49 @@ // Determine whether the call could modify the field of the specified // instance at the specified offset. // -bool CallNode::may_modify(const TypePtr *addr_t, PhaseTransform *phase) { - const TypeOopPtr *adrInst_t = addr_t->isa_oopptr(); - - // If not an OopPtr or not an instance type, assume the worst. - // Note: currently this method is called only for instance types. - if (adrInst_t == NULL || !adrInst_t->is_known_instance()) { - return true; +bool CallNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) { + assert((t_oop != NULL), "sanity"); + if (t_oop->is_known_instance()) { + // The instance_id is set only for scalar-replaceable allocations which + // are not passed as arguments according to Escape Analysis. + return false; } - // The instance_id is set only for scalar-replaceable allocations which - // are not passed as arguments according to Escape Analysis. - return false; + if (t_oop->is_ptr_to_boxed_value()) { + ciKlass* boxing_klass = t_oop->klass(); + if (is_CallStaticJava() && as_CallStaticJava()->is_boxing_method()) { + // Skip unrelated boxing methods. + Node* proj = proj_out(TypeFunc::Parms); + if ((proj == NULL) || (phase->type(proj)->is_instptr()->klass() != boxing_klass)) { + return false; + } + } + if (is_CallJava() && as_CallJava()->method() != NULL) { + ciMethod* meth = as_CallJava()->method(); + if (meth->is_accessor()) { + return false; + } + // May modify (by reflection) if an boxing object is passed + // as argument or returned. + if (returns_pointer() && (proj_out(TypeFunc::Parms) != NULL)) { + Node* proj = proj_out(TypeFunc::Parms); + const TypeInstPtr* inst_t = phase->type(proj)->isa_instptr(); + if ((inst_t != NULL) && (!inst_t->klass_is_exact() || + (inst_t->klass() == boxing_klass))) { + return true; + } + } + const TypeTuple* d = tf()->domain(); + for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { + const TypeInstPtr* inst_t = d->field_at(i)->isa_instptr(); + if ((inst_t != NULL) && (!inst_t->klass_is_exact() || + (inst_t->klass() == boxing_klass))) { + return true; + } + } + return false; + } + } + return true; } // Does this call have a direct reference to n other than debug information? @@ -1020,6 +1063,7 @@ int scloff = jvms->scloff(); int endoff = jvms->endoff(); assert(endoff == (int)req(), "no other states or debug info after me"); + assert(jvms->scl_size() == 0, "parsed code should not have scalar objects"); Node* top = Compile::current()->top(); for (uint i = 0; i < grow_by; i++) { ins_req(monoff, top); @@ -1035,6 +1079,7 @@ const int MonitorEdges = 2; assert(JVMState::logMonitorEdges == exact_log2(MonitorEdges), "correct MonitorEdges"); assert(req() == jvms()->endoff(), "correct sizing"); + assert((jvms()->scl_size() == 0), "parsed code should not have scalar objects"); int nextmon = jvms()->scloff(); if (GenerateSynchronizationCode) { add_req(lock->box_node()); @@ -1050,6 +1095,7 @@ void SafePointNode::pop_monitor() { // Delete last monitor from debug info + assert((jvms()->scl_size() == 0), "parsed code should not have scalar objects"); debug_only(int num_before_pop = jvms()->nof_monitors()); const int MonitorEdges = (1<scloff(); @@ -1154,6 +1200,7 @@ init_class_id(Class_Allocate); init_flags(Flag_is_macro); _is_scalar_replaceable = false; + _is_non_escaping = false; Node *topnode = C->top(); init_req( TypeFunc::Control , ctrl ); @@ -1169,8 +1216,6 @@ } //============================================================================= -uint AllocateArrayNode::size_of() const { return sizeof(*this); } - Node* AllocateArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { if (remove_dead_region(phase, can_reshape)) return this; // Don't bother trying to transform a dead node @@ -1235,6 +1280,8 @@ // - the narrow_length is 0 // - the narrow_length is not wider than length assert(narrow_length_type == TypeInt::ZERO || + length_type->is_con() && narrow_length_type->is_con() && + (narrow_length_type->_hi <= length_type->_lo) || (narrow_length_type->_hi <= length_type->_hi && narrow_length_type->_lo >= length_type->_lo), "narrow type must be narrower than length type");