153 ldp(c_rarg3, c_rarg2, Address(post(sp, 2 * wordSize)));
154 } else {
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 enum return_state_t {
163 does_not_return, requires_return
164 };
165
166
167 // Implementation of StubFrame
168
169 class StubFrame: public StackObj {
170 private:
171 StubAssembler* _sasm;
172 bool _return_state;
173
174 public:
175 StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments, return_state_t return_state=requires_return);
176 void load_argument(int offset_in_words, Register reg);
177
178 ~StubFrame();
179 };;
180
181 void StubAssembler::prologue(const char* name, bool must_gc_arguments) {
182 set_info(name, must_gc_arguments);
183 enter();
184 }
185
186 void StubAssembler::epilogue() {
187 leave();
188 ret(lr);
189 }
190
191 #define __ _sasm->
192
193 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments, return_state_t return_state) {
194 _sasm = sasm;
195 _return_state = return_state;
196 __ prologue(name, must_gc_arguments);
197 }
198
199 // load parameters that were stored with LIR_Assembler::store_parameter
200 // Note: offsets for store_parameter and load_argument must match
201 void StubFrame::load_argument(int offset_in_words, Register reg) {
202 __ load_parameter(offset_in_words, reg);
203 }
204
205 StubFrame::~StubFrame() {
206 if (_return_state == requires_return) {
207 __ epilogue();
208 } else {
209 __ should_not_reach_here();
210 }
211 }
212
213 #undef __
214
215
216 // Implementation of Runtime1
217
218 #define __ sasm->
219
220 const int float_regs_as_doubles_size_in_slots = pd_nof_fpu_regs_frame_map * 2;
221
222 // Stack layout for saving/restoring all the registers needed during a runtime
223 // call (this includes deoptimization)
224 // Note: note that users of this frame may well have arguments to some runtime
225 // while these values are on the stack. These positions neglect those arguments
226 // but the code in save_live_registers will take the argument count into
227 // account.
228 //
229
230 enum reg_save_layout {
235 // Tries to smart of about FP registers. In particular we separate
236 // saving and describing the FPU registers for deoptimization since we
237 // have to save the FPU registers twice if we describe them. The
238 // deopt blob is the only thing which needs to describe FPU registers.
239 // In all other cases it should be sufficient to simply save their
240 // current value.
241
242 static int cpu_reg_save_offsets[FrameMap::nof_cpu_regs];
243 static int fpu_reg_save_offsets[FrameMap::nof_fpu_regs];
244 static int reg_save_size_in_words;
245 static int frame_size_in_bytes = -1;
246
247 static OopMap* generate_oop_map(StubAssembler* sasm, bool save_fpu_registers) {
248 int frame_size_in_bytes = reg_save_frame_size * BytesPerWord;
249 sasm->set_frame_size(frame_size_in_bytes / BytesPerWord);
250 int frame_size_in_slots = frame_size_in_bytes / sizeof(jint);
251 OopMap* oop_map = new OopMap(frame_size_in_slots, 0);
252
253 for (int i = 0; i < FrameMap::nof_cpu_regs; i++) {
254 Register r = as_Register(i);
255 if (i <= 18 && i != rscratch1->encoding() && i != rscratch2->encoding()) {
256 int sp_offset = cpu_reg_save_offsets[i];
257 oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset),
258 r->as_VMReg());
259 }
260 }
261
262 if (save_fpu_registers) {
263 for (int i = 0; i < FrameMap::nof_fpu_regs; i++) {
264 FloatRegister r = as_FloatRegister(i);
265 {
266 int sp_offset = fpu_reg_save_offsets[i];
267 oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset),
268 r->as_VMReg());
269 }
270 }
271 }
272 return oop_map;
273 }
274
275 static OopMap* save_live_registers(StubAssembler* sasm,
320
321
322 void Runtime1::initialize_pd() {
323 int i;
324 int sp_offset = 0;
325
326 // all float registers are saved explicitly
327 assert(FrameMap::nof_fpu_regs == 32, "double registers not handled here");
328 for (i = 0; i < FrameMap::nof_fpu_regs; i++) {
329 fpu_reg_save_offsets[i] = sp_offset;
330 sp_offset += 2; // SP offsets are in halfwords
331 }
332
333 for (i = 0; i < FrameMap::nof_cpu_regs; i++) {
334 Register r = as_Register(i);
335 cpu_reg_save_offsets[i] = sp_offset;
336 sp_offset += 2; // SP offsets are in halfwords
337 }
338 }
339
340
341 // target: the entry point of the method that creates and posts the exception oop
342 // has_argument: true if the exception needs arguments (passed in rscratch1 and rscratch2)
343
344 OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) {
345 // make a frame and preserve the caller's caller-save registers
346 OopMap* oop_map = save_live_registers(sasm);
347 int call_offset;
348 if (!has_argument) {
349 call_offset = __ call_RT(noreg, noreg, target);
350 } else {
351 __ mov(c_rarg1, rscratch1);
352 __ mov(c_rarg2, rscratch2);
353 call_offset = __ call_RT(noreg, noreg, target);
354 }
355 OopMapSet* oop_maps = new OopMapSet();
356 oop_maps->add_gc_map(call_offset, oop_map);
357 return oop_maps;
358 }
359
845 __ check_klass_subtype_slow_path(r4, r0, r2, r5, nullptr, &miss);
846
847 // fallthrough on success:
848 __ mov(rscratch1, 1);
849 __ str(rscratch1, Address(sp, (result_off) * VMRegImpl::stack_slot_size)); // result
850 __ pop(RegSet::of(r0, r2, r4, r5), sp);
851 __ ret(lr);
852
853 __ bind(miss);
854 __ str(zr, Address(sp, (result_off) * VMRegImpl::stack_slot_size)); // result
855 __ pop(RegSet::of(r0, r2, r4, r5), sp);
856 __ ret(lr);
857 }
858 break;
859
860 case monitorenter_nofpu_id:
861 save_fpu_registers = false;
862 // fall through
863 case monitorenter_id:
864 {
865 StubFrame f(sasm, "monitorenter", dont_gc_arguments);
866 OopMap* map = save_live_registers(sasm, save_fpu_registers);
867
868 // Called with store_parameter and not C abi
869
870 f.load_argument(1, r0); // r0,: object
871 f.load_argument(0, r1); // r1,: lock address
872
873 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), r0, r1);
874
875 oop_maps = new OopMapSet();
876 oop_maps->add_gc_map(call_offset, map);
877 restore_live_registers(sasm, save_fpu_registers);
878 }
879 break;
880
881 case monitorexit_nofpu_id:
882 save_fpu_registers = false;
883 // fall through
884 case monitorexit_id:
885 {
|
153 ldp(c_rarg3, c_rarg2, Address(post(sp, 2 * wordSize)));
154 } else {
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 enum return_state_t {
163 does_not_return, requires_return
164 };
165
166
167 // Implementation of StubFrame
168
169 class StubFrame: public StackObj {
170 private:
171 StubAssembler* _sasm;
172 bool _return_state;
173 bool _use_pop_on_epilogue;
174
175 StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments,
176 return_state_t return_state, bool use_pop_on_epilogue);
177
178 public:
179 StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments, bool use_pop_on_epilogue);
180 StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments, return_state_t return_state);
181 StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments);
182 ~StubFrame();
183
184 void load_argument(int offset_in_words, Register reg);
185 };;
186
187 void StubAssembler::prologue(const char* name, bool must_gc_arguments) {
188 set_info(name, must_gc_arguments);
189 enter();
190 }
191
192 void StubAssembler::epilogue(bool use_pop) {
193 // use_pop when this frame may have been frozen on one carrier
194 // thread then thawed on another carrier thread, rendering the fp
195 // register invalid. We must restore the previous FP because it is
196 // used as a call-saved scratch register by compiled code.
197 if (use_pop) {
198 ldp(rfp, lr, Address(post(sp, 2 * wordSize)));
199 } else {
200 leave();
201 }
202 ret(lr);
203 }
204
205 #define __ _sasm->
206
207 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments,
208 return_state_t return_state, bool use_pop_on_epilogue)
209 : _sasm(sasm), _return_state(return_state), _use_pop_on_epilogue(use_pop_on_epilogue) {
210 __ prologue(name, must_gc_arguments);
211 }
212
213 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments,
214 bool use_pop_on_epilogue) :
215 StubFrame(sasm, name, must_gc_arguments, requires_return, use_pop_on_epilogue) {}
216
217 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments,
218 return_state_t return_state) :
219 StubFrame(sasm, name, must_gc_arguments, return_state, /*use_pop_on_epilogue*/false) {}
220
221 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) :
222 StubFrame(sasm, name, must_gc_arguments, requires_return, /*use_pop_on_epilogue*/false) {}
223
224 // load parameters that were stored with LIR_Assembler::store_parameter
225 // Note: offsets for store_parameter and load_argument must match
226 void StubFrame::load_argument(int offset_in_words, Register reg) {
227 __ load_parameter(offset_in_words, reg);
228 }
229
230 StubFrame::~StubFrame() {
231 __ epilogue(_use_pop_on_epilogue);
232 }
233
234 #undef __
235
236
237 // Implementation of Runtime1
238
239 #define __ sasm->
240
241 const int float_regs_as_doubles_size_in_slots = pd_nof_fpu_regs_frame_map * 2;
242
243 // Stack layout for saving/restoring all the registers needed during a runtime
244 // call (this includes deoptimization)
245 // Note: note that users of this frame may well have arguments to some runtime
246 // while these values are on the stack. These positions neglect those arguments
247 // but the code in save_live_registers will take the argument count into
248 // account.
249 //
250
251 enum reg_save_layout {
256 // Tries to smart of about FP registers. In particular we separate
257 // saving and describing the FPU registers for deoptimization since we
258 // have to save the FPU registers twice if we describe them. The
259 // deopt blob is the only thing which needs to describe FPU registers.
260 // In all other cases it should be sufficient to simply save their
261 // current value.
262
263 static int cpu_reg_save_offsets[FrameMap::nof_cpu_regs];
264 static int fpu_reg_save_offsets[FrameMap::nof_fpu_regs];
265 static int reg_save_size_in_words;
266 static int frame_size_in_bytes = -1;
267
268 static OopMap* generate_oop_map(StubAssembler* sasm, bool save_fpu_registers) {
269 int frame_size_in_bytes = reg_save_frame_size * BytesPerWord;
270 sasm->set_frame_size(frame_size_in_bytes / BytesPerWord);
271 int frame_size_in_slots = frame_size_in_bytes / sizeof(jint);
272 OopMap* oop_map = new OopMap(frame_size_in_slots, 0);
273
274 for (int i = 0; i < FrameMap::nof_cpu_regs; i++) {
275 Register r = as_Register(i);
276 if (r == rthread || (i <= 18 && i != rscratch1->encoding() && i != rscratch2->encoding())) {
277 int sp_offset = cpu_reg_save_offsets[i];
278 oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset),
279 r->as_VMReg());
280 }
281 }
282
283 if (save_fpu_registers) {
284 for (int i = 0; i < FrameMap::nof_fpu_regs; i++) {
285 FloatRegister r = as_FloatRegister(i);
286 {
287 int sp_offset = fpu_reg_save_offsets[i];
288 oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset),
289 r->as_VMReg());
290 }
291 }
292 }
293 return oop_map;
294 }
295
296 static OopMap* save_live_registers(StubAssembler* sasm,
341
342
343 void Runtime1::initialize_pd() {
344 int i;
345 int sp_offset = 0;
346
347 // all float registers are saved explicitly
348 assert(FrameMap::nof_fpu_regs == 32, "double registers not handled here");
349 for (i = 0; i < FrameMap::nof_fpu_regs; i++) {
350 fpu_reg_save_offsets[i] = sp_offset;
351 sp_offset += 2; // SP offsets are in halfwords
352 }
353
354 for (i = 0; i < FrameMap::nof_cpu_regs; i++) {
355 Register r = as_Register(i);
356 cpu_reg_save_offsets[i] = sp_offset;
357 sp_offset += 2; // SP offsets are in halfwords
358 }
359 }
360
361 // return: offset in 64-bit words.
362 uint Runtime1::runtime_blob_current_thread_offset(frame f) {
363 CodeBlob* cb = f.cb();
364 assert(cb == Runtime1::blob_for(Runtime1::monitorenter_id) ||
365 cb == Runtime1::blob_for(Runtime1::monitorenter_nofpu_id), "must be");
366 assert(cb != nullptr && cb->is_runtime_stub(), "invalid frame");
367 int offset = cpu_reg_save_offsets[rthread->encoding()];
368 return offset / 2; // SP offsets are in halfwords
369 }
370
371 // target: the entry point of the method that creates and posts the exception oop
372 // has_argument: true if the exception needs arguments (passed in rscratch1 and rscratch2)
373
374 OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) {
375 // make a frame and preserve the caller's caller-save registers
376 OopMap* oop_map = save_live_registers(sasm);
377 int call_offset;
378 if (!has_argument) {
379 call_offset = __ call_RT(noreg, noreg, target);
380 } else {
381 __ mov(c_rarg1, rscratch1);
382 __ mov(c_rarg2, rscratch2);
383 call_offset = __ call_RT(noreg, noreg, target);
384 }
385 OopMapSet* oop_maps = new OopMapSet();
386 oop_maps->add_gc_map(call_offset, oop_map);
387 return oop_maps;
388 }
389
875 __ check_klass_subtype_slow_path(r4, r0, r2, r5, nullptr, &miss);
876
877 // fallthrough on success:
878 __ mov(rscratch1, 1);
879 __ str(rscratch1, Address(sp, (result_off) * VMRegImpl::stack_slot_size)); // result
880 __ pop(RegSet::of(r0, r2, r4, r5), sp);
881 __ ret(lr);
882
883 __ bind(miss);
884 __ str(zr, Address(sp, (result_off) * VMRegImpl::stack_slot_size)); // result
885 __ pop(RegSet::of(r0, r2, r4, r5), sp);
886 __ ret(lr);
887 }
888 break;
889
890 case monitorenter_nofpu_id:
891 save_fpu_registers = false;
892 // fall through
893 case monitorenter_id:
894 {
895 StubFrame f(sasm, "monitorenter", dont_gc_arguments, /*use_pop_on_epilogue*/true);
896 OopMap* map = save_live_registers(sasm, save_fpu_registers);
897
898 // Called with store_parameter and not C abi
899
900 f.load_argument(1, r0); // r0,: object
901 f.load_argument(0, r1); // r1,: lock address
902
903 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), r0, r1);
904
905 oop_maps = new OopMapSet();
906 oop_maps->add_gc_map(call_offset, map);
907 restore_live_registers(sasm, save_fpu_registers);
908 }
909 break;
910
911 case monitorexit_nofpu_id:
912 save_fpu_registers = false;
913 // fall through
914 case monitorexit_id:
915 {
|