--- old/src/share/vm/opto/library_call.cpp 2014-10-23 13:31:09.167468562 +0200 +++ new/src/share/vm/opto/library_call.cpp 2014-10-23 13:31:08.912367452 +0200 @@ -4389,8 +4389,11 @@ 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 (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) { @@ -4455,6 +4458,26 @@ 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) @@ -4631,7 +4654,7 @@ src = null_check(src, T_ARRAY); dest = null_check(dest, T_ARRAY); - bool notest = false; + bool validated = false; const Type* src_type = _gvn.type(src); const Type* dest_type = _gvn.type(dest); @@ -4735,7 +4758,7 @@ if (!too_many_traps(Deoptimization::Reason_intrinsic) && !src->is_top() && !dest->is_top()) { // validate arguments: enables transformation the ArrayCopyNode - notest = true; + validated = true; RegionNode* slow_region = new RegionNode(1); record_for_igvn(slow_region); @@ -4795,13 +4818,15 @@ load_object_klass(src), load_object_klass(dest), load_array_length(src), load_array_length(dest)); - if (notest) { - ac->set_arraycopy_notest(); - } + ac->set_arraycopy(validated); Node* n = _gvn.transform(ac); - assert(n == ac, "cannot disappear"); - ac->connect_outputs(this); + if (n == ac) { + ac->connect_outputs(this); + } else { + assert(validated, "shouldn't transform if all arguments not validated"); + set_all_memory(n); + } return true; }