--- 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 &&