6 #include "src/arm64/assembler-arm64-inl.h" 7 #include "src/arm64/macro-assembler-arm64-inl.h" 8 #include "src/deoptimizer.h" 9 #include "src/frame-constants.h" 10 #include "src/register-configuration.h" 11 #include "src/safepoint-table.h" 21 void CopyRegListToFrame(MacroAssembler* masm,
const Register& dst,
22 int dst_offset,
const CPURegList& reg_list,
23 const Register& temp0,
const Register& temp1,
25 DCHECK_EQ(reg_list.Count() % 2, 0);
26 UseScratchRegisterScope temps(masm);
27 CPURegList copy_to_input = reg_list;
28 int reg_size = reg_list.RegisterSizeInBytes();
29 DCHECK_EQ(temp0.SizeInBytes(), reg_size);
30 DCHECK_EQ(temp1.SizeInBytes(), reg_size);
35 Register src = temps.AcquireX();
36 masm->Add(src, sp, src_offset);
37 masm->Add(dst, dst, dst_offset);
40 for (
int i = 0;
i < reg_list.Count();
i += 2) {
41 masm->Ldp(temp0, temp1, MemOperand(src,
i * reg_size));
43 CPURegister reg0 = copy_to_input.PopLowestIndex();
44 CPURegister reg1 = copy_to_input.PopLowestIndex();
45 int offset0 = reg0.code() * reg_size;
46 int offset1 = reg1.code() * reg_size;
49 if (offset1 == offset0 + reg_size) {
50 masm->Stp(temp0, temp1, MemOperand(dst, offset0));
52 masm->Str(temp0, MemOperand(dst, offset0));
53 masm->Str(temp1, MemOperand(dst, offset1));
56 masm->Sub(dst, dst, dst_offset);
59 void RestoreRegList(MacroAssembler* masm,
const CPURegList& reg_list,
60 const Register& src_base,
int src_offset) {
61 DCHECK_EQ(reg_list.Count() % 2, 0);
62 UseScratchRegisterScope temps(masm);
63 CPURegList restore_list = reg_list;
64 int reg_size = restore_list.RegisterSizeInBytes();
69 Register src = temps.AcquireX();
70 masm->Add(src, src_base, src_offset);
72 #if defined(V8_OS_WIN) 74 restore_list.Remove(x18);
78 while (!restore_list.IsEmpty()) {
79 CPURegister reg0 = restore_list.PopLowestIndex();
80 CPURegister reg1 = restore_list.PopLowestIndex();
81 int offset0 = reg0.code() * reg_size;
83 #if defined(V8_OS_WIN) 84 if (reg1 == NoCPUReg) {
85 masm->Ldr(reg0, MemOperand(src, offset0));
90 int offset1 = reg1.code() * reg_size;
93 if (offset1 == offset0 + reg_size) {
94 masm->Ldp(reg0, reg1, MemOperand(src, offset0));
96 masm->Ldr(reg0, MemOperand(src, offset0));
97 masm->Ldr(reg1, MemOperand(src, offset1));
103 void Deoptimizer::TableEntryGenerator::Generate() {
111 CPURegList saved_double_registers(
112 CPURegister::kVRegister, kDRegSizeInBits,
113 RegisterConfiguration::Default()->allocatable_double_codes_mask());
114 DCHECK_EQ(saved_double_registers.Count() % 2, 0);
115 __ PushCPURegList(saved_double_registers);
117 CPURegList saved_float_registers(
118 CPURegister::kVRegister, kSRegSizeInBits,
119 RegisterConfiguration::Default()->allocatable_float_codes_mask());
120 DCHECK_EQ(saved_float_registers.Count() % 4, 0);
121 __ PushCPURegList(saved_float_registers);
124 CPURegList saved_registers(CPURegister::kRegister, kXRegSizeInBits, 0, 28);
125 saved_registers.Remove(ip0);
126 saved_registers.Remove(ip1);
127 saved_registers.Combine(fp);
128 DCHECK_EQ(saved_registers.Count() % 2, 0);
129 __ PushCPURegList(saved_registers);
131 __ Mov(x3, Operand(ExternalReference::Create(
132 IsolateAddressId::kCEntryFPAddress, isolate())));
133 __ Str(fp, MemOperand(x3));
135 const int kSavedRegistersAreaSize =
136 (saved_registers.Count() * kXRegSize) +
137 (saved_double_registers.Count() * kDRegSize) +
138 (saved_float_registers.Count() * kSRegSize);
141 const int kFloatRegistersOffset = saved_registers.Count() * kXRegSize;
142 const int kDoubleRegistersOffset =
143 kFloatRegistersOffset + saved_float_registers.Count() * kSRegSize;
146 Register bailout_id = x2;
147 __ Peek(bailout_id, kSavedRegistersAreaSize);
149 Register code_object = x3;
150 Register fp_to_sp = x4;
153 __ Mov(code_object, lr);
156 __ Add(fp_to_sp, sp, kSavedRegistersAreaSize + (2 * kPointerSize));
157 __ Sub(fp_to_sp, fp, fp_to_sp);
160 __ Ldr(x1, MemOperand(fp, CommonFrameConstants::kContextOrFrameTypeOffset));
163 DCHECK_GT(kSavedRegistersAreaSize,
164 -JavaScriptFrameConstants::kFunctionOffset);
165 __ Ldr(x0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
168 __ Tst(x1, kSmiTagMask);
171 __ Mov(x1, static_cast<int>(deopt_kind()));
176 __ Mov(x5, ExternalReference::isolate_address(isolate()));
180 AllowExternalCallThatCantCauseGC scope(masm());
181 __ CallCFunction(ExternalReference::new_deoptimizer_function(), 6);
185 Register deoptimizer = x0;
188 __ Ldr(x1, MemOperand(deoptimizer, Deoptimizer::input_offset()));
191 CopyRegListToFrame(masm(), x1, FrameDescription::registers_offset(),
192 saved_registers, x2, x3);
195 CopyRegListToFrame(masm(), x1, FrameDescription::double_registers_offset(),
196 saved_double_registers, x2, x3, kDoubleRegistersOffset);
201 CopyRegListToFrame(masm(), x1, FrameDescription::float_registers_offset(),
202 saved_float_registers, w2, w3, kFloatRegistersOffset);
205 DCHECK_EQ(kSavedRegistersAreaSize % kXRegSize, 0);
206 __ Drop(2 + (kSavedRegistersAreaSize / kXRegSize));
210 Register unwind_limit = x2;
211 __ Ldr(unwind_limit, MemOperand(x1, FrameDescription::frame_size_offset()));
216 __ Add(x3, x1, FrameDescription::frame_content_offset());
217 __ SlotAddress(x1, 0);
218 __ Lsr(unwind_limit, unwind_limit, kPointerSizeLog2);
219 __ Mov(x5, unwind_limit);
220 __ CopyDoubleWords(x3, x1, x5);
221 __ Drop(unwind_limit);
227 AllowExternalCallThatCantCauseGC scope(masm());
228 __ CallCFunction(ExternalReference::compute_output_frames_function(), 1);
233 UseScratchRegisterScope temps(masm());
234 Register scratch = temps.AcquireX();
235 __ Ldr(scratch, MemOperand(x4, Deoptimizer::caller_frame_top_offset()));
240 Label outer_push_loop, inner_push_loop,
241 outer_loop_header, inner_loop_header;
242 __ Ldrsw(x1, MemOperand(x4, Deoptimizer::output_count_offset()));
243 __ Ldr(x0, MemOperand(x4, Deoptimizer::output_offset()));
244 __ Add(x1, x0, Operand(x1, LSL, kPointerSizeLog2));
245 __ B(&outer_loop_header);
247 __ Bind(&outer_push_loop);
248 Register current_frame = x2;
249 Register frame_size = x3;
250 __ Ldr(current_frame, MemOperand(x0, kPointerSize, PostIndex));
251 __ Ldr(x3, MemOperand(current_frame, FrameDescription::frame_size_offset()));
252 __ Lsr(frame_size, x3, kPointerSizeLog2);
253 __ Claim(frame_size);
255 __ Add(x7, current_frame, FrameDescription::frame_content_offset());
256 __ SlotAddress(x6, 0);
257 __ CopyDoubleWords(x6, x7, frame_size);
259 __ Bind(&outer_loop_header);
261 __ B(lt, &outer_push_loop);
263 __ Ldr(x1, MemOperand(x4, Deoptimizer::input_offset()));
264 RestoreRegList(masm(), saved_double_registers, x1,
265 FrameDescription::double_registers_offset());
276 DCHECK(!saved_registers.IncludesAliasOf(lr));
277 Register last_output_frame = lr;
278 __ Mov(last_output_frame, current_frame);
280 RestoreRegList(masm(), saved_registers, last_output_frame,
281 FrameDescription::registers_offset());
283 Register continuation = x7;
284 __ Ldr(continuation, MemOperand(last_output_frame,
285 FrameDescription::continuation_offset()));
286 __ Ldr(lr, MemOperand(last_output_frame, FrameDescription::pc_offset()));
292 const int Deoptimizer::table_entry_size_ = 0 * kInstrSize;
294 void Deoptimizer::TableEntryGenerator::GeneratePrologue() {
295 UseScratchRegisterScope temps(masm());
300 Register entry_id = temps.AcquireX();
301 DCHECK(entry_id.Is(x16));
302 __ Push(padreg, entry_id);
304 if (__ emit_debug_code()) {
306 __ Cmp(entry_id, count());
307 __ Check(lo, AbortReason::kOffsetOutOfRange);
311 bool Deoptimizer::PadTopOfStackRegister() {
return true; }
313 void FrameDescription::SetCallerPc(
unsigned offset, intptr_t value) {
314 SetFrameSlot(offset, value);
318 void FrameDescription::SetCallerFp(
unsigned offset, intptr_t value) {
319 SetFrameSlot(offset, value);
323 void FrameDescription::SetCallerConstantPool(
unsigned offset, intptr_t value) {