1.1 --- a/src/share/vm/opto/memnode.cpp Wed Dec 05 09:00:00 2007 -0800 1.2 +++ b/src/share/vm/opto/memnode.cpp Wed Dec 05 09:01:00 2007 -0800 1.3 @@ -634,6 +634,46 @@ 1.4 Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const { 1.5 Node* ld_adr = in(MemNode::Address); 1.6 1.7 + const TypeInstPtr* tp = phase->type(ld_adr)->isa_instptr(); 1.8 + Compile::AliasType* atp = tp != NULL ? phase->C->alias_type(tp) : NULL; 1.9 + if (EliminateAutoBox && atp != NULL && atp->index() >= Compile::AliasIdxRaw && 1.10 + atp->field() != NULL && !atp->field()->is_volatile()) { 1.11 + uint alias_idx = atp->index(); 1.12 + bool final = atp->field()->is_final(); 1.13 + Node* result = NULL; 1.14 + Node* current = st; 1.15 + // Skip through chains of MemBarNodes checking the MergeMems for 1.16 + // new states for the slice of this load. Stop once any other 1.17 + // kind of node is encountered. Loads from final memory can skip 1.18 + // through any kind of MemBar but normal loads shouldn't skip 1.19 + // through MemBarAcquire since the could allow them to move out of 1.20 + // a synchronized region. 1.21 + while (current->is_Proj()) { 1.22 + int opc = current->in(0)->Opcode(); 1.23 + if ((final && opc == Op_MemBarAcquire) || 1.24 + opc == Op_MemBarRelease || opc == Op_MemBarCPUOrder) { 1.25 + Node* mem = current->in(0)->in(TypeFunc::Memory); 1.26 + if (mem->is_MergeMem()) { 1.27 + MergeMemNode* merge = mem->as_MergeMem(); 1.28 + Node* new_st = merge->memory_at(alias_idx); 1.29 + if (new_st == merge->base_memory()) { 1.30 + // Keep searching 1.31 + current = merge->base_memory(); 1.32 + continue; 1.33 + } 1.34 + // Save the new memory state for the slice and fall through 1.35 + // to exit. 1.36 + result = new_st; 1.37 + } 1.38 + } 1.39 + break; 1.40 + } 1.41 + if (result != NULL) { 1.42 + st = result; 1.43 + } 1.44 + } 1.45 + 1.46 + 1.47 // Loop around twice in the case Load -> Initialize -> Store. 1.48 // (See PhaseIterGVN::add_users_to_worklist, which knows about this case.) 1.49 for (int trip = 0; trip <= 1; trip++) { 1.50 @@ -723,6 +763,168 @@ 1.51 return this; 1.52 } 1.53 1.54 + 1.55 +// Returns true if the AliasType refers to the field that holds the 1.56 +// cached box array. Currently only handles the IntegerCache case. 1.57 +static bool is_autobox_cache(Compile::AliasType* atp) { 1.58 + if (atp != NULL && atp->field() != NULL) { 1.59 + ciField* field = atp->field(); 1.60 + ciSymbol* klass = field->holder()->name(); 1.61 + if (field->name() == ciSymbol::cache_field_name() && 1.62 + field->holder()->uses_default_loader() && 1.63 + klass == ciSymbol::java_lang_Integer_IntegerCache()) { 1.64 + return true; 1.65 + } 1.66 + } 1.67 + return false; 1.68 +} 1.69 + 1.70 +// Fetch the base value in the autobox array 1.71 +static bool fetch_autobox_base(Compile::AliasType* atp, int& cache_offset) { 1.72 + if (atp != NULL && atp->field() != NULL) { 1.73 + ciField* field = atp->field(); 1.74 + ciSymbol* klass = field->holder()->name(); 1.75 + if (field->name() == ciSymbol::cache_field_name() && 1.76 + field->holder()->uses_default_loader() && 1.77 + klass == ciSymbol::java_lang_Integer_IntegerCache()) { 1.78 + assert(field->is_constant(), "what?"); 1.79 + ciObjArray* array = field->constant_value().as_object()->as_obj_array(); 1.80 + // Fetch the box object at the base of the array and get its value 1.81 + ciInstance* box = array->obj_at(0)->as_instance(); 1.82 + ciInstanceKlass* ik = box->klass()->as_instance_klass(); 1.83 + if (ik->nof_nonstatic_fields() == 1) { 1.84 + // This should be true nonstatic_field_at requires calling 1.85 + // nof_nonstatic_fields so check it anyway 1.86 + ciConstant c = box->field_value(ik->nonstatic_field_at(0)); 1.87 + cache_offset = c.as_int(); 1.88 + } 1.89 + return true; 1.90 + } 1.91 + } 1.92 + return false; 1.93 +} 1.94 + 1.95 +// Returns true if the AliasType refers to the value field of an 1.96 +// autobox object. Currently only handles Integer. 1.97 +static bool is_autobox_object(Compile::AliasType* atp) { 1.98 + if (atp != NULL && atp->field() != NULL) { 1.99 + ciField* field = atp->field(); 1.100 + ciSymbol* klass = field->holder()->name(); 1.101 + if (field->name() == ciSymbol::value_name() && 1.102 + field->holder()->uses_default_loader() && 1.103 + klass == ciSymbol::java_lang_Integer()) { 1.104 + return true; 1.105 + } 1.106 + } 1.107 + return false; 1.108 +} 1.109 + 1.110 + 1.111 +// We're loading from an object which has autobox behaviour. 1.112 +// If this object is result of a valueOf call we'll have a phi 1.113 +// merging a newly allocated object and a load from the cache. 1.114 +// We want to replace this load with the original incoming 1.115 +// argument to the valueOf call. 1.116 +Node* LoadNode::eliminate_autobox(PhaseGVN* phase) { 1.117 + Node* base = in(Address)->in(AddPNode::Base); 1.118 + if (base->is_Phi() && base->req() == 3) { 1.119 + AllocateNode* allocation = NULL; 1.120 + int allocation_index = -1; 1.121 + int load_index = -1; 1.122 + for (uint i = 1; i < base->req(); i++) { 1.123 + allocation = AllocateNode::Ideal_allocation(base->in(i), phase); 1.124 + if (allocation != NULL) { 1.125 + allocation_index = i; 1.126 + load_index = 3 - allocation_index; 1.127 + break; 1.128 + } 1.129 + } 1.130 + LoadNode* load = NULL; 1.131 + if (allocation != NULL && base->in(load_index)->is_Load()) { 1.132 + load = base->in(load_index)->as_Load(); 1.133 + } 1.134 + if (load != NULL && in(Memory)->is_Phi() && in(Memory)->in(0) == base->in(0)) { 1.135 + // Push the loads from the phi that comes from valueOf up 1.136 + // through it to allow elimination of the loads and the recovery 1.137 + // of the original value. 1.138 + Node* mem_phi = in(Memory); 1.139 + Node* offset = in(Address)->in(AddPNode::Offset); 1.140 + 1.141 + Node* in1 = clone(); 1.142 + Node* in1_addr = in1->in(Address)->clone(); 1.143 + in1_addr->set_req(AddPNode::Base, base->in(allocation_index)); 1.144 + in1_addr->set_req(AddPNode::Address, base->in(allocation_index)); 1.145 + in1_addr->set_req(AddPNode::Offset, offset); 1.146 + in1->set_req(0, base->in(allocation_index)); 1.147 + in1->set_req(Address, in1_addr); 1.148 + in1->set_req(Memory, mem_phi->in(allocation_index)); 1.149 + 1.150 + Node* in2 = clone(); 1.151 + Node* in2_addr = in2->in(Address)->clone(); 1.152 + in2_addr->set_req(AddPNode::Base, base->in(load_index)); 1.153 + in2_addr->set_req(AddPNode::Address, base->in(load_index)); 1.154 + in2_addr->set_req(AddPNode::Offset, offset); 1.155 + in2->set_req(0, base->in(load_index)); 1.156 + in2->set_req(Address, in2_addr); 1.157 + in2->set_req(Memory, mem_phi->in(load_index)); 1.158 + 1.159 + in1_addr = phase->transform(in1_addr); 1.160 + in1 = phase->transform(in1); 1.161 + in2_addr = phase->transform(in2_addr); 1.162 + in2 = phase->transform(in2); 1.163 + 1.164 + PhiNode* result = PhiNode::make_blank(base->in(0), this); 1.165 + result->set_req(allocation_index, in1); 1.166 + result->set_req(load_index, in2); 1.167 + return result; 1.168 + } 1.169 + } else if (base->is_Load()) { 1.170 + // Eliminate the load of Integer.value for integers from the cache 1.171 + // array by deriving the value from the index into the array. 1.172 + // Capture the offset of the load and then reverse the computation. 1.173 + Node* load_base = base->in(Address)->in(AddPNode::Base); 1.174 + if (load_base != NULL) { 1.175 + Compile::AliasType* atp = phase->C->alias_type(load_base->adr_type()); 1.176 + intptr_t cache_offset; 1.177 + int shift = -1; 1.178 + Node* cache = NULL; 1.179 + if (is_autobox_cache(atp)) { 1.180 + shift = exact_log2(type2aelembytes[T_OBJECT]); 1.181 + cache = AddPNode::Ideal_base_and_offset(load_base->in(Address), phase, cache_offset); 1.182 + } 1.183 + if (cache != NULL && base->in(Address)->is_AddP()) { 1.184 + Node* elements[4]; 1.185 + int count = base->in(Address)->as_AddP()->unpack_offsets(elements, ARRAY_SIZE(elements)); 1.186 + int cache_low; 1.187 + if (count > 0 && fetch_autobox_base(atp, cache_low)) { 1.188 + int offset = arrayOopDesc::base_offset_in_bytes(memory_type()) - (cache_low << shift); 1.189 + // Add up all the offsets making of the address of the load 1.190 + Node* result = elements[0]; 1.191 + for (int i = 1; i < count; i++) { 1.192 + result = phase->transform(new (phase->C, 3) AddXNode(result, elements[i])); 1.193 + } 1.194 + // Remove the constant offset from the address and then 1.195 + // remove the scaling of the offset to recover the original index. 1.196 + result = phase->transform(new (phase->C, 3) AddXNode(result, phase->MakeConX(-offset))); 1.197 + if (result->Opcode() == Op_LShiftX && result->in(2) == phase->intcon(shift)) { 1.198 + // Peel the shift off directly but wrap it in a dummy node 1.199 + // since Ideal can't return existing nodes 1.200 + result = new (phase->C, 3) RShiftXNode(result->in(1), phase->intcon(0)); 1.201 + } else { 1.202 + result = new (phase->C, 3) RShiftXNode(result, phase->intcon(shift)); 1.203 + } 1.204 +#ifdef _LP64 1.205 + result = new (phase->C, 2) ConvL2INode(phase->transform(result)); 1.206 +#endif 1.207 + return result; 1.208 + } 1.209 + } 1.210 + } 1.211 + } 1.212 + return NULL; 1.213 +} 1.214 + 1.215 + 1.216 //------------------------------Ideal------------------------------------------ 1.217 // If the load is from Field memory and the pointer is non-null, we can 1.218 // zero out the control input. 1.219 @@ -755,6 +957,17 @@ 1.220 } 1.221 } 1.222 1.223 + if (EliminateAutoBox && can_reshape && in(Address)->is_AddP()) { 1.224 + Node* base = in(Address)->in(AddPNode::Base); 1.225 + if (base != NULL) { 1.226 + Compile::AliasType* atp = phase->C->alias_type(adr_type()); 1.227 + if (is_autobox_object(atp)) { 1.228 + Node* result = eliminate_autobox(phase); 1.229 + if (result != NULL) return result; 1.230 + } 1.231 + } 1.232 + } 1.233 + 1.234 // Check for prior store with a different base or offset; make Load 1.235 // independent. Skip through any number of them. Bail out if the stores 1.236 // are in an endless dead cycle and report no progress. This is a key 1.237 @@ -858,6 +1071,17 @@ 1.238 // This can happen if a interface-typed array narrows to a class type. 1.239 jt = _type; 1.240 } 1.241 + 1.242 + if (EliminateAutoBox) { 1.243 + // The pointers in the autobox arrays are always non-null 1.244 + Node* base = in(Address)->in(AddPNode::Base); 1.245 + if (base != NULL) { 1.246 + Compile::AliasType* atp = phase->C->alias_type(base->adr_type()); 1.247 + if (is_autobox_cache(atp)) { 1.248 + return jt->join(TypePtr::NOTNULL)->is_ptr(); 1.249 + } 1.250 + } 1.251 + } 1.252 return jt; 1.253 } 1.254 }