< prev index next >

src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp

Print this page

  25  */
  26 
  27 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
  28 #include "gc/shenandoah/mode/shenandoahMode.hpp"
  29 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  30 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
  31 #include "gc/shenandoah/shenandoahForwarding.hpp"
  32 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  33 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
  34 #include "gc/shenandoah/shenandoahRuntime.hpp"
  35 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
  36 #include "interpreter/interp_masm.hpp"
  37 #include "interpreter/interpreter.hpp"
  38 #include "runtime/javaThread.hpp"
  39 #include "runtime/sharedRuntime.hpp"
  40 #ifdef COMPILER1
  41 #include "c1/c1_LIRAssembler.hpp"
  42 #include "c1/c1_MacroAssembler.hpp"
  43 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
  44 #endif




  45 
  46 #define __ masm->
  47 
  48 void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
  49                                                        Register src, Register dst, Register count, RegSet saved_regs) {
  50   if (is_oop) {
  51     bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
  52     if ((ShenandoahSATBBarrier && !dest_uninitialized) || ShenandoahLoadRefBarrier) {
  53 
  54       Label done;
  55 
  56       // Avoid calling runtime if count == 0
  57       __ cbz(count, done);
  58 
  59       // Is GC active?
  60       assert(!saved_regs.contains(rscratch1), "Sanity: about to clobber rscratch1");
  61       assert(!saved_regs.contains(rscratch2), "Sanity: about to clobber rscratch2");
  62       Address gc_state(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
  63       __ ldrb(rscratch1, gc_state);
  64       if (ShenandoahSATBBarrier && dest_uninitialized) {

 814       __ lea(lr, RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak_narrow)));
 815     } else {
 816       __ lea(lr, RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak)));
 817     }
 818   } else {
 819     assert(is_phantom, "only remaining strength");
 820     assert(is_native, "phantom must only be called off-heap");
 821     __ lea(lr, RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom)));
 822   }
 823   __ blr(lr);
 824   __ mov(rscratch1, r0);
 825   __ pop_call_clobbered_registers();
 826   __ mov(r0, rscratch1);
 827 
 828   __ epilogue();
 829 }
 830 
 831 #undef __
 832 
 833 #endif // COMPILER1















































































































































































































































































































































































































































  25  */
  26 
  27 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
  28 #include "gc/shenandoah/mode/shenandoahMode.hpp"
  29 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  30 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
  31 #include "gc/shenandoah/shenandoahForwarding.hpp"
  32 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  33 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
  34 #include "gc/shenandoah/shenandoahRuntime.hpp"
  35 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
  36 #include "interpreter/interp_masm.hpp"
  37 #include "interpreter/interpreter.hpp"
  38 #include "runtime/javaThread.hpp"
  39 #include "runtime/sharedRuntime.hpp"
  40 #ifdef COMPILER1
  41 #include "c1/c1_LIRAssembler.hpp"
  42 #include "c1/c1_MacroAssembler.hpp"
  43 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
  44 #endif
  45 #ifdef COMPILER2
  46 #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
  47 #include "opto/output.hpp"
  48 #endif
  49 
  50 #define __ masm->
  51 
  52 void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
  53                                                        Register src, Register dst, Register count, RegSet saved_regs) {
  54   if (is_oop) {
  55     bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
  56     if ((ShenandoahSATBBarrier && !dest_uninitialized) || ShenandoahLoadRefBarrier) {
  57 
  58       Label done;
  59 
  60       // Avoid calling runtime if count == 0
  61       __ cbz(count, done);
  62 
  63       // Is GC active?
  64       assert(!saved_regs.contains(rscratch1), "Sanity: about to clobber rscratch1");
  65       assert(!saved_regs.contains(rscratch2), "Sanity: about to clobber rscratch2");
  66       Address gc_state(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
  67       __ ldrb(rscratch1, gc_state);
  68       if (ShenandoahSATBBarrier && dest_uninitialized) {

 818       __ lea(lr, RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak_narrow)));
 819     } else {
 820       __ lea(lr, RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak)));
 821     }
 822   } else {
 823     assert(is_phantom, "only remaining strength");
 824     assert(is_native, "phantom must only be called off-heap");
 825     __ lea(lr, RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom)));
 826   }
 827   __ blr(lr);
 828   __ mov(rscratch1, r0);
 829   __ pop_call_clobbered_registers();
 830   __ mov(r0, rscratch1);
 831 
 832   __ epilogue();
 833 }
 834 
 835 #undef __
 836 
 837 #endif // COMPILER1
 838 
 839 #ifdef COMPILER2
 840 
 841 #undef __
 842 #define __ masm->
 843 
 844 
 845 void ShenandoahBarrierSetAssembler::load_c2(const MachNode* node, MacroAssembler* masm, Register dst, Address src, Register tmp1, Register tmp2, bool is_narrow, bool is_acquire) {
 846   // Do the actual load. This load is the candidate for implicit null check, and MUST come first.
 847   if (is_narrow) {
 848     if (is_acquire) {
 849       assert(src.getMode() == Address::base_plus_offset && src.offset() == 0,
 850           "is_acquire path requires address to be base-only");
 851       __ ldarw(dst, src.base());
 852     } else {
 853       __ ldrw(dst, src);
 854     }
 855   } else {
 856     if (is_acquire) {
 857       assert(src.getMode() == Address::base_plus_offset && src.offset() == 0,
 858           "is_acquire path requires address to be base-only");
 859       __ ldar(dst, src.base());
 860     } else {
 861       __ ldr(dst, src);
 862     }
 863   }
 864 
 865   ShenandoahBarrierStubC2::load_post(masm, node, dst, src, tmp1, tmp2, is_narrow);
 866 }
 867 
 868 void ShenandoahBarrierSetAssembler::store_c2(const MachNode* node, MacroAssembler* masm, Address dst, bool dst_narrow,
 869     Register src, bool src_narrow, Register tmp1, Register tmp2, Register tmp3, bool is_volatile) {
 870 
 871   ShenandoahBarrierStubC2::store_pre(masm, node, tmp1, dst, tmp2, tmp3, dst_narrow);
 872 
 873   // Do the actual store
 874   if (dst_narrow) {
 875     if (!src_narrow) {
 876       // Need to encode into rscratch, because we cannot clobber src.
 877       if ((node->barrier_data() & ShenandoahBitNotNull) == 0) {
 878         __ encode_heap_oop(tmp2, src);
 879       } else {
 880         __ encode_heap_oop_not_null(tmp2, src);
 881       }
 882       src = tmp2;
 883     }
 884 
 885     if (is_volatile) {
 886       assert(dst.getMode() == Address::base_plus_offset && dst.offset() == 0,
 887           "is_acquire path requires address to be base-only");
 888       __ stlrw(src, dst.base());
 889     } else {
 890       __ strw(src, dst);
 891     }
 892   } else {
 893     if (is_volatile) {
 894       assert(dst.getMode() == Address::base_plus_offset && dst.offset() == 0,
 895           "is_acquire path requires address to be base-only");
 896       __ stlr(src, dst.base());
 897     } else {
 898       __ str(src, dst);
 899     }
 900   }
 901 
 902   ShenandoahBarrierStubC2::store_post(masm, node, dst, tmp2, tmp3);
 903 }
 904 
 905 void ShenandoahBarrierSetAssembler::compare_and_set_c2(const MachNode* node, MacroAssembler* masm, Register res, Register addr,
 906     Register oldval, Register newval, Register tmp1, Register tmp2, Register tmp3, bool exchange, bool narrow, bool weak, bool acquire) {
 907   Assembler::operand_size op_size = narrow ? Assembler::word : Assembler::xword;
 908 
 909   ShenandoahBarrierStubC2::load_store_pre(masm, node, tmp1, addr, tmp2, tmp3, narrow);
 910 
 911   // CAS!
 912   __ cmpxchg(addr, oldval, newval, op_size, acquire, /* release */ true, weak, exchange ? res : noreg);
 913 
 914   // If we need a boolean result out of CAS, set the flag appropriately and promote the result.
 915   if (!exchange) {
 916     assert(res != noreg, "need result register");
 917     __ cset(res, Assembler::EQ);
 918   }
 919 
 920   ShenandoahBarrierStubC2::load_store_post(masm, node, Address(addr, 0), tmp2, tmp3);
 921 }
 922 
 923 void ShenandoahBarrierSetAssembler::get_and_set_c2(const MachNode* node, MacroAssembler* masm, Register preval,
 924     Register newval, Register addr, Register tmp1, Register tmp2, Register tmp3, bool is_acquire) {
 925   bool is_narrow = node->bottom_type()->isa_narrowoop();
 926 
 927   ShenandoahBarrierStubC2::load_store_pre(masm, node, tmp1, addr, tmp2, tmp3, is_narrow);
 928 
 929   if (is_narrow) {
 930     if (is_acquire) {
 931       __ atomic_xchgalw(preval, newval, addr);
 932     } else {
 933       __ atomic_xchgw(preval, newval, addr);
 934     }
 935   } else {
 936     if (is_acquire) {
 937       __ atomic_xchgal(preval, newval, addr);
 938     } else {
 939       __ atomic_xchg(preval, newval, addr);
 940     }
 941   }
 942 
 943   ShenandoahBarrierStubC2::load_store_post(masm, node, Address(addr, 0), tmp2, tmp3);
 944 }
 945 
 946 #undef __
 947 #define __ masm.
 948 
 949 void ShenandoahBarrierStubC2::cardtable(MacroAssembler& masm, Address address, Register tmp1, Register tmp2) {
 950   assert(CardTable::dirty_card_val() == 0, "must be");
 951   Assembler::InlineSkippedInstructionsCounter skip_counter(&masm);
 952 
 953   // tmp1 = card table base (holder)
 954   Address curr_ct_holder_addr(rthread, in_bytes(ShenandoahThreadLocalData::card_table_offset()));
 955   __ ldr(tmp1, curr_ct_holder_addr);
 956 
 957   // tmp2 = effective address
 958   __ lea(tmp2, address);
 959 
 960   // tmp2 = &card_table[ addr >> CardTable::card_shift() ] ; card index
 961   __ add(tmp2, tmp1, tmp2, Assembler::LSR, CardTable::card_shift());
 962 
 963   if (UseCondCardMark) {
 964     Label L_already_dirty;
 965     __ ldrb(tmp1, Address(tmp2));
 966     __ cbz(tmp1, L_already_dirty);
 967     __ strb(zr, Address(tmp2));
 968     __ bind(L_already_dirty);
 969   } else {
 970     __ strb(zr, Address(tmp2));
 971   }
 972 }
 973 
 974 void ShenandoahBarrierStubC2::enter_if_gc_state(MacroAssembler& masm, const char test_state, Register tmp) {
 975   Assembler::InlineSkippedInstructionsCounter skip_counter(&masm);
 976   PhaseOutput* const output = Compile::current()->output();
 977   Address gc_state_fast(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_fast_array_offset(test_state)));
 978 
 979   // We piggyback on scratch_emit_size mode to compute the slowpath stub size.
 980   // We'll use that information to decide whether we need a far jump to the
 981   // stub entry point or not. In scratch_emit_size mode we don't bind entry()
 982   // because otherwise it will be rebound when we later emit the instructions
 983   // for real.
 984   if (_needs_far_jump) {
 985     __ ldrb(tmp, gc_state_fast);
 986     __ cbz(tmp, *continuation());
 987     __ b(output->in_scratch_emit_size() ? *continuation() : *entry());
 988   } else {
 989     __ ldrb(tmp, gc_state_fast);
 990     __ cbnz(tmp, output->in_scratch_emit_size() ? *continuation() : *entry());
 991   }
 992 
 993   // This is were the slowpath stub will return to or the code above will
 994   // jump to if the checks are false
 995   __ bind(*continuation());
 996 }
 997 
 998 void ShenandoahBarrierStubC2::emit_code(MacroAssembler& masm) {
 999   Assembler::InlineSkippedInstructionsCounter skip_counter(&masm);
1000   assert(_needs_keep_alive_barrier || _needs_load_ref_barrier, "Why are you here?");
1001   PhaseOutput* const output = Compile::current()->output();
1002 
1003   // We piggyback on scratch_emit_size mode to compute the slowpath stub size.
1004   // We'll use that information to decide whether we need a far jump to the
1005   // stub entry point or not. In scratch_emit_size mode we don't bind entry()
1006   // because otherwise it will be rebound when we later emit the instructions
1007   // for real.
1008   if (!output->in_scratch_emit_size()) {
1009     __ bind(*entry());
1010   }
1011 
1012   // If we need to load ourselves, do it here.
1013   if (_do_load) {
1014     if (_narrow) {
1015       __ ldrw(_obj, _addr);
1016     } else {
1017       __ ldr(_obj, _addr);
1018     }
1019   }
1020 
1021   // If the object is null, there is no point in applying barriers.
1022   maybe_far_jump_if_zero(masm, _obj);
1023 
1024   // We need to make sure that loads done by callers survive across slow-path calls.
1025   // For self-loads, we need to care about the case when both KA and LRB are enabled (rare).
1026   bool needs_both_barriers = _needs_keep_alive_barrier && _needs_load_ref_barrier;
1027   if (!_do_load || needs_both_barriers) {
1028     preserve(_obj);
1029   }
1030 
1031   // Go for barriers. Barriers can return straight to continuation, as long
1032   // as another barrier is not needed and we can reach the fastpath.
1033   if (needs_both_barriers) {
1034     // The Load match rule in the .ad file may have legitimized the load
1035     // address using a TEMP register and in that case we need to explicitly
1036     // preserve them here, because the RA does not consider TEMP as live-in,
1037     // and the KA runtime call may clobber them and cause a crash on the
1038     // subsequent LRB stub.
1039     if (_addr.base() != noreg) {
1040       preserve(_addr.base());
1041     }
1042     if (_addr.index() != noreg) {
1043       preserve(_addr.index());
1044     }
1045     keepalive(masm, nullptr);
1046     lrb(masm);
1047   } else if (_needs_keep_alive_barrier) {
1048     keepalive(masm, continuation());
1049   } else if (_needs_load_ref_barrier) {
1050     lrb(masm);
1051   } else {
1052     ShouldNotReachHere();
1053   }
1054 }
1055 
1056 void ShenandoahBarrierStubC2::maybe_far_jump_if_zero(MacroAssembler& masm, Register reg) {
1057   if (_needs_far_jump) {
1058     Label L_short_jump;
1059     __ cbnz(reg, L_short_jump);
1060     __ b(*continuation());
1061     __ bind(L_short_jump);
1062   } else {
1063     __ cbz(reg, *continuation());
1064   }
1065 }
1066 
1067 void ShenandoahBarrierStubC2::keepalive(MacroAssembler& masm, Label* L_done) {
1068   Address gcstate(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_fast_array_offset(ShenandoahHeap::MARKING)));
1069   Address index(rthread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset()));
1070   Address buffer(rthread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset()));
1071   Label L_through, L_slowpath;
1072 
1073   // If another barrier is enabled as well, do a runtime check for a specific barrier.
1074   if (_needs_load_ref_barrier) {
1075     assert(L_done == nullptr, "L_done is always null when _needs_load_ref_barrier is true");
1076     __ ldrb(_tmp1, gcstate);
1077     __ cbz(_tmp1, L_through);
1078   }
1079 
1080   // Fast-path: put object into buffer.
1081   // If buffer is already full, go slow.
1082   __ ldr(_tmp1, index);
1083   __ cbz(_tmp1, L_slowpath);
1084   __ sub(_tmp1, _tmp1, wordSize);
1085   __ str(_tmp1, index);
1086   __ ldr(_tmp2, buffer);
1087 
1088   // Store the object in queue.
1089   // If object is narrow, we need to decode it before inserting.
1090   if (_narrow) {
1091     __ add(_tmp2, _tmp2, _tmp1);
1092     __ decode_heap_oop_not_null(_tmp1, _obj);
1093     __ str(_tmp1, Address(_tmp2));
1094   } else {
1095     // Buffer is 64-bit address, must be in base register.
1096     __ str(_obj, Address(_tmp2, _tmp1));
1097   }
1098 
1099   // Fast-path exits here.
1100   if (L_done != nullptr) {
1101     __ b(*L_done);
1102   } else {
1103     __ b(L_through);
1104   }
1105 
1106   // Slow-path: call runtime to handle.
1107   __ bind(L_slowpath);
1108 
1109   {
1110     SaveLiveRegisters slr(&masm, this);
1111 
1112     // Go to runtime and handle the rest there.
1113     __ mov(c_rarg0, _obj);
1114     __ mov(lr, keepalive_runtime_entry_addr());
1115     __ blr(lr);
1116   }
1117   if (L_done != nullptr) {
1118     __ b(*L_done);
1119   } else {
1120     __ bind(L_through);
1121   }
1122 }
1123 
1124 void ShenandoahBarrierStubC2::lrb(MacroAssembler& masm) {
1125   Label L_slow;
1126 
1127   // If another barrier is enabled as well, do a runtime check for a specific barrier.
1128   if (_needs_keep_alive_barrier) {
1129     char state_to_check = ShenandoahHeap::HAS_FORWARDED | (_needs_load_ref_weak_barrier ? ShenandoahHeap::WEAK_ROOTS : 0);
1130     Address gc_state_fast(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_fast_array_offset(state_to_check)));
1131     __ ldrb(_tmp1, gc_state_fast);
1132     maybe_far_jump_if_zero(masm, _tmp1);
1133   }
1134 
1135   // If weak references are being processed, weak/phantom loads need to go slow,
1136   // regardless of their cset status.
1137   if (_needs_load_ref_weak_barrier) {
1138     Address gc_state_fast(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_fast_array_offset(ShenandoahHeap::WEAK_ROOTS)));
1139     __ ldrb(_tmp1, gc_state_fast);
1140     __ cbnz(_tmp1, L_slow);
1141   }
1142 
1143   // Cset-check. Fall-through to slow if in collection set.
1144   bool is_aot = AOTCodeCache::is_on_for_dump();
1145   if (!is_aot) {
1146     __ mov(_tmp1, ShenandoahHeap::in_cset_fast_test_addr());
1147     if (_narrow) {
1148       __ decode_heap_oop_not_null(_tmp2, _obj);
1149       __ add(_tmp1, _tmp1, _tmp2, Assembler::LSR, ShenandoahHeapRegion::region_size_bytes_shift_jint());
1150     } else {
1151       __ add(_tmp1, _tmp1, _obj, Assembler::LSR, ShenandoahHeapRegion::region_size_bytes_shift_jint());
1152     }
1153   } else {
1154     // Generating AOT code, pull the cset bitmap and region shift from AOT table.
1155     if (_narrow) {
1156       __ decode_heap_oop_not_null(_tmp1, _obj);
1157     } else {
1158       __ mov(_tmp1, _obj);
1159     }
1160     __ lea(_tmp2, ExternalAddress(AOTRuntimeConstants::grain_shift_address()));
1161     __ ldrw(_tmp2, Address(_tmp2));
1162     __ lsrv(_tmp2, _tmp1, _tmp2);
1163     __ lea(_tmp1, ExternalAddress(AOTRuntimeConstants::cset_base_address()));
1164     __ ldr(_tmp1, Address(_tmp1));
1165     __ add(_tmp1, _tmp1, _tmp2);
1166   }
1167   __ ldrb(_tmp1, Address(_tmp1, 0));
1168   maybe_far_jump_if_zero(masm, _tmp1);
1169 
1170   // Slow path
1171   __ bind(L_slow);
1172 
1173   // Obj is the result, need to temporarily stop preserving it.
1174   bool is_obj_preserved = is_preserved(_obj);
1175   if (is_obj_preserved) {
1176     dont_preserve(_obj);
1177   }
1178   {
1179     SaveLiveRegisters slr(&masm, this);
1180 
1181     // Shuffle in the arguments. The end result should be:
1182     //   c_rarg0 <-- obj
1183     //   c_rarg1 <-- lea(addr)
1184     if (c_rarg0 == _obj) {
1185       __ lea(c_rarg1, _addr);
1186     } else if (c_rarg1 == _obj) {
1187       // Set up arguments in reverse, and then flip them
1188       __ lea(c_rarg0, _addr);
1189       // flip them
1190       __ mov(_tmp1, c_rarg0);
1191       __ mov(c_rarg0, c_rarg1);
1192       __ mov(c_rarg1, _tmp1);
1193     } else {
1194       assert_different_registers(c_rarg1, _obj);
1195       __ lea(c_rarg1, _addr);
1196       __ mov(c_rarg0, _obj);
1197     }
1198 
1199     // Go to runtime and handle the rest there.
1200     __ mov(lr, lrb_runtime_entry_addr());
1201     __ blr(lr);
1202 
1203     // Save the result where needed. Narrow entries return narrowOop (32 bits)
1204     // and AAPCS does not guarantee the upper 32 bits of x0 are zero.
1205     if (_narrow) {
1206       __ movw(_obj, r0);
1207     } else if (_obj != r0) {
1208       __ mov(_obj, r0);
1209     }
1210   }
1211   if (is_obj_preserved) {
1212     preserve(_obj);
1213   }
1214 
1215   __ b(*continuation());
1216 }
1217 
1218 int ShenandoahBarrierStubC2::available_gp_registers() {
1219   Unimplemented(); // Not used
1220   return 0;
1221 }
1222 
1223 bool ShenandoahBarrierStubC2::is_special_register(Register r) {
1224   Unimplemented(); // Not used
1225   return true;
1226 }
1227 
1228 static ShenandoahBarrierSetC2State* barrier_set_state() {
1229   return reinterpret_cast<ShenandoahBarrierSetC2State*>(Compile::current()->barrier_set_state());
1230 }
1231 
1232 static int get_stub_size(ShenandoahBarrierStubC2* stub) {
1233   PhaseOutput* const output = Compile::current()->output();
1234   assert(output->in_scratch_emit_size(), "only used when in scratch_emit_size.");
1235   BufferBlob* const blob = output->scratch_buffer_blob();
1236   CodeBuffer cb(blob->content_begin(), (address)output->scratch_locs_memory() - blob->content_begin());
1237   MacroAssembler masm(&cb);
1238   stub->emit_code(masm);
1239   return cb.insts_size();
1240 }
1241 
1242 void ShenandoahBarrierStubC2::post_init() {
1243   // If we are in scratch emit mode we assume worst case, and force the use of
1244   // far branches.
1245   PhaseOutput* const output = Compile::current()->output();
1246   ShenandoahBarrierSetC2State* state = barrier_set_state();
1247   if (output->in_scratch_emit_size()) {
1248     state->inc_stubs_current_total_size(get_stub_size(this));
1249     _needs_far_jump = true;
1250     return;
1251   }
1252 
1253   // The logic implemented in this stub only uses short jumps (cbz, cbnz) if
1254   // the aggregation of all relevant code sections of a method is less than 1MB
1255   // - 2KB. We could be more aggressive and try and compute the distance
1256   // between the fastpath branch and the stub entry but in practice not many
1257   // methods reach the 1MB size.
1258   const BufferSizingData* sizing = output->buffer_sizing_data();
1259   const int code_size = sizing->_code + state->stubs_current_total_size();
1260 
1261   // Maximum backward range is 1M. Maximum forward reach is 1M - 4bytes.
1262   // Subtract 2K to be ultra conservative.
1263   const int cond_branch_max_reach = (int)(1*M - 2*K);
1264   _needs_far_jump = code_size >= cond_branch_max_reach;
1265 }
1266 
1267 #endif // COMPILER2
< prev index next >