src/share/vm/opto/library_call.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Cdiff src/share/vm/opto/library_call.cpp

src/share/vm/opto/library_call.cpp

Print this page
rev 7589 : 6700100: optimize inline_native_clone() for small objects with exact klass
Summary: optimize small instance clones as loads/stores
Reviewed-by:

*** 4473,4484 **** const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM; ArrayCopyNode* ac = ArrayCopyNode::make(this, false, src, NULL, dest, NULL, countx, false); ac->set_clonebasic(); Node* n = _gvn.transform(ac); ! assert(n == ac, "cannot disappear"); set_predefined_output_for_runtime_call(ac, ac->in(TypeFunc::Memory), raw_adr_type); // If necessary, emit some card marks afterwards. (Non-arrays only.) if (card_mark) { assert(!is_array, ""); // Put in store barrier for any and all oops we are sticking --- 4473,4487 ---- const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM; ArrayCopyNode* ac = ArrayCopyNode::make(this, false, src, NULL, dest, NULL, countx, false); ac->set_clonebasic(); Node* n = _gvn.transform(ac); ! if (n == ac) { set_predefined_output_for_runtime_call(ac, ac->in(TypeFunc::Memory), raw_adr_type); + } else { + set_all_memory(n); + } // If necessary, emit some card marks afterwards. (Non-arrays only.) if (card_mark) { assert(!is_array, ""); // Put in store barrier for any and all oops we are sticking
*** 4539,4548 **** --- 4542,4571 ---- jvms()->set_should_reexecute(true); Node* obj = null_check_receiver(); if (stopped()) return true; + const TypeOopPtr* obj_type = _gvn.type(obj)->is_oopptr(); + + // If we are going to clone an instance, we need its exact type to + // know the number and types of fields to convert the clone to + // loads/stores. Maybe a speculative type can help us. + if (!obj_type->klass_is_exact() && + obj_type->speculative_type() != NULL && + obj_type->speculative_type()->is_instance_klass()) { + ciInstanceKlass* spec_ik = obj_type->speculative_type()->as_instance_klass(); + if (spec_ik->nof_nonstatic_fields() <= ArrayCopyLoadStoreMaxElem && + !spec_ik->has_injected_fields()) { + ciKlass* k = obj_type->klass(); + if (!k->is_instance_klass() || + k->as_instance_klass()->is_interface() || + k->as_instance_klass()->has_subklass()) { + obj = maybe_cast_profiled_obj(obj, obj_type->speculative_type(), false); + } + } + } + Node* obj_klass = load_object_klass(obj); const TypeKlassPtr* tklass = _gvn.type(obj_klass)->isa_klassptr(); const TypeOopPtr* toop = ((tklass != NULL) ? tklass->as_instance_type() : TypeInstPtr::NOTNULL);
*** 4741,4751 **** sfpt->set_i_o(map()->i_o()); sfpt->set_memory(map()->memory()); } ! bool notest = false; const Type* src_type = _gvn.type(src); const Type* dest_type = _gvn.type(dest); const TypeAryPtr* top_src = src_type->isa_aryptr(); const TypeAryPtr* top_dest = dest_type->isa_aryptr(); --- 4764,4774 ---- sfpt->set_i_o(map()->i_o()); sfpt->set_memory(map()->memory()); } ! bool validated = false; const Type* src_type = _gvn.type(src); const Type* dest_type = _gvn.type(dest); const TypeAryPtr* top_src = src_type->isa_aryptr(); const TypeAryPtr* top_dest = dest_type->isa_aryptr();
*** 4845,4855 **** } } if (!too_many_traps(Deoptimization::Reason_intrinsic) && !src->is_top() && !dest->is_top()) { // validate arguments: enables transformation the ArrayCopyNode ! notest = true; RegionNode* slow_region = new RegionNode(1); record_for_igvn(slow_region); // (1) src and dest are arrays. --- 4868,4878 ---- } } if (!too_many_traps(Deoptimization::Reason_intrinsic) && !src->is_top() && !dest->is_top()) { // validate arguments: enables transformation the ArrayCopyNode ! validated = true; RegionNode* slow_region = new RegionNode(1); record_for_igvn(slow_region); // (1) src and dest are arrays.
*** 4920,4936 **** // so the compiler has a chance to eliminate them: during macro expansion, // we have to set their control (CastPP nodes are eliminated). load_object_klass(src), load_object_klass(dest), load_array_length(src), load_array_length(dest)); ! if (notest) { ! ac->set_arraycopy_notest(); ! } Node* n = _gvn.transform(ac); ! assert(n == ac, "cannot disappear"); ac->connect_outputs(this); return true; } --- 4943,4961 ---- // so the compiler has a chance to eliminate them: during macro expansion, // we have to set their control (CastPP nodes are eliminated). load_object_klass(src), load_object_klass(dest), load_array_length(src), load_array_length(dest)); ! ac->set_arraycopy(validated); Node* n = _gvn.transform(ac); ! if (n == ac) { ac->connect_outputs(this); + } else { + assert(validated, "shouldn't transform if all arguments not validated"); + set_all_memory(n); + } return true; }
src/share/vm/opto/library_call.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File