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

src/share/vm/opto/library_call.cpp

Print this page
rev 7687 : 6912521: System.arraycopy works slower than the simple loop for little lengths
Summary: convert small array copies to series of loads and stores
Reviewed-by:


3932       PreserveJVMState pjvms(this);
3933       set_control(_gvn.transform(bailout));
3934       uncommon_trap(Deoptimization::Reason_intrinsic,
3935                     Deoptimization::Action_maybe_recompile);
3936     }
3937 
3938     if (!stopped()) {
3939       // How many elements will we copy from the original?
3940       // The answer is MinI(orig_length - start, length).
3941       Node* orig_tail = _gvn.transform(new SubINode(orig_length, start));
3942       Node* moved = generate_min_max(vmIntrinsics::_min, orig_tail, length);
3943 
3944       newcopy = new_array(klass_node, length, 0);  // no arguments to push
3945 
3946       // Generate a direct call to the right arraycopy function(s).
3947       // We know the copy is disjoint but we might not know if the
3948       // oop stores need checking.
3949       // Extreme case:  Arrays.copyOf((Integer[])x, 10, String[].class).
3950       // This will fail a store-check if x contains any non-nulls.
3951 
3952       Node* alloc = tightly_coupled_allocation(newcopy, NULL);


3953 
3954       ArrayCopyNode* ac = ArrayCopyNode::make(this, true, original, start, newcopy, intcon(0), moved, alloc != NULL,


























3955                                               load_object_klass(original), klass_node);
3956       if (!is_copyOfRange) {
3957         ac->set_copyof();
3958       } else {
3959         ac->set_copyofrange();
3960       }
3961       Node* n = _gvn.transform(ac);
3962       assert(n == ac, "cannot disappear");
3963       ac->connect_outputs(this);




3964     }
3965   } // original reexecute is set back here
3966 
3967   C->set_has_split_ifs(true); // Has chance for split-if optimization
3968   if (!stopped()) {
3969     set_result(newcopy);
3970   }
3971   return true;
3972 }
3973 
3974 
3975 //----------------------generate_virtual_guard---------------------------
3976 // Helper for hashCode and clone.  Peeks inside the vtable to avoid a call.
3977 Node* LibraryCallKit::generate_virtual_guard(Node* obj_klass,
3978                                              RegionNode* slow_region) {
3979   ciMethod* method = callee();
3980   int vtable_index = method->vtable_index();
3981   assert(vtable_index >= 0 || vtable_index == Method::nonvirtual_vtable_index,
3982          err_msg_res("bad index %d", vtable_index));
3983   // Get the Method* out of the appropriate vtable entry.




3932       PreserveJVMState pjvms(this);
3933       set_control(_gvn.transform(bailout));
3934       uncommon_trap(Deoptimization::Reason_intrinsic,
3935                     Deoptimization::Action_maybe_recompile);
3936     }
3937 
3938     if (!stopped()) {
3939       // How many elements will we copy from the original?
3940       // The answer is MinI(orig_length - start, length).
3941       Node* orig_tail = _gvn.transform(new SubINode(orig_length, start));
3942       Node* moved = generate_min_max(vmIntrinsics::_min, orig_tail, length);
3943 
3944       newcopy = new_array(klass_node, length, 0);  // no arguments to push
3945 
3946       // Generate a direct call to the right arraycopy function(s).
3947       // We know the copy is disjoint but we might not know if the
3948       // oop stores need checking.
3949       // Extreme case:  Arrays.copyOf((Integer[])x, 10, String[].class).
3950       // This will fail a store-check if x contains any non-nulls.
3951 
3952       if (_gvn.type(klass_node)->singleton()) {
3953         ciKlass* subk   = _gvn.type(load_object_klass(original))->is_klassptr()->klass();
3954         ciKlass* superk = _gvn.type(klass_node)->is_klassptr()->klass();
3955 
3956         int test = C->static_subtype_check(superk, subk);
3957         if (test != Compile::SSC_always_true && test != Compile::SSC_always_false) {
3958           const TypeOopPtr* t_original = _gvn.type(original)->is_oopptr();
3959           if (t_original->speculative_type() != NULL) {
3960             original = maybe_cast_profiled_obj(original, t_original->speculative_type(), true);
3961           }
3962         }
3963       }
3964 
3965       bool validated = false;
3966       // Reason_class_check rather than Reason_intrinsic because we
3967       // want to intrinsify even if this traps.
3968       if (!too_many_traps(Deoptimization::Reason_class_check)) {
3969         Node* not_subtype_ctrl = gen_subtype_check(load_object_klass(original),
3970                                                    klass_node);
3971         
3972         if (not_subtype_ctrl != top()) {
3973           PreserveJVMState pjvms(this);
3974           set_control(not_subtype_ctrl);
3975           uncommon_trap(Deoptimization::Reason_class_check,
3976                         Deoptimization::Action_make_not_entrant);
3977           assert(stopped(), "Should be stopped");
3978         }
3979         validated = true;
3980       }
3981 
3982       ArrayCopyNode* ac = ArrayCopyNode::make(this, true, original, start, newcopy, intcon(0), moved, true,
3983                                               load_object_klass(original), klass_node);
3984       if (!is_copyOfRange) {
3985         ac->set_copyof(validated);
3986       } else {
3987         ac->set_copyofrange(validated);
3988       }
3989       Node* n = _gvn.transform(ac);
3990       if (n == ac) {
3991         ac->connect_outputs(this);
3992       } else {
3993         assert(validated, "shouldn't transform if all arguments not validated");
3994         set_all_memory(n);
3995       }
3996     }
3997   } // original reexecute is set back here
3998 
3999   C->set_has_split_ifs(true); // Has chance for split-if optimization
4000   if (!stopped()) {
4001     set_result(newcopy);
4002   }
4003   return true;
4004 }
4005 
4006 
4007 //----------------------generate_virtual_guard---------------------------
4008 // Helper for hashCode and clone.  Peeks inside the vtable to avoid a call.
4009 Node* LibraryCallKit::generate_virtual_guard(Node* obj_klass,
4010                                              RegionNode* slow_region) {
4011   ciMethod* method = callee();
4012   int vtable_index = method->vtable_index();
4013   assert(vtable_index >= 0 || vtable_index == Method::nonvirtual_vtable_index,
4014          err_msg_res("bad index %d", vtable_index));
4015   // Get the Method* out of the appropriate vtable entry.


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