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) %{ |