155 mov(c_rarg1, arg1); 156 mov(c_rarg2, arg2); 157 mov(c_rarg3, arg3); 158 } 159 return call_RT(oop_result1, metadata_result, entry, 3); 160 } 161 162 // Implementation of StubFrame 163 164 class StubFrame: public StackObj { 165 private: 166 StubAssembler* _sasm; 167 168 public: 169 StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments); 170 void load_argument(int offset_in_words, Register reg); 171 172 ~StubFrame(); 173 };; 174 175 176 #define __ _sasm-> 177 178 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) { 179 _sasm = sasm; 180 __ set_info(name, must_gc_arguments); 181 __ enter(); 182 } 183 184 // load parameters that were stored with LIR_Assembler::store_parameter 185 // Note: offsets for store_parameter and load_argument must match 186 void StubFrame::load_argument(int offset_in_words, Register reg) { 187 // rbp, + 0: link 188 // + 1: return address 189 // + 2: argument with offset 0 190 // + 3: argument with offset 1 191 // + 4: ... 192 193 __ ldr(reg, Address(rfp, (offset_in_words + 2) * BytesPerWord)); 194 } 195 196 197 StubFrame::~StubFrame() { 198 __ leave(); 199 __ ret(lr); 200 } 201 202 #undef __ 203 204 205 // Implementation of Runtime1 206 207 #define __ sasm-> 208 209 const int float_regs_as_doubles_size_in_slots = pd_nof_fpu_regs_frame_map * 2; 210 211 // Stack layout for saving/restoring all the registers needed during a runtime 212 // call (this includes deoptimization) 213 // Note: note that users of this frame may well have arguments to some runtime 214 // while these values are on the stack. These positions neglect those arguments 215 // but the code in save_live_registers will take the argument count into 216 // account. 217 // 218 219 enum reg_save_layout { 1134 1135 case handle_exception_from_callee_id: 1136 { StubFrame f(sasm, "handle_exception_from_callee", dont_gc_arguments); 1137 oop_maps = generate_handle_exception(id, sasm); 1138 } 1139 break; 1140 1141 case throw_index_exception_id: 1142 { StubFrame f(sasm, "index_range_check_failed", dont_gc_arguments); 1143 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); 1144 } 1145 break; 1146 1147 case throw_array_store_exception_id: 1148 { StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments); 1149 // tos + 0: link 1150 // + 1: return address 1151 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true); 1152 } 1153 break; 1154 1155 #if INCLUDE_ALL_GCS 1156 1157 case g1_pre_barrier_slow_id: 1158 { 1159 StubFrame f(sasm, "g1_pre_barrier", dont_gc_arguments); 1160 // arg0 : previous value of memory 1161 1162 BarrierSet* bs = Universe::heap()->barrier_set(); 1163 if (bs->kind() != BarrierSet::G1BarrierSet) { 1164 __ mov(r0, (int)id); 1165 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), r0); 1166 __ should_not_reach_here(); 1167 break; 1168 } 1169 1170 const Register pre_val = r0; 1171 const Register thread = rthread; 1172 const Register tmp = rscratch1; 1173 1174 Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() + 1175 SATBMarkQueue::byte_offset_of_active())); 1176 1177 Address queue_index(thread, in_bytes(JavaThread::satb_mark_queue_offset() + 1178 SATBMarkQueue::byte_offset_of_index())); 1179 Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() + 1180 SATBMarkQueue::byte_offset_of_buf())); 1181 1182 Label done; 1183 Label runtime; 1184 1185 // Is marking still active? 1186 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { 1187 __ ldrw(tmp, in_progress); 1188 } else { 1189 assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); 1190 __ ldrb(tmp, in_progress); 1191 } 1192 __ cbzw(tmp, done); 1193 1194 // Can we store original value in the thread's buffer? 1195 __ ldr(tmp, queue_index); 1196 __ cbz(tmp, runtime); 1197 1198 __ sub(tmp, tmp, wordSize); 1199 __ str(tmp, queue_index); 1200 __ ldr(rscratch2, buffer); 1201 __ add(tmp, tmp, rscratch2); 1202 f.load_argument(0, rscratch2); 1203 __ str(rscratch2, Address(tmp, 0)); 1204 __ b(done); 1205 1206 __ bind(runtime); 1207 __ push_call_clobbered_registers(); 1208 f.load_argument(0, pre_val); 1209 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread); 1210 __ pop_call_clobbered_registers(); 1211 __ bind(done); 1212 } 1213 break; 1214 case g1_post_barrier_slow_id: 1215 { 1216 StubFrame f(sasm, "g1_post_barrier", dont_gc_arguments); 1217 1218 // arg0: store_address 1219 Address store_addr(rfp, 2*BytesPerWord); 1220 1221 BarrierSet* bs = Universe::heap()->barrier_set(); 1222 CardTableModRefBS* ctbs = barrier_set_cast<CardTableModRefBS>(bs); 1223 CardTable* ct = ctbs->card_table(); 1224 assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code"); 1225 1226 Label done; 1227 Label runtime; 1228 1229 // At this point we know new_value is non-NULL and the new_value crosses regions. 1230 // Must check to see if card is already dirty 1231 1232 const Register thread = rthread; 1233 1234 Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() + 1235 DirtyCardQueue::byte_offset_of_index())); 1236 Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() + 1237 DirtyCardQueue::byte_offset_of_buf())); 1238 1239 const Register card_offset = rscratch2; 1240 // LR is free here, so we can use it to hold the byte_map_base. 1241 const Register byte_map_base = lr; 1242 1243 assert_different_registers(card_offset, byte_map_base, rscratch1); 1244 1245 f.load_argument(0, card_offset); 1246 __ lsr(card_offset, card_offset, CardTable::card_shift); 1247 __ load_byte_map_base(byte_map_base); 1248 __ ldrb(rscratch1, Address(byte_map_base, card_offset)); 1249 __ cmpw(rscratch1, (int)G1CardTable::g1_young_card_val()); 1250 __ br(Assembler::EQ, done); 1251 1252 assert((int)CardTable::dirty_card_val() == 0, "must be 0"); 1253 1254 __ membar(Assembler::StoreLoad); 1255 __ ldrb(rscratch1, Address(byte_map_base, card_offset)); 1256 __ cbzw(rscratch1, done); 1257 1258 // storing region crossing non-NULL, card is clean. 1259 // dirty card and log. 1260 __ strb(zr, Address(byte_map_base, card_offset)); 1261 1262 // Convert card offset into an address in card_addr 1263 Register card_addr = card_offset; 1264 __ add(card_addr, byte_map_base, card_addr); 1265 1266 __ ldr(rscratch1, queue_index); 1267 __ cbz(rscratch1, runtime); 1268 __ sub(rscratch1, rscratch1, wordSize); 1269 __ str(rscratch1, queue_index); 1270 1271 // Reuse LR to hold buffer_addr 1272 const Register buffer_addr = lr; 1273 1274 __ ldr(buffer_addr, buffer); 1275 __ str(card_addr, Address(buffer_addr, rscratch1)); 1276 __ b(done); 1277 1278 __ bind(runtime); 1279 __ push_call_clobbered_registers(); 1280 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread); 1281 __ pop_call_clobbered_registers(); 1282 __ bind(done); 1283 1284 } 1285 break; 1286 #endif 1287 1288 case predicate_failed_trap_id: 1289 { 1290 StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments); 1291 1292 OopMap* map = save_live_registers(sasm); 1293 1294 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, predicate_failed_trap)); 1295 oop_maps = new OopMapSet(); 1296 oop_maps->add_gc_map(call_offset, map); 1297 restore_live_registers(sasm); 1298 __ leave(); 1299 DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob(); 1300 assert(deopt_blob != NULL, "deoptimization blob must have been created"); 1301 1302 __ far_jump(RuntimeAddress(deopt_blob->unpack_with_reexecution())); 1303 } 1304 break; 1305 1306 | 155 mov(c_rarg1, arg1); 156 mov(c_rarg2, arg2); 157 mov(c_rarg3, arg3); 158 } 159 return call_RT(oop_result1, metadata_result, entry, 3); 160 } 161 162 // Implementation of StubFrame 163 164 class StubFrame: public StackObj { 165 private: 166 StubAssembler* _sasm; 167 168 public: 169 StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments); 170 void load_argument(int offset_in_words, Register reg); 171 172 ~StubFrame(); 173 };; 174 175 void StubAssembler::prologue(const char* name, bool must_gc_arguments) { 176 set_info(name, must_gc_arguments); 177 enter(); 178 } 179 180 void StubAssembler::epilogue() { 181 leave(); 182 ret(lr); 183 } 184 185 #define __ _sasm-> 186 187 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) { 188 _sasm = sasm; 189 __ prologue(name, must_gc_arguments); 190 } 191 192 // load parameters that were stored with LIR_Assembler::store_parameter 193 // Note: offsets for store_parameter and load_argument must match 194 void StubFrame::load_argument(int offset_in_words, Register reg) { 195 __ load_parameter(offset_in_words, reg); 196 } 197 198 199 StubFrame::~StubFrame() { 200 __ epilogue(); 201 } 202 203 #undef __ 204 205 206 // Implementation of Runtime1 207 208 #define __ sasm-> 209 210 const int float_regs_as_doubles_size_in_slots = pd_nof_fpu_regs_frame_map * 2; 211 212 // Stack layout for saving/restoring all the registers needed during a runtime 213 // call (this includes deoptimization) 214 // Note: note that users of this frame may well have arguments to some runtime 215 // while these values are on the stack. These positions neglect those arguments 216 // but the code in save_live_registers will take the argument count into 217 // account. 218 // 219 220 enum reg_save_layout { 1135 1136 case handle_exception_from_callee_id: 1137 { StubFrame f(sasm, "handle_exception_from_callee", dont_gc_arguments); 1138 oop_maps = generate_handle_exception(id, sasm); 1139 } 1140 break; 1141 1142 case throw_index_exception_id: 1143 { StubFrame f(sasm, "index_range_check_failed", dont_gc_arguments); 1144 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); 1145 } 1146 break; 1147 1148 case throw_array_store_exception_id: 1149 { StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments); 1150 // tos + 0: link 1151 // + 1: return address 1152 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true); 1153 } 1154 break; 1155 1156 case predicate_failed_trap_id: 1157 { 1158 StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments); 1159 1160 OopMap* map = save_live_registers(sasm); 1161 1162 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, predicate_failed_trap)); 1163 oop_maps = new OopMapSet(); 1164 oop_maps->add_gc_map(call_offset, map); 1165 restore_live_registers(sasm); 1166 __ leave(); 1167 DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob(); 1168 assert(deopt_blob != NULL, "deoptimization blob must have been created"); 1169 1170 __ far_jump(RuntimeAddress(deopt_blob->unpack_with_reexecution())); 1171 } 1172 break; 1173 1174 |