hotspot/src/cpu/sparc/vm/sparc.ad
changeset 35086 bbf32241d851
parent 34162 16b54851eaf6
child 35135 dd2ce9021031
equal deleted inserted replaced
35085:839c8ba29724 35086:bbf32241d851
   999     }
   999     }
  1000   }
  1000   }
  1001 #endif
  1001 #endif
  1002 }
  1002 }
  1003 
  1003 
  1004 void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocType rtype, bool preserve_g2 = false) {
  1004 void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, RelocationHolder const& rspec, bool preserve_g2 = false) {
  1005   // The method which records debug information at every safepoint
  1005   // The method which records debug information at every safepoint
  1006   // expects the call to be the first instruction in the snippet as
  1006   // expects the call to be the first instruction in the snippet as
  1007   // it creates a PcDesc structure which tracks the offset of a call
  1007   // it creates a PcDesc structure which tracks the offset of a call
  1008   // from the start of the codeBlob. This offset is computed as
  1008   // from the start of the codeBlob. This offset is computed as
  1009   // code_end() - code_begin() of the code which has been emitted
  1009   // code_end() - code_begin() of the code which has been emitted
  1021 
  1021 
  1022 #ifdef ASSERT
  1022 #ifdef ASSERT
  1023   int startpos = __ offset();
  1023   int startpos = __ offset();
  1024 #endif /* ASSERT */
  1024 #endif /* ASSERT */
  1025 
  1025 
  1026   __ call((address)entry_point, rtype);
  1026   __ call((address)entry_point, rspec);
  1027 
  1027 
  1028   if (preserve_g2)   __ delayed()->mov(G2, L7);
  1028   if (preserve_g2)   __ delayed()->mov(G2, L7);
  1029   else __ delayed()->nop();
  1029   else __ delayed()->nop();
  1030 
  1030 
  1031   if (preserve_g2)   __ mov(L7, G2);
  1031   if (preserve_g2)   __ mov(L7, G2);
  2591   %}
  2591   %}
  2592 
  2592 
  2593   enc_class Java_To_Runtime (method meth) %{    // CALL Java_To_Runtime
  2593   enc_class Java_To_Runtime (method meth) %{    // CALL Java_To_Runtime
  2594     // CALL directly to the runtime
  2594     // CALL directly to the runtime
  2595     // The user of this is responsible for ensuring that R_L7 is empty (killed).
  2595     // The user of this is responsible for ensuring that R_L7 is empty (killed).
  2596     emit_call_reloc(cbuf, $meth$$method, relocInfo::runtime_call_type,
  2596     emit_call_reloc(cbuf, $meth$$method, runtime_call_Relocation::spec(), /*preserve_g2=*/true);
  2597                     /*preserve_g2=*/true);
       
  2598   %}
  2597   %}
  2599 
  2598 
  2600   enc_class preserve_SP %{
  2599   enc_class preserve_SP %{
  2601     MacroAssembler _masm(&cbuf);
  2600     MacroAssembler _masm(&cbuf);
  2602     __ mov(SP, L7_mh_SP_save);
  2601     __ mov(SP, L7_mh_SP_save);
  2609 
  2608 
  2610   enc_class Java_Static_Call (method meth) %{    // JAVA STATIC CALL
  2609   enc_class Java_Static_Call (method meth) %{    // JAVA STATIC CALL
  2611     // CALL to fixup routine.  Fixup routine uses ScopeDesc info to determine
  2610     // CALL to fixup routine.  Fixup routine uses ScopeDesc info to determine
  2612     // who we intended to call.
  2611     // who we intended to call.
  2613     if (!_method) {
  2612     if (!_method) {
  2614       emit_call_reloc(cbuf, $meth$$method, relocInfo::runtime_call_type);
  2613       emit_call_reloc(cbuf, $meth$$method, runtime_call_Relocation::spec());
  2615     } else if (_optimized_virtual) {
       
  2616       emit_call_reloc(cbuf, $meth$$method, relocInfo::opt_virtual_call_type);
       
  2617     } else {
  2614     } else {
  2618       emit_call_reloc(cbuf, $meth$$method, relocInfo::static_call_type);
  2615       int method_index = resolved_method_index(cbuf);
  2619     }
  2616       RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index)
  2620     if (_method) {  // Emit stub for static call.
  2617                                                   : static_call_Relocation::spec(method_index);
       
  2618       emit_call_reloc(cbuf, $meth$$method, rspec);
       
  2619 
       
  2620       // Emit stub for static call.
  2621       address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
  2621       address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
  2622       // Stub does not fit into scratch buffer if TraceJumps is enabled
  2622       // Stub does not fit into scratch buffer if TraceJumps is enabled
  2623       if (stub == NULL && !(TraceJumps && Compile::current()->in_scratch_emit_size())) {
  2623       if (stub == NULL && !(TraceJumps && Compile::current()->in_scratch_emit_size())) {
  2624         ciEnv::current()->record_failure("CodeCache is full");
  2624         ciEnv::current()->record_failure("CodeCache is full");
  2625         return;
  2625         return;
  2636       // must be invalid_vtable_index, not nonvirtual_vtable_index
  2636       // must be invalid_vtable_index, not nonvirtual_vtable_index
  2637       assert(vtable_index == Method::invalid_vtable_index, "correct sentinel value");
  2637       assert(vtable_index == Method::invalid_vtable_index, "correct sentinel value");
  2638       Register G5_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode());
  2638       Register G5_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode());
  2639       assert(G5_ic_reg == G5_inline_cache_reg, "G5_inline_cache_reg used in assemble_ic_buffer_code()");
  2639       assert(G5_ic_reg == G5_inline_cache_reg, "G5_inline_cache_reg used in assemble_ic_buffer_code()");
  2640       assert(G5_ic_reg == G5_megamorphic_method, "G5_megamorphic_method used in megamorphic call stub");
  2640       assert(G5_ic_reg == G5_megamorphic_method, "G5_megamorphic_method used in megamorphic call stub");
  2641       __ ic_call((address)$meth$$method);
  2641       __ ic_call((address)$meth$$method, /*emit_delay=*/true, resolved_method_index(cbuf));
  2642     } else {
  2642     } else {
  2643       assert(!UseInlineCaches, "expect vtable calls only if not using ICs");
  2643       assert(!UseInlineCaches, "expect vtable calls only if not using ICs");
  2644       // Just go thru the vtable
  2644       // Just go thru the vtable
  2645       // get receiver klass (receiver already checked for non-null)
  2645       // get receiver klass (receiver already checked for non-null)
  2646       // If we end up going thru a c2i adapter interpreter expects method in G5
  2646       // If we end up going thru a c2i adapter interpreter expects method in G5
 10067   effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp);
 10067   effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp);
 10068   ins_cost(300);
 10068   ins_cost(300);
 10069   format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp" %}
 10069   format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp" %}
 10070   ins_encode %{
 10070   ins_encode %{
 10071     __ string_compare($str1$$Register, $str2$$Register,
 10071     __ string_compare($str1$$Register, $str2$$Register,
 10072                       $cnt1$$Register, $cnt2$$Register, 
 10072                       $cnt1$$Register, $cnt2$$Register,
 10073                       $tmp$$Register, $tmp$$Register,
 10073                       $tmp$$Register, $tmp$$Register,
 10074                       $result$$Register, StrIntrinsicNode::LL);
 10074                       $result$$Register, StrIntrinsicNode::LL);
 10075   %}                    
 10075   %}
 10076   ins_pipe(long_memory_op);
 10076   ins_pipe(long_memory_op);
 10077 %}
 10077 %}
 10078 
 10078 
 10079 instruct string_compareU(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
 10079 instruct string_compareU(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
 10080                          o7RegI tmp, flagsReg ccr) %{
 10080                          o7RegI tmp, flagsReg ccr) %{
 10086   ins_encode %{
 10086   ins_encode %{
 10087     __ string_compare($str1$$Register, $str2$$Register,
 10087     __ string_compare($str1$$Register, $str2$$Register,
 10088                       $cnt1$$Register, $cnt2$$Register,
 10088                       $cnt1$$Register, $cnt2$$Register,
 10089                       $tmp$$Register, $tmp$$Register,
 10089                       $tmp$$Register, $tmp$$Register,
 10090                       $result$$Register, StrIntrinsicNode::UU);
 10090                       $result$$Register, StrIntrinsicNode::UU);
 10091   %}                    
 10091   %}
 10092   ins_pipe(long_memory_op);
 10092   ins_pipe(long_memory_op);
 10093 %}
 10093 %}
 10094 
 10094 
 10095 instruct string_compareLU(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
 10095 instruct string_compareLU(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
 10096                           o7RegI tmp1, g1RegI tmp2, flagsReg ccr) %{
 10096                           o7RegI tmp1, g1RegI tmp2, flagsReg ccr) %{
 10102   ins_encode %{
 10102   ins_encode %{
 10103     __ string_compare($str1$$Register, $str2$$Register,
 10103     __ string_compare($str1$$Register, $str2$$Register,
 10104                       $cnt1$$Register, $cnt2$$Register,
 10104                       $cnt1$$Register, $cnt2$$Register,
 10105                       $tmp1$$Register, $tmp2$$Register,
 10105                       $tmp1$$Register, $tmp2$$Register,
 10106                       $result$$Register, StrIntrinsicNode::LU);
 10106                       $result$$Register, StrIntrinsicNode::LU);
 10107   %}                    
 10107   %}
 10108   ins_pipe(long_memory_op);
 10108   ins_pipe(long_memory_op);
 10109 %}
 10109 %}
 10110 
 10110 
 10111 instruct string_compareUL(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
 10111 instruct string_compareUL(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
 10112                           o7RegI tmp1, g1RegI tmp2, flagsReg ccr) %{
 10112                           o7RegI tmp1, g1RegI tmp2, flagsReg ccr) %{
 10115   effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp1, KILL tmp2);
 10115   effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp1, KILL tmp2);
 10116   ins_cost(300);
 10116   ins_cost(300);
 10117   format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp1,$tmp2" %}
 10117   format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp1,$tmp2" %}
 10118   ins_encode %{
 10118   ins_encode %{
 10119     __ string_compare($str2$$Register, $str1$$Register,
 10119     __ string_compare($str2$$Register, $str1$$Register,
 10120                       $cnt2$$Register, $cnt1$$Register, 
 10120                       $cnt2$$Register, $cnt1$$Register,
 10121                       $tmp1$$Register, $tmp2$$Register,
 10121                       $tmp1$$Register, $tmp2$$Register,
 10122                       $result$$Register, StrIntrinsicNode::UL);
 10122                       $result$$Register, StrIntrinsicNode::UL);
 10123   %}                    
 10123   %}
 10124   ins_pipe(long_memory_op);
 10124   ins_pipe(long_memory_op);
 10125 %}
 10125 %}
 10126 
 10126 
 10127 instruct string_equalsL(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result,
 10127 instruct string_equalsL(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result,
 10128                         o7RegI tmp, flagsReg ccr) %{
 10128                         o7RegI tmp, flagsReg ccr) %{