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

Side by Side Diff: src/ia32/macro-assembler-ia32.cc

Issue 3141047: Cleanup the way the debugger stores live registers when entering at a break... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « src/ia32/macro-assembler-ia32.h ('k') | src/serialize.cc » ('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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 184
185 185
186 void MacroAssembler::StackLimitCheck(Label* on_stack_overflow) { 186 void MacroAssembler::StackLimitCheck(Label* on_stack_overflow) {
187 cmp(esp, 187 cmp(esp,
188 Operand::StaticVariable(ExternalReference::address_of_stack_limit())); 188 Operand::StaticVariable(ExternalReference::address_of_stack_limit()));
189 j(below, on_stack_overflow); 189 j(below, on_stack_overflow);
190 } 190 }
191 191
192 192
193 #ifdef ENABLE_DEBUGGER_SUPPORT 193 #ifdef ENABLE_DEBUGGER_SUPPORT
194 void MacroAssembler::SaveRegistersToMemory(RegList regs) {
195 ASSERT((regs & ~kJSCallerSaved) == 0);
196 // Copy the content of registers to memory location.
197 for (int i = 0; i < kNumJSCallerSaved; i++) {
198 int r = JSCallerSavedCode(i);
199 if ((regs & (1 << r)) != 0) {
200 Register reg = { r };
201 ExternalReference reg_addr =
202 ExternalReference(Debug_Address::Register(i));
203 mov(Operand::StaticVariable(reg_addr), reg);
204 }
205 }
206 }
207
208
209 void MacroAssembler::RestoreRegistersFromMemory(RegList regs) {
210 ASSERT((regs & ~kJSCallerSaved) == 0);
211 // Copy the content of memory location to registers.
212 for (int i = kNumJSCallerSaved; --i >= 0;) {
213 int r = JSCallerSavedCode(i);
214 if ((regs & (1 << r)) != 0) {
215 Register reg = { r };
216 ExternalReference reg_addr =
217 ExternalReference(Debug_Address::Register(i));
218 mov(reg, Operand::StaticVariable(reg_addr));
219 }
220 }
221 }
222
223
224 void MacroAssembler::PushRegistersFromMemory(RegList regs) {
225 ASSERT((regs & ~kJSCallerSaved) == 0);
226 // Push the content of the memory location to the stack.
227 for (int i = 0; i < kNumJSCallerSaved; i++) {
228 int r = JSCallerSavedCode(i);
229 if ((regs & (1 << r)) != 0) {
230 ExternalReference reg_addr =
231 ExternalReference(Debug_Address::Register(i));
232 push(Operand::StaticVariable(reg_addr));
233 }
234 }
235 }
236
237
238 void MacroAssembler::PopRegistersToMemory(RegList regs) {
239 ASSERT((regs & ~kJSCallerSaved) == 0);
240 // Pop the content from the stack to the memory location.
241 for (int i = kNumJSCallerSaved; --i >= 0;) {
242 int r = JSCallerSavedCode(i);
243 if ((regs & (1 << r)) != 0) {
244 ExternalReference reg_addr =
245 ExternalReference(Debug_Address::Register(i));
246 pop(Operand::StaticVariable(reg_addr));
247 }
248 }
249 }
250
251
252 void MacroAssembler::CopyRegistersFromStackToMemory(Register base,
253 Register scratch,
254 RegList regs) {
255 ASSERT((regs & ~kJSCallerSaved) == 0);
256 // Copy the content of the stack to the memory location and adjust base.
257 for (int i = kNumJSCallerSaved; --i >= 0;) {
258 int r = JSCallerSavedCode(i);
259 if ((regs & (1 << r)) != 0) {
260 mov(scratch, Operand(base, 0));
261 ExternalReference reg_addr =
262 ExternalReference(Debug_Address::Register(i));
263 mov(Operand::StaticVariable(reg_addr), scratch);
264 lea(base, Operand(base, kPointerSize));
265 }
266 }
267 }
268
269 void MacroAssembler::DebugBreak() { 194 void MacroAssembler::DebugBreak() {
270 Set(eax, Immediate(0)); 195 Set(eax, Immediate(0));
271 mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak))); 196 mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak)));
272 CEntryStub ces(1); 197 CEntryStub ces(1);
273 call(ces.GetCode(), RelocInfo::DEBUG_BREAK); 198 call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
274 } 199 }
275 #endif 200 #endif
276 201
202
277 void MacroAssembler::Set(Register dst, const Immediate& x) { 203 void MacroAssembler::Set(Register dst, const Immediate& x) {
278 if (x.is_zero()) { 204 if (x.is_zero()) {
279 xor_(dst, Operand(dst)); // shorter than mov 205 xor_(dst, Operand(dst)); // shorter than mov
280 } else { 206 } else {
281 mov(dst, x); 207 mov(dst, x);
282 } 208 }
283 } 209 }
284 210
285 211
286 void MacroAssembler::Set(const Operand& dst, const Immediate& x) { 212 void MacroAssembler::Set(const Operand& dst, const Immediate& x) {
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 324
399 void MacroAssembler::LeaveFrame(StackFrame::Type type) { 325 void MacroAssembler::LeaveFrame(StackFrame::Type type) {
400 if (FLAG_debug_code) { 326 if (FLAG_debug_code) {
401 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), 327 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset),
402 Immediate(Smi::FromInt(type))); 328 Immediate(Smi::FromInt(type)));
403 Check(equal, "stack frame types must match"); 329 Check(equal, "stack frame types must match");
404 } 330 }
405 leave(); 331 leave();
406 } 332 }
407 333
408 void MacroAssembler::EnterExitFramePrologue(ExitFrame::Mode mode) { 334
335 void MacroAssembler::EnterExitFramePrologue() {
409 // Setup the frame structure on the stack. 336 // Setup the frame structure on the stack.
410 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); 337 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
411 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); 338 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
412 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); 339 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize);
413 push(ebp); 340 push(ebp);
414 mov(ebp, Operand(esp)); 341 mov(ebp, Operand(esp));
415 342
416 // Reserve room for entry stack pointer and push the debug marker. 343 // Reserve room for entry stack pointer and push the code object.
417 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); 344 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
418 push(Immediate(0)); // Saved entry sp, patched before call. 345 push(Immediate(0)); // Saved entry sp, patched before call.
419 push(Immediate(CodeObject())); // Accessed from ExitFrame::code_slot. 346 push(Immediate(CodeObject())); // Accessed from ExitFrame::code_slot.
420 347
421 // Save the frame pointer and the context in top. 348 // Save the frame pointer and the context in top.
422 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); 349 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
423 ExternalReference context_address(Top::k_context_address); 350 ExternalReference context_address(Top::k_context_address);
424 mov(Operand::StaticVariable(c_entry_fp_address), ebp); 351 mov(Operand::StaticVariable(c_entry_fp_address), ebp);
425 mov(Operand::StaticVariable(context_address), esi); 352 mov(Operand::StaticVariable(context_address), esi);
426 } 353 }
427 354
428 void MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc) {
429 #ifdef ENABLE_DEBUGGER_SUPPORT
430 // Save the state of all registers to the stack from the memory
431 // location. This is needed to allow nested break points.
432 if (mode == ExitFrame::MODE_DEBUG) {
433 // TODO(1243899): This should be symmetric to
434 // CopyRegistersFromStackToMemory() but it isn't! esp is assumed
435 // correct here, but computed for the other call. Very error
436 // prone! FIX THIS. Actually there are deeper problems with
437 // register saving than this asymmetry (see the bug report
438 // associated with this issue).
439 PushRegistersFromMemory(kJSCallerSaved);
440 }
441 #endif
442 355
356 void MacroAssembler::EnterExitFrameEpilogue(int argc) {
443 // Reserve space for arguments. 357 // Reserve space for arguments.
444 sub(Operand(esp), Immediate(argc * kPointerSize)); 358 sub(Operand(esp), Immediate(argc * kPointerSize));
445 359
446 // Get the required frame alignment for the OS. 360 // Get the required frame alignment for the OS.
447 static const int kFrameAlignment = OS::ActivationFrameAlignment(); 361 static const int kFrameAlignment = OS::ActivationFrameAlignment();
448 if (kFrameAlignment > 0) { 362 if (kFrameAlignment > 0) {
449 ASSERT(IsPowerOf2(kFrameAlignment)); 363 ASSERT(IsPowerOf2(kFrameAlignment));
450 and_(esp, -kFrameAlignment); 364 and_(esp, -kFrameAlignment);
451 } 365 }
452 366
453 // Patch the saved entry sp. 367 // Patch the saved entry sp.
454 mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp); 368 mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp);
455 } 369 }
456 370
457 371
458 void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode) { 372 void MacroAssembler::EnterExitFrame() {
459 EnterExitFramePrologue(mode); 373 EnterExitFramePrologue();
460 374
461 // Setup argc and argv in callee-saved registers. 375 // Setup argc and argv in callee-saved registers.
462 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 376 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
463 mov(edi, Operand(eax)); 377 mov(edi, Operand(eax));
464 lea(esi, Operand(ebp, eax, times_4, offset)); 378 lea(esi, Operand(ebp, eax, times_4, offset));
465 379
466 EnterExitFrameEpilogue(mode, 2); 380 EnterExitFrameEpilogue(2);
467 } 381 }
468 382
469 383
470 void MacroAssembler::EnterApiExitFrame(ExitFrame::Mode mode, 384 void MacroAssembler::EnterApiExitFrame(int stack_space,
471 int stack_space,
472 int argc) { 385 int argc) {
473 EnterExitFramePrologue(mode); 386 EnterExitFramePrologue();
474 387
475 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 388 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
476 lea(esi, Operand(ebp, (stack_space * kPointerSize) + offset)); 389 lea(esi, Operand(ebp, (stack_space * kPointerSize) + offset));
477 390
478 EnterExitFrameEpilogue(mode, argc); 391 EnterExitFrameEpilogue(argc);
479 } 392 }
480 393
481 394
482 void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode) { 395 void MacroAssembler::LeaveExitFrame() {
483 #ifdef ENABLE_DEBUGGER_SUPPORT
484 // Restore the memory copy of the registers by digging them out from
485 // the stack. This is needed to allow nested break points.
486 if (mode == ExitFrame::MODE_DEBUG) {
487 // It's okay to clobber register ebx below because we don't need
488 // the function pointer after this.
489 const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
490 int kOffset = ExitFrameConstants::kCodeOffset - kCallerSavedSize;
491 lea(ebx, Operand(ebp, kOffset));
492 CopyRegistersFromStackToMemory(ebx, ecx, kJSCallerSaved);
493 }
494 #endif
495
496 // Get the return address from the stack and restore the frame pointer. 396 // Get the return address from the stack and restore the frame pointer.
497 mov(ecx, Operand(ebp, 1 * kPointerSize)); 397 mov(ecx, Operand(ebp, 1 * kPointerSize));
498 mov(ebp, Operand(ebp, 0 * kPointerSize)); 398 mov(ebp, Operand(ebp, 0 * kPointerSize));
499 399
500 // Pop the arguments and the receiver from the caller stack. 400 // Pop the arguments and the receiver from the caller stack.
501 lea(esp, Operand(esi, 1 * kPointerSize)); 401 lea(esp, Operand(esi, 1 * kPointerSize));
502 402
503 // Restore current context from top and clear it in debug mode. 403 // Restore current context from top and clear it in debug mode.
504 ExternalReference context_address(Top::k_context_address); 404 ExternalReference context_address(Top::k_context_address);
505 mov(esi, Operand::StaticVariable(context_address)); 405 mov(esi, Operand::StaticVariable(context_address));
(...skipping 1169 matching lines...) Expand 10 before | Expand all | Expand 10 after
1675 1575
1676 // Check that the code was patched as expected. 1576 // Check that the code was patched as expected.
1677 ASSERT(masm_.pc_ == address_ + size_); 1577 ASSERT(masm_.pc_ == address_ + size_);
1678 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 1578 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
1679 } 1579 }
1680 1580
1681 1581
1682 } } // namespace v8::internal 1582 } } // namespace v8::internal
1683 1583
1684 #endif // V8_TARGET_ARCH_IA32 1584 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.h ('k') | src/serialize.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698