OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 output_frame->SetDoubleRegister(i, double_value); | 131 output_frame->SetDoubleRegister(i, double_value); |
132 } | 132 } |
133 } | 133 } |
134 | 134 |
135 | 135 |
136 Code* Deoptimizer::NotifyStubFailureBuiltin() { | 136 Code* Deoptimizer::NotifyStubFailureBuiltin() { |
137 return isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles); | 137 return isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles); |
138 } | 138 } |
139 | 139 |
140 | 140 |
| 141 #define __ masm-> |
| 142 |
| 143 static void CopyRegisterDumpToFrame(MacroAssembler* masm, |
| 144 Register frame, |
| 145 CPURegList reg_list, |
| 146 Register scratch1, |
| 147 Register scratch2, |
| 148 int src_offset, |
| 149 int dst_offset) { |
| 150 int offset0, offset1; |
| 151 CPURegList copy_to_input = reg_list; |
| 152 int reg_count = reg_list.Count(); |
| 153 int reg_size = reg_list.RegisterSizeInBytes(); |
| 154 for (int i = 0; i < (reg_count / 2); i++) { |
| 155 __ PeekPair(scratch1, scratch2, src_offset + (i * reg_size * 2)); |
| 156 |
| 157 offset0 = (copy_to_input.PopLowestIndex().code() * reg_size) + dst_offset; |
| 158 offset1 = (copy_to_input.PopLowestIndex().code() * reg_size) + dst_offset; |
| 159 |
| 160 if ((offset0 + reg_size) == offset1) { |
| 161 // Registers are adjacent: store in pairs. |
| 162 __ Stp(scratch1, scratch2, MemOperand(frame, offset0)); |
| 163 } else { |
| 164 // Registers are not adjacent: store individually. |
| 165 __ Str(scratch1, MemOperand(frame, offset0)); |
| 166 __ Str(scratch2, MemOperand(frame, offset1)); |
| 167 } |
| 168 } |
| 169 if ((reg_count & 1) != 0) { |
| 170 __ Peek(scratch1, src_offset + (reg_count - 1) * reg_size); |
| 171 offset0 = (copy_to_input.PopLowestIndex().code() * reg_size) + dst_offset; |
| 172 __ Str(scratch1, MemOperand(frame, offset0)); |
| 173 } |
| 174 } |
| 175 |
| 176 #undef __ |
| 177 |
141 #define __ masm()-> | 178 #define __ masm()-> |
142 | 179 |
143 void Deoptimizer::EntryGenerator::Generate() { | 180 void Deoptimizer::EntryGenerator::Generate() { |
144 GeneratePrologue(); | 181 GeneratePrologue(); |
145 | 182 |
146 // TODO(all): This code needs to be revisited. We probably only need to save | 183 // TODO(all): This code needs to be revisited. We probably only need to save |
147 // caller-saved registers here. Callee-saved registers can be stored directly | 184 // caller-saved registers here. Callee-saved registers can be stored directly |
148 // in the input frame. | 185 // in the input frame. |
149 | 186 |
150 // Save all allocatable floating point registers. | 187 // Save all allocatable floating point registers. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate()), 6); | 230 __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate()), 6); |
194 } | 231 } |
195 | 232 |
196 // Preserve "deoptimizer" object in register x0. | 233 // Preserve "deoptimizer" object in register x0. |
197 Register deoptimizer = x0; | 234 Register deoptimizer = x0; |
198 | 235 |
199 // Get the input frame descriptor pointer. | 236 // Get the input frame descriptor pointer. |
200 __ Ldr(x1, MemOperand(deoptimizer, Deoptimizer::input_offset())); | 237 __ Ldr(x1, MemOperand(deoptimizer, Deoptimizer::input_offset())); |
201 | 238 |
202 // Copy core registers into the input frame. | 239 // Copy core registers into the input frame. |
203 CPURegList copy_to_input = saved_registers; | 240 CopyRegisterDumpToFrame(masm(), x1, saved_registers, x2, x4, 0, |
204 for (int i = 0; i < saved_registers.Count(); i++) { | 241 FrameDescription::registers_offset()); |
205 // TODO(all): Look for opportunities to optimize this by using ldp/stp. | |
206 __ Peek(x2, i * kPointerSize); | |
207 CPURegister current_reg = copy_to_input.PopLowestIndex(); | |
208 int offset = (current_reg.code() * kPointerSize) + | |
209 FrameDescription::registers_offset(); | |
210 __ Str(x2, MemOperand(x1, offset)); | |
211 } | |
212 | 242 |
213 // Copy FP registers to the input frame. | 243 // Copy FP registers to the input frame. |
214 for (int i = 0; i < saved_fp_registers.Count(); i++) { | 244 CopyRegisterDumpToFrame(masm(), x1, saved_fp_registers, x2, x4, |
215 // TODO(all): Look for opportunities to optimize this by using ldp/stp. | 245 kFPRegistersOffset, |
216 int dst_offset = FrameDescription::double_registers_offset() + | 246 FrameDescription::double_registers_offset()); |
217 (i * kDoubleSize); | |
218 int src_offset = kFPRegistersOffset + (i * kDoubleSize); | |
219 __ Peek(x2, src_offset); | |
220 __ Str(x2, MemOperand(x1, dst_offset)); | |
221 } | |
222 | 247 |
223 // Remove the bailout id and the saved registers from the stack. | 248 // Remove the bailout id and the saved registers from the stack. |
224 __ Drop(1 + (kSavedRegistersAreaSize / kXRegSize)); | 249 __ Drop(1 + (kSavedRegistersAreaSize / kXRegSize)); |
225 | 250 |
226 // Compute a pointer to the unwinding limit in register x2; that is | 251 // Compute a pointer to the unwinding limit in register x2; that is |
227 // the first stack slot not part of the input frame. | 252 // the first stack slot not part of the input frame. |
228 Register unwind_limit = x2; | 253 Register unwind_limit = x2; |
229 __ Ldr(unwind_limit, MemOperand(x1, FrameDescription::frame_size_offset())); | 254 __ Ldr(unwind_limit, MemOperand(x1, FrameDescription::frame_size_offset())); |
230 __ Add(unwind_limit, unwind_limit, __ StackPointer()); | 255 __ Add(unwind_limit, unwind_limit, __ StackPointer()); |
231 | 256 |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 | 404 |
380 void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) { | 405 void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) { |
381 // No out-of-line constant pool support. | 406 // No out-of-line constant pool support. |
382 UNREACHABLE(); | 407 UNREACHABLE(); |
383 } | 408 } |
384 | 409 |
385 | 410 |
386 #undef __ | 411 #undef __ |
387 | 412 |
388 } } // namespace v8::internal | 413 } } // namespace v8::internal |
OLD | NEW |