Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(238)

Side by Side Diff: src/mips64/deoptimizer-mips64.cc

Issue 2829073002: MIPS64: Move load/store instructions to macro-assembler. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/mips64/constants-mips64.h ('k') | src/mips64/macro-assembler-mips64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/codegen.h" 5 #include "src/codegen.h"
6 #include "src/deoptimizer.h" 6 #include "src/deoptimizer.h"
7 #include "src/full-codegen/full-codegen.h" 7 #include "src/full-codegen/full-codegen.h"
8 #include "src/register-configuration.h" 8 #include "src/register-configuration.h"
9 #include "src/safepoint-table.h" 9 #include "src/safepoint-table.h"
10 10
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kMaxNumRegisters; 116 const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kMaxNumRegisters;
117 const int kFloatRegsSize = kFloatSize * FloatRegister::kMaxNumRegisters; 117 const int kFloatRegsSize = kFloatSize * FloatRegister::kMaxNumRegisters;
118 118
119 // Save all double FPU registers before messing with them. 119 // Save all double FPU registers before messing with them.
120 __ Dsubu(sp, sp, Operand(kDoubleRegsSize)); 120 __ Dsubu(sp, sp, Operand(kDoubleRegsSize));
121 const RegisterConfiguration* config = RegisterConfiguration::Crankshaft(); 121 const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
122 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { 122 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
123 int code = config->GetAllocatableDoubleCode(i); 123 int code = config->GetAllocatableDoubleCode(i);
124 const DoubleRegister fpu_reg = DoubleRegister::from_code(code); 124 const DoubleRegister fpu_reg = DoubleRegister::from_code(code);
125 int offset = code * kDoubleSize; 125 int offset = code * kDoubleSize;
126 __ sdc1(fpu_reg, MemOperand(sp, offset)); 126 __ Sdc1(fpu_reg, MemOperand(sp, offset));
127 } 127 }
128 128
129 // Save all float FPU registers before messing with them. 129 // Save all float FPU registers before messing with them.
130 __ Dsubu(sp, sp, Operand(kFloatRegsSize)); 130 __ Dsubu(sp, sp, Operand(kFloatRegsSize));
131 for (int i = 0; i < config->num_allocatable_float_registers(); ++i) { 131 for (int i = 0; i < config->num_allocatable_float_registers(); ++i) {
132 int code = config->GetAllocatableFloatCode(i); 132 int code = config->GetAllocatableFloatCode(i);
133 const FloatRegister fpu_reg = FloatRegister::from_code(code); 133 const FloatRegister fpu_reg = FloatRegister::from_code(code);
134 int offset = code * kFloatSize; 134 int offset = code * kFloatSize;
135 __ swc1(fpu_reg, MemOperand(sp, offset)); 135 __ Swc1(fpu_reg, MemOperand(sp, offset));
136 } 136 }
137 137
138 // Push saved_regs (needed to populate FrameDescription::registers_). 138 // Push saved_regs (needed to populate FrameDescription::registers_).
139 // Leave gaps for other registers. 139 // Leave gaps for other registers.
140 __ Dsubu(sp, sp, kNumberOfRegisters * kPointerSize); 140 __ Dsubu(sp, sp, kNumberOfRegisters * kPointerSize);
141 for (int16_t i = kNumberOfRegisters - 1; i >= 0; i--) { 141 for (int16_t i = kNumberOfRegisters - 1; i >= 0; i--) {
142 if ((saved_regs & (1 << i)) != 0) { 142 if ((saved_regs & (1 << i)) != 0) {
143 __ sd(ToRegister(i), MemOperand(sp, kPointerSize * i)); 143 __ Sd(ToRegister(i), MemOperand(sp, kPointerSize * i));
144 } 144 }
145 } 145 }
146 146
147 __ li(a2, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); 147 __ li(a2, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
148 __ sd(fp, MemOperand(a2)); 148 __ Sd(fp, MemOperand(a2));
149 149
150 const int kSavedRegistersAreaSize = 150 const int kSavedRegistersAreaSize =
151 (kNumberOfRegisters * kPointerSize) + kDoubleRegsSize + kFloatRegsSize; 151 (kNumberOfRegisters * kPointerSize) + kDoubleRegsSize + kFloatRegsSize;
152 152
153 // Get the bailout id from the stack. 153 // Get the bailout id from the stack.
154 __ ld(a2, MemOperand(sp, kSavedRegistersAreaSize)); 154 __ Ld(a2, MemOperand(sp, kSavedRegistersAreaSize));
155 155
156 // Get the address of the location in the code object (a3) (return 156 // Get the address of the location in the code object (a3) (return
157 // address for lazy deoptimization) and compute the fp-to-sp delta in 157 // address for lazy deoptimization) and compute the fp-to-sp delta in
158 // register a4. 158 // register a4.
159 __ mov(a3, ra); 159 __ mov(a3, ra);
160 // Correct one word for bailout id. 160 // Correct one word for bailout id.
161 __ Daddu(a4, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize))); 161 __ Daddu(a4, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize)));
162 162
163 __ Dsubu(a4, fp, a4); 163 __ Dsubu(a4, fp, a4);
164 164
165 // Allocate a new deoptimizer object. 165 // Allocate a new deoptimizer object.
166 __ PrepareCallCFunction(6, a5); 166 __ PrepareCallCFunction(6, a5);
167 // Pass six arguments, according to n64 ABI. 167 // Pass six arguments, according to n64 ABI.
168 __ mov(a0, zero_reg); 168 __ mov(a0, zero_reg);
169 Label context_check; 169 Label context_check;
170 __ ld(a1, MemOperand(fp, CommonFrameConstants::kContextOrFrameTypeOffset)); 170 __ Ld(a1, MemOperand(fp, CommonFrameConstants::kContextOrFrameTypeOffset));
171 __ JumpIfSmi(a1, &context_check); 171 __ JumpIfSmi(a1, &context_check);
172 __ ld(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 172 __ Ld(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
173 __ bind(&context_check); 173 __ bind(&context_check);
174 __ li(a1, Operand(type())); // Bailout type. 174 __ li(a1, Operand(type())); // Bailout type.
175 // a2: bailout id already loaded. 175 // a2: bailout id already loaded.
176 // a3: code address or 0 already loaded. 176 // a3: code address or 0 already loaded.
177 // a4: already has fp-to-sp delta. 177 // a4: already has fp-to-sp delta.
178 __ li(a5, Operand(ExternalReference::isolate_address(isolate()))); 178 __ li(a5, Operand(ExternalReference::isolate_address(isolate())));
179 179
180 // Call Deoptimizer::New(). 180 // Call Deoptimizer::New().
181 { 181 {
182 AllowExternalCallThatCantCauseGC scope(masm()); 182 AllowExternalCallThatCantCauseGC scope(masm());
183 __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate()), 6); 183 __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate()), 6);
184 } 184 }
185 185
186 // Preserve "deoptimizer" object in register v0 and get the input 186 // Preserve "deoptimizer" object in register v0 and get the input
187 // frame descriptor pointer to a1 (deoptimizer->input_); 187 // frame descriptor pointer to a1 (deoptimizer->input_);
188 // Move deopt-obj to a0 for call to Deoptimizer::ComputeOutputFrames() below. 188 // Move deopt-obj to a0 for call to Deoptimizer::ComputeOutputFrames() below.
189 __ mov(a0, v0); 189 __ mov(a0, v0);
190 __ ld(a1, MemOperand(v0, Deoptimizer::input_offset())); 190 __ Ld(a1, MemOperand(v0, Deoptimizer::input_offset()));
191 191
192 // Copy core registers into FrameDescription::registers_[kNumRegisters]. 192 // Copy core registers into FrameDescription::registers_[kNumRegisters].
193 DCHECK(Register::kNumRegisters == kNumberOfRegisters); 193 DCHECK(Register::kNumRegisters == kNumberOfRegisters);
194 for (int i = 0; i < kNumberOfRegisters; i++) { 194 for (int i = 0; i < kNumberOfRegisters; i++) {
195 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); 195 int offset = (i * kPointerSize) + FrameDescription::registers_offset();
196 if ((saved_regs & (1 << i)) != 0) { 196 if ((saved_regs & (1 << i)) != 0) {
197 __ ld(a2, MemOperand(sp, i * kPointerSize)); 197 __ Ld(a2, MemOperand(sp, i * kPointerSize));
198 __ sd(a2, MemOperand(a1, offset)); 198 __ Sd(a2, MemOperand(a1, offset));
199 } else if (FLAG_debug_code) { 199 } else if (FLAG_debug_code) {
200 __ li(a2, kDebugZapValue); 200 __ li(a2, kDebugZapValue);
201 __ sd(a2, MemOperand(a1, offset)); 201 __ Sd(a2, MemOperand(a1, offset));
202 } 202 }
203 } 203 }
204 204
205 int double_regs_offset = FrameDescription::double_registers_offset(); 205 int double_regs_offset = FrameDescription::double_registers_offset();
206 // Copy FPU registers to 206 // Copy FPU registers to
207 // double_registers_[DoubleRegister::kNumAllocatableRegisters] 207 // double_registers_[DoubleRegister::kNumAllocatableRegisters]
208 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { 208 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
209 int code = config->GetAllocatableDoubleCode(i); 209 int code = config->GetAllocatableDoubleCode(i);
210 int dst_offset = code * kDoubleSize + double_regs_offset; 210 int dst_offset = code * kDoubleSize + double_regs_offset;
211 int src_offset = 211 int src_offset =
212 code * kDoubleSize + kNumberOfRegisters * kPointerSize + kFloatRegsSize; 212 code * kDoubleSize + kNumberOfRegisters * kPointerSize + kFloatRegsSize;
213 __ ldc1(f0, MemOperand(sp, src_offset)); 213 __ Ldc1(f0, MemOperand(sp, src_offset));
214 __ sdc1(f0, MemOperand(a1, dst_offset)); 214 __ Sdc1(f0, MemOperand(a1, dst_offset));
215 } 215 }
216 216
217 int float_regs_offset = FrameDescription::float_registers_offset(); 217 int float_regs_offset = FrameDescription::float_registers_offset();
218 // Copy FPU registers to 218 // Copy FPU registers to
219 // float_registers_[FloatRegister::kNumAllocatableRegisters] 219 // float_registers_[FloatRegister::kNumAllocatableRegisters]
220 for (int i = 0; i < config->num_allocatable_float_registers(); ++i) { 220 for (int i = 0; i < config->num_allocatable_float_registers(); ++i) {
221 int code = config->GetAllocatableFloatCode(i); 221 int code = config->GetAllocatableFloatCode(i);
222 int dst_offset = code * kFloatSize + float_regs_offset; 222 int dst_offset = code * kFloatSize + float_regs_offset;
223 int src_offset = code * kFloatSize + kNumberOfRegisters * kPointerSize; 223 int src_offset = code * kFloatSize + kNumberOfRegisters * kPointerSize;
224 __ lwc1(f0, MemOperand(sp, src_offset)); 224 __ Lwc1(f0, MemOperand(sp, src_offset));
225 __ swc1(f0, MemOperand(a1, dst_offset)); 225 __ Swc1(f0, MemOperand(a1, dst_offset));
226 } 226 }
227 227
228 // Remove the bailout id and the saved registers from the stack. 228 // Remove the bailout id and the saved registers from the stack.
229 __ Daddu(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize))); 229 __ Daddu(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize)));
230 230
231 // Compute a pointer to the unwinding limit in register a2; that is 231 // Compute a pointer to the unwinding limit in register a2; that is
232 // the first stack slot not part of the input frame. 232 // the first stack slot not part of the input frame.
233 __ ld(a2, MemOperand(a1, FrameDescription::frame_size_offset())); 233 __ Ld(a2, MemOperand(a1, FrameDescription::frame_size_offset()));
234 __ Daddu(a2, a2, sp); 234 __ Daddu(a2, a2, sp);
235 235
236 // Unwind the stack down to - but not including - the unwinding 236 // Unwind the stack down to - but not including - the unwinding
237 // limit and copy the contents of the activation frame to the input 237 // limit and copy the contents of the activation frame to the input
238 // frame description. 238 // frame description.
239 __ Daddu(a3, a1, Operand(FrameDescription::frame_content_offset())); 239 __ Daddu(a3, a1, Operand(FrameDescription::frame_content_offset()));
240 Label pop_loop; 240 Label pop_loop;
241 Label pop_loop_header; 241 Label pop_loop_header;
242 __ BranchShort(&pop_loop_header); 242 __ BranchShort(&pop_loop_header);
243 __ bind(&pop_loop); 243 __ bind(&pop_loop);
244 __ pop(a4); 244 __ pop(a4);
245 __ sd(a4, MemOperand(a3, 0)); 245 __ Sd(a4, MemOperand(a3, 0));
246 __ daddiu(a3, a3, sizeof(uint64_t)); 246 __ daddiu(a3, a3, sizeof(uint64_t));
247 __ bind(&pop_loop_header); 247 __ bind(&pop_loop_header);
248 __ BranchShort(&pop_loop, ne, a2, Operand(sp)); 248 __ BranchShort(&pop_loop, ne, a2, Operand(sp));
249 // Compute the output frame in the deoptimizer. 249 // Compute the output frame in the deoptimizer.
250 __ push(a0); // Preserve deoptimizer object across call. 250 __ push(a0); // Preserve deoptimizer object across call.
251 // a0: deoptimizer object; a1: scratch. 251 // a0: deoptimizer object; a1: scratch.
252 __ PrepareCallCFunction(1, a1); 252 __ PrepareCallCFunction(1, a1);
253 // Call Deoptimizer::ComputeOutputFrames(). 253 // Call Deoptimizer::ComputeOutputFrames().
254 { 254 {
255 AllowExternalCallThatCantCauseGC scope(masm()); 255 AllowExternalCallThatCantCauseGC scope(masm());
256 __ CallCFunction( 256 __ CallCFunction(
257 ExternalReference::compute_output_frames_function(isolate()), 1); 257 ExternalReference::compute_output_frames_function(isolate()), 1);
258 } 258 }
259 __ pop(a0); // Restore deoptimizer object (class Deoptimizer). 259 __ pop(a0); // Restore deoptimizer object (class Deoptimizer).
260 260
261 __ ld(sp, MemOperand(a0, Deoptimizer::caller_frame_top_offset())); 261 __ Ld(sp, MemOperand(a0, Deoptimizer::caller_frame_top_offset()));
262 262
263 // Replace the current (input) frame with the output frames. 263 // Replace the current (input) frame with the output frames.
264 Label outer_push_loop, inner_push_loop, 264 Label outer_push_loop, inner_push_loop,
265 outer_loop_header, inner_loop_header; 265 outer_loop_header, inner_loop_header;
266 // Outer loop state: a4 = current "FrameDescription** output_", 266 // Outer loop state: a4 = current "FrameDescription** output_",
267 // a1 = one past the last FrameDescription**. 267 // a1 = one past the last FrameDescription**.
268 __ lw(a1, MemOperand(a0, Deoptimizer::output_count_offset())); 268 __ Lw(a1, MemOperand(a0, Deoptimizer::output_count_offset()));
269 __ ld(a4, MemOperand(a0, Deoptimizer::output_offset())); // a4 is output_. 269 __ Ld(a4, MemOperand(a0, Deoptimizer::output_offset())); // a4 is output_.
270 __ Dlsa(a1, a4, a1, kPointerSizeLog2); 270 __ Dlsa(a1, a4, a1, kPointerSizeLog2);
271 __ BranchShort(&outer_loop_header); 271 __ BranchShort(&outer_loop_header);
272 __ bind(&outer_push_loop); 272 __ bind(&outer_push_loop);
273 // Inner loop state: a2 = current FrameDescription*, a3 = loop index. 273 // Inner loop state: a2 = current FrameDescription*, a3 = loop index.
274 __ ld(a2, MemOperand(a4, 0)); // output_[ix] 274 __ Ld(a2, MemOperand(a4, 0)); // output_[ix]
275 __ ld(a3, MemOperand(a2, FrameDescription::frame_size_offset())); 275 __ Ld(a3, MemOperand(a2, FrameDescription::frame_size_offset()));
276 __ BranchShort(&inner_loop_header); 276 __ BranchShort(&inner_loop_header);
277 __ bind(&inner_push_loop); 277 __ bind(&inner_push_loop);
278 __ Dsubu(a3, a3, Operand(sizeof(uint64_t))); 278 __ Dsubu(a3, a3, Operand(sizeof(uint64_t)));
279 __ Daddu(a6, a2, Operand(a3)); 279 __ Daddu(a6, a2, Operand(a3));
280 __ ld(a7, MemOperand(a6, FrameDescription::frame_content_offset())); 280 __ Ld(a7, MemOperand(a6, FrameDescription::frame_content_offset()));
281 __ push(a7); 281 __ push(a7);
282 __ bind(&inner_loop_header); 282 __ bind(&inner_loop_header);
283 __ BranchShort(&inner_push_loop, ne, a3, Operand(zero_reg)); 283 __ BranchShort(&inner_push_loop, ne, a3, Operand(zero_reg));
284 284
285 __ Daddu(a4, a4, Operand(kPointerSize)); 285 __ Daddu(a4, a4, Operand(kPointerSize));
286 __ bind(&outer_loop_header); 286 __ bind(&outer_loop_header);
287 __ BranchShort(&outer_push_loop, lt, a4, Operand(a1)); 287 __ BranchShort(&outer_push_loop, lt, a4, Operand(a1));
288 288
289 __ ld(a1, MemOperand(a0, Deoptimizer::input_offset())); 289 __ Ld(a1, MemOperand(a0, Deoptimizer::input_offset()));
290 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { 290 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
291 int code = config->GetAllocatableDoubleCode(i); 291 int code = config->GetAllocatableDoubleCode(i);
292 const DoubleRegister fpu_reg = DoubleRegister::from_code(code); 292 const DoubleRegister fpu_reg = DoubleRegister::from_code(code);
293 int src_offset = code * kDoubleSize + double_regs_offset; 293 int src_offset = code * kDoubleSize + double_regs_offset;
294 __ ldc1(fpu_reg, MemOperand(a1, src_offset)); 294 __ Ldc1(fpu_reg, MemOperand(a1, src_offset));
295 } 295 }
296 296
297 // Push state, pc, and continuation from the last output frame. 297 // Push state, pc, and continuation from the last output frame.
298 __ ld(a6, MemOperand(a2, FrameDescription::state_offset())); 298 __ Ld(a6, MemOperand(a2, FrameDescription::state_offset()));
299 __ push(a6); 299 __ push(a6);
300 300
301 __ ld(a6, MemOperand(a2, FrameDescription::pc_offset())); 301 __ Ld(a6, MemOperand(a2, FrameDescription::pc_offset()));
302 __ push(a6); 302 __ push(a6);
303 __ ld(a6, MemOperand(a2, FrameDescription::continuation_offset())); 303 __ Ld(a6, MemOperand(a2, FrameDescription::continuation_offset()));
304 __ push(a6); 304 __ push(a6);
305 305
306 306
307 // Technically restoring 'at' should work unless zero_reg is also restored 307 // Technically restoring 'at' should work unless zero_reg is also restored
308 // but it's safer to check for this. 308 // but it's safer to check for this.
309 DCHECK(!(at.bit() & restored_regs)); 309 DCHECK(!(at.bit() & restored_regs));
310 // Restore the registers from the last output frame. 310 // Restore the registers from the last output frame.
311 __ mov(at, a2); 311 __ mov(at, a2);
312 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { 312 for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
313 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); 313 int offset = (i * kPointerSize) + FrameDescription::registers_offset();
314 if ((restored_regs & (1 << i)) != 0) { 314 if ((restored_regs & (1 << i)) != 0) {
315 __ ld(ToRegister(i), MemOperand(at, offset)); 315 __ Ld(ToRegister(i), MemOperand(at, offset));
316 } 316 }
317 } 317 }
318 318
319 __ InitializeRootRegister(); 319 __ InitializeRootRegister();
320 320
321 __ pop(at); // Get continuation, leave pc on stack. 321 __ pop(at); // Get continuation, leave pc on stack.
322 __ pop(ra); 322 __ pop(ra);
323 __ Jump(at); 323 __ Jump(at);
324 __ stop("Unreachable."); 324 __ stop("Unreachable.");
325 } 325 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 // No embedded constant pool support. 403 // No embedded constant pool support.
404 UNREACHABLE(); 404 UNREACHABLE();
405 } 405 }
406 406
407 407
408 #undef __ 408 #undef __
409 409
410 410
411 } // namespace internal 411 } // namespace internal
412 } // namespace v8 412 } // namespace v8
OLDNEW
« no previous file with comments | « src/mips64/constants-mips64.h ('k') | src/mips64/macro-assembler-mips64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698