5 #include "src/assembler-inl.h" 6 #include "src/deoptimizer.h" 7 #include "src/register-configuration.h" 8 #include "src/safepoint-table.h" 13 const int Deoptimizer::table_entry_size_ = 8;
19 void Deoptimizer::TableEntryGenerator::Generate() {
24 const int kNumberOfRegisters = Register::kNumRegisters;
26 RegList restored_regs = kJSCallerSaved | kCalleeSaved;
27 RegList saved_regs = restored_regs | sp.bit();
29 const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kNumRegisters;
30 const int kFloatRegsSize = kFloatSize * FloatRegister::kNumRegisters;
33 __ subi(sp, sp, Operand(kDoubleRegsSize));
34 const RegisterConfiguration* config = RegisterConfiguration::Default();
35 for (
int i = 0;
i < config->num_allocatable_double_registers(); ++
i) {
36 int code = config->GetAllocatableDoubleCode(
i);
37 const DoubleRegister dreg = DoubleRegister::from_code(code);
38 int offset = code * kDoubleSize;
39 __ stfd(dreg, MemOperand(sp, offset));
42 __ subi(sp, sp, Operand(kFloatRegsSize));
43 for (
int i = 0;
i < config->num_allocatable_float_registers(); ++
i) {
44 int code = config->GetAllocatableFloatCode(
i);
45 const FloatRegister freg = FloatRegister::from_code(code);
46 int offset = code * kFloatSize;
47 __ stfs(freg, MemOperand(sp, offset));
52 __ subi(sp, sp, Operand(kNumberOfRegisters * kPointerSize));
53 for (int16_t
i = kNumberOfRegisters - 1;
i >= 0;
i--) {
54 if ((saved_regs & (1 <<
i)) != 0) {
55 __ StoreP(ToRegister(
i), MemOperand(sp, kPointerSize *
i));
59 __ mov(ip, Operand(ExternalReference::Create(
60 IsolateAddressId::kCEntryFPAddress, isolate())));
61 __ StoreP(fp, MemOperand(ip));
63 const int kSavedRegistersAreaSize =
64 (kNumberOfRegisters * kPointerSize) + kDoubleRegsSize + kFloatRegsSize;
67 __ LoadP(r5, MemOperand(sp, kSavedRegistersAreaSize));
74 __ addi(r7, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize)));
79 __ PrepareCallCFunction(6, r8);
80 __ li(r3, Operand::Zero());
82 __ LoadP(r4, MemOperand(fp, CommonFrameConstants::kContextOrFrameTypeOffset));
83 __ JumpIfSmi(r4, &context_check);
84 __ LoadP(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
85 __ bind(&context_check);
86 __ li(r4, Operand(static_cast<int>(deopt_kind())));
90 __ mov(r8, Operand(ExternalReference::isolate_address(isolate())));
93 AllowExternalCallThatCantCauseGC scope(masm());
94 __ CallCFunction(ExternalReference::new_deoptimizer_function(), 6);
99 __ LoadP(r4, MemOperand(r3, Deoptimizer::input_offset()));
102 DCHECK_EQ(Register::kNumRegisters, kNumberOfRegisters);
103 for (
int i = 0;
i < kNumberOfRegisters;
i++) {
104 int offset = (
i * kPointerSize) + FrameDescription::registers_offset();
105 __ LoadP(r5, MemOperand(sp,
i * kPointerSize));
106 __ StoreP(r5, MemOperand(r4, offset));
109 int double_regs_offset = FrameDescription::double_registers_offset();
112 for (
int i = 0;
i < config->num_allocatable_double_registers(); ++
i) {
113 int code = config->GetAllocatableDoubleCode(
i);
114 int dst_offset = code * kDoubleSize + double_regs_offset;
116 code * kDoubleSize + kNumberOfRegisters * kPointerSize + kFloatRegsSize;
117 __ lfd(d0, MemOperand(sp, src_offset));
118 __ stfd(d0, MemOperand(r4, dst_offset));
120 int float_regs_offset = FrameDescription::float_registers_offset();
123 for (
int i = 0;
i < config->num_allocatable_float_registers(); ++
i) {
124 int code = config->GetAllocatableFloatCode(
i);
125 int dst_offset = code * kFloatSize + float_regs_offset;
126 int src_offset = code * kFloatSize + kNumberOfRegisters * kPointerSize;
127 __ lfs(d0, MemOperand(sp, src_offset));
128 __ stfs(d0, MemOperand(r4, dst_offset));
131 __ addi(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize)));
135 __ LoadP(r5, MemOperand(r4, FrameDescription::frame_size_offset()));
141 __ addi(r6, r4, Operand(FrameDescription::frame_content_offset()));
143 Label pop_loop_header;
144 __ b(&pop_loop_header);
147 __ StoreP(r7, MemOperand(r6, 0));
148 __ addi(r6, r6, Operand(kPointerSize));
149 __ bind(&pop_loop_header);
156 __ PrepareCallCFunction(1, r4);
159 AllowExternalCallThatCantCauseGC scope(masm());
160 __ CallCFunction(ExternalReference::compute_output_frames_function(), 1);
164 __ LoadP(sp, MemOperand(r3, Deoptimizer::caller_frame_top_offset()));
167 Label outer_push_loop, inner_push_loop, outer_loop_header, inner_loop_header;
170 __ lwz(r4, MemOperand(r3, Deoptimizer::output_count_offset()));
171 __ LoadP(r7, MemOperand(r3, Deoptimizer::output_offset()));
172 __ ShiftLeftImm(r4, r4, Operand(kPointerSizeLog2));
174 __ b(&outer_loop_header);
176 __ bind(&outer_push_loop);
178 __ LoadP(r5, MemOperand(r7, 0));
179 __ LoadP(r6, MemOperand(r5, FrameDescription::frame_size_offset()));
180 __ b(&inner_loop_header);
182 __ bind(&inner_push_loop);
183 __ addi(r6, r6, Operand(-
sizeof(intptr_t)));
185 __ LoadP(r9, MemOperand(r9, FrameDescription::frame_content_offset()));
188 __ bind(&inner_loop_header);
189 __ cmpi(r6, Operand::Zero());
190 __ bne(&inner_push_loop);
192 __ addi(r7, r7, Operand(kPointerSize));
193 __ bind(&outer_loop_header);
195 __ blt(&outer_push_loop);
197 __ LoadP(r4, MemOperand(r3, Deoptimizer::input_offset()));
198 for (
int i = 0;
i < config->num_allocatable_double_registers(); ++
i) {
199 int code = config->GetAllocatableDoubleCode(
i);
200 const DoubleRegister dreg = DoubleRegister::from_code(code);
201 int src_offset = code * kDoubleSize + double_regs_offset;
202 __ lfd(dreg, MemOperand(r4, src_offset));
206 __ LoadP(r9, MemOperand(r5, FrameDescription::pc_offset()));
208 __ LoadP(r9, MemOperand(r5, FrameDescription::continuation_offset()));
212 DCHECK(!(ip.bit() & restored_regs));
214 for (
int i = kNumberOfRegisters - 1;
i >= 0;
i--) {
215 int offset = (
i * kPointerSize) + FrameDescription::registers_offset();
216 if ((restored_regs & (1 <<
i)) != 0) {
217 __ LoadP(ToRegister(
i), MemOperand(ip, offset));
225 __ stop(
"Unreachable.");
229 void Deoptimizer::TableEntryGenerator::GeneratePrologue() {
230 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm());
235 for (
int i = 0;
i < count();
i++) {
236 int start = masm()->pc_offset();
238 __ li(ip, Operand(
i));
240 DCHECK(masm()->pc_offset() - start == table_entry_size_);
246 bool Deoptimizer::PadTopOfStackRegister() {
return false; }
248 void FrameDescription::SetCallerPc(
unsigned offset, intptr_t value) {
249 SetFrameSlot(offset, value);
253 void FrameDescription::SetCallerFp(
unsigned offset, intptr_t value) {
254 SetFrameSlot(offset, value);
258 void FrameDescription::SetCallerConstantPool(
unsigned offset, intptr_t value) {
259 DCHECK(FLAG_enable_embedded_constant_pool);
260 SetFrameSlot(offset, value);