diff -r ec595a5e793e -r 72a9b7284ccf hotspot/src/share/vm/opto/memnode.cpp --- a/hotspot/src/share/vm/opto/memnode.cpp Mon Mar 09 13:34:00 2009 -0700 +++ b/hotspot/src/share/vm/opto/memnode.cpp Thu Mar 12 18:16:36 2009 -0700 @@ -100,12 +100,12 @@ while (prev != result) { prev = result; if (result == start_mem) - break; // hit one of our sentinals + break; // hit one of our sentinels // skip over a call which does not affect this memory slice if (result->is_Proj() && result->as_Proj()->_con == TypeFunc::Memory) { Node *proj_in = result->in(0); if (proj_in->is_Allocate() && proj_in->_idx == instance_id) { - break; // hit one of our sentinals + break; // hit one of our sentinels } else if (proj_in->is_Call()) { CallNode *call = proj_in->as_Call(); if (!call->may_modify(t_adr, phase)) { @@ -198,7 +198,7 @@ // If not, we can update the input infinitely along a MergeMem cycle // Equivalent code in PhiNode::Ideal Node* m = phase->transform(mmem); - // If tranformed to a MergeMem, get the desired slice + // If transformed to a MergeMem, get the desired slice // Otherwise the returned node represents memory for every slice mem = (m->is_MergeMem())? m->as_MergeMem()->memory_at(alias_idx) : m; // Update input if it is progress over what we have now @@ -778,7 +778,7 @@ adr_type->offset() == arrayOopDesc::length_offset_in_bytes()), "use LoadRangeNode instead"); switch (bt) { - case T_BOOLEAN: + case T_BOOLEAN: return new (C, 3) LoadUBNode(ctl, mem, adr, adr_type, rt->is_int() ); case T_BYTE: return new (C, 3) LoadBNode (ctl, mem, adr, adr_type, rt->is_int() ); case T_INT: return new (C, 3) LoadINode (ctl, mem, adr, adr_type, rt->is_int() ); case T_CHAR: return new (C, 3) LoadUSNode(ctl, mem, adr, adr_type, rt->is_int() ); @@ -970,7 +970,7 @@ } // Search for an existing data phi which was generated before for the same - // instance's field to avoid infinite genertion of phis in a loop. + // instance's field to avoid infinite generation of phis in a loop. Node *region = mem->in(0); if (is_instance_field_load_with_local_phi(region)) { const TypePtr *addr_t = in(MemNode::Address)->bottom_type()->isa_ptr(); @@ -1066,11 +1066,11 @@ break; } } - LoadNode* load = NULL; - if (allocation != NULL && base->in(load_index)->is_Load()) { - load = base->in(load_index)->as_Load(); - } - if (load != NULL && in(Memory)->is_Phi() && in(Memory)->in(0) == base->in(0)) { + bool has_load = ( allocation != NULL && + (base->in(load_index)->is_Load() || + base->in(load_index)->is_DecodeN() && + base->in(load_index)->in(1)->is_Load()) ); + if (has_load && in(Memory)->is_Phi() && in(Memory)->in(0) == base->in(0)) { // Push the loads from the phi that comes from valueOf up // through it to allow elimination of the loads and the recovery // of the original value. @@ -1106,11 +1106,20 @@ result->set_req(load_index, in2); return result; } - } else if (base->is_Load()) { + } else if (base->is_Load() || + base->is_DecodeN() && base->in(1)->is_Load()) { + if (base->is_DecodeN()) { + // Get LoadN node which loads cached Integer object + base = base->in(1); + } // Eliminate the load of Integer.value for integers from the cache // array by deriving the value from the index into the array. // Capture the offset of the load and then reverse the computation. Node* load_base = base->in(Address)->in(AddPNode::Base); + if (load_base->is_DecodeN()) { + // Get LoadN node which loads IntegerCache.cache field + load_base = load_base->in(1); + } if (load_base != NULL) { Compile::AliasType* atp = phase->C->alias_type(load_base->adr_type()); intptr_t cache_offset; @@ -1245,7 +1254,7 @@ // (This tweaking with igvn only works because x is a new node.) igvn->set_type(x, t); // If x is a TypeNode, capture any more-precise type permanently into Node - // othewise it will be not updated during igvn->transform since + // otherwise it will be not updated during igvn->transform since // igvn->type(x) is set to x->Value() already. x->raise_bottom_type(t); Node *y = x->Identity(igvn); @@ -1607,6 +1616,22 @@ return LoadNode::Ideal(phase, can_reshape); } +//--------------------------LoadUBNode::Ideal------------------------------------- +// +// If the previous store is to the same address as this load, +// and the value stored was larger than a byte, replace this load +// with the value stored truncated to a byte. If no truncation is +// needed, the replacement is done in LoadNode::Identity(). +// +Node* LoadUBNode::Ideal(PhaseGVN* phase, bool can_reshape) { + Node* mem = in(MemNode::Memory); + Node* value = can_see_stored_value(mem, phase); + if (value && !phase->type(value)->higher_equal(_type)) + return new (phase->C, 3) AndINode(value, phase->intcon(0xFF)); + // Identity call will handle the case where truncation is not needed. + return LoadNode::Ideal(phase, can_reshape); +} + //--------------------------LoadUSNode::Ideal------------------------------------- // // If the previous store is to the same address as this load, @@ -2582,7 +2607,7 @@ // capturing of nearby memory operations. // // During macro-expansion, all captured initializations which store -// constant values of 32 bits or smaller are coalesced (if advantagous) +// constant values of 32 bits or smaller are coalesced (if advantageous) // into larger 'tiles' 32 or 64 bits. This allows an object to be // initialized in fewer memory operations. Memory words which are // covered by neither tiles nor non-constant stores are pre-zeroed @@ -3669,7 +3694,7 @@ else if (old_mmem != NULL) { new_mem = old_mmem->memory_at(i); } - // else preceeding memory was not a MergeMem + // else preceding memory was not a MergeMem // replace equivalent phis (unfortunately, they do not GVN together) if (new_mem != NULL && new_mem != new_base &&