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

Side by Side Diff: src/x64/macro-assembler-x64.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/x64/macro-assembler-x64.h ('k') | test/cctest/cctest.status » ('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 2009 the V8 project authors. All rights reserved. 1 // Copyright 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 2084 matching lines...) Expand 10 before | Expand all | Expand 10 after
2095 movq(kScratchRegister, ExternalReference(counter)); 2095 movq(kScratchRegister, ExternalReference(counter));
2096 Operand operand(kScratchRegister, 0); 2096 Operand operand(kScratchRegister, 0);
2097 if (value == 1) { 2097 if (value == 1) {
2098 decl(operand); 2098 decl(operand);
2099 } else { 2099 } else {
2100 subl(operand, Immediate(value)); 2100 subl(operand, Immediate(value));
2101 } 2101 }
2102 } 2102 }
2103 } 2103 }
2104 2104
2105 #ifdef ENABLE_DEBUGGER_SUPPORT
2106
2107 void MacroAssembler::PushRegistersFromMemory(RegList regs) {
2108 ASSERT((regs & ~kJSCallerSaved) == 0);
2109 // Push the content of the memory location to the stack.
2110 for (int i = 0; i < kNumJSCallerSaved; i++) {
2111 int r = JSCallerSavedCode(i);
2112 if ((regs & (1 << r)) != 0) {
2113 ExternalReference reg_addr =
2114 ExternalReference(Debug_Address::Register(i));
2115 movq(kScratchRegister, reg_addr);
2116 push(Operand(kScratchRegister, 0));
2117 }
2118 }
2119 }
2120
2121 2105
2122 void MacroAssembler::SaveRegistersToMemory(RegList regs) { 2106 #ifdef ENABLE_DEBUGGER_SUPPORT
2123 ASSERT((regs & ~kJSCallerSaved) == 0);
2124 // Copy the content of registers to memory location.
2125 for (int i = 0; i < kNumJSCallerSaved; i++) {
2126 int r = JSCallerSavedCode(i);
2127 if ((regs & (1 << r)) != 0) {
2128 Register reg = { r };
2129 ExternalReference reg_addr =
2130 ExternalReference(Debug_Address::Register(i));
2131 movq(kScratchRegister, reg_addr);
2132 movq(Operand(kScratchRegister, 0), reg);
2133 }
2134 }
2135 }
2136
2137
2138 void MacroAssembler::RestoreRegistersFromMemory(RegList regs) {
2139 ASSERT((regs & ~kJSCallerSaved) == 0);
2140 // Copy the content of memory location to registers.
2141 for (int i = kNumJSCallerSaved - 1; i >= 0; i--) {
2142 int r = JSCallerSavedCode(i);
2143 if ((regs & (1 << r)) != 0) {
2144 Register reg = { r };
2145 ExternalReference reg_addr =
2146 ExternalReference(Debug_Address::Register(i));
2147 movq(kScratchRegister, reg_addr);
2148 movq(reg, Operand(kScratchRegister, 0));
2149 }
2150 }
2151 }
2152
2153
2154 void MacroAssembler::PopRegistersToMemory(RegList regs) {
2155 ASSERT((regs & ~kJSCallerSaved) == 0);
2156 // Pop the content from the stack to the memory location.
2157 for (int i = kNumJSCallerSaved - 1; i >= 0; i--) {
2158 int r = JSCallerSavedCode(i);
2159 if ((regs & (1 << r)) != 0) {
2160 ExternalReference reg_addr =
2161 ExternalReference(Debug_Address::Register(i));
2162 movq(kScratchRegister, reg_addr);
2163 pop(Operand(kScratchRegister, 0));
2164 }
2165 }
2166 }
2167
2168
2169 void MacroAssembler::CopyRegistersFromStackToMemory(Register base,
2170 Register scratch,
2171 RegList regs) {
2172 ASSERT(!scratch.is(kScratchRegister));
2173 ASSERT(!base.is(kScratchRegister));
2174 ASSERT(!base.is(scratch));
2175 ASSERT((regs & ~kJSCallerSaved) == 0);
2176 // Copy the content of the stack to the memory location and adjust base.
2177 for (int i = kNumJSCallerSaved - 1; i >= 0; i--) {
2178 int r = JSCallerSavedCode(i);
2179 if ((regs & (1 << r)) != 0) {
2180 movq(scratch, Operand(base, 0));
2181 ExternalReference reg_addr =
2182 ExternalReference(Debug_Address::Register(i));
2183 movq(kScratchRegister, reg_addr);
2184 movq(Operand(kScratchRegister, 0), scratch);
2185 lea(base, Operand(base, kPointerSize));
2186 }
2187 }
2188 }
2189
2190 void MacroAssembler::DebugBreak() { 2107 void MacroAssembler::DebugBreak() {
2191 ASSERT(allow_stub_calls()); 2108 ASSERT(allow_stub_calls());
2192 xor_(rax, rax); // no arguments 2109 xor_(rax, rax); // no arguments
2193 movq(rbx, ExternalReference(Runtime::kDebugBreak)); 2110 movq(rbx, ExternalReference(Runtime::kDebugBreak));
2194 CEntryStub ces(1); 2111 CEntryStub ces(1);
2195 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); 2112 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
2196 } 2113 }
2197 #endif // ENABLE_DEBUGGER_SUPPORT 2114 #endif // ENABLE_DEBUGGER_SUPPORT
2198 2115
2199 2116
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
2349 if (FLAG_debug_code) { 2266 if (FLAG_debug_code) {
2350 Move(kScratchRegister, Smi::FromInt(type)); 2267 Move(kScratchRegister, Smi::FromInt(type));
2351 cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); 2268 cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister);
2352 Check(equal, "stack frame types must match"); 2269 Check(equal, "stack frame types must match");
2353 } 2270 }
2354 movq(rsp, rbp); 2271 movq(rsp, rbp);
2355 pop(rbp); 2272 pop(rbp);
2356 } 2273 }
2357 2274
2358 2275
2359 void MacroAssembler::EnterExitFramePrologue(ExitFrame::Mode mode, 2276 void MacroAssembler::EnterExitFramePrologue(bool save_rax) {
2360 bool save_rax) {
2361 // Setup the frame structure on the stack. 2277 // Setup the frame structure on the stack.
2362 // All constants are relative to the frame pointer of the exit frame. 2278 // All constants are relative to the frame pointer of the exit frame.
2363 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); 2279 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
2364 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); 2280 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
2365 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); 2281 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize);
2366 push(rbp); 2282 push(rbp);
2367 movq(rbp, rsp); 2283 movq(rbp, rsp);
2368 2284
2369 // Reserve room for entry stack pointer and push the debug marker. 2285 // Reserve room for entry stack pointer and push the code object.
2370 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); 2286 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
2371 push(Immediate(0)); // Saved entry sp, patched before call. 2287 push(Immediate(0)); // Saved entry sp, patched before call.
2372 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); 2288 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
2373 push(kScratchRegister); // Accessed from EditFrame::code_slot. 2289 push(kScratchRegister); // Accessed from EditFrame::code_slot.
2374 2290
2375 // Save the frame pointer and the context in top. 2291 // Save the frame pointer and the context in top.
2376 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); 2292 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
2377 ExternalReference context_address(Top::k_context_address); 2293 ExternalReference context_address(Top::k_context_address);
2378 if (save_rax) { 2294 if (save_rax) {
2379 movq(r14, rax); // Backup rax before we use it. 2295 movq(r14, rax); // Backup rax before we use it.
2380 } 2296 }
2381 2297
2382 movq(rax, rbp); 2298 movq(rax, rbp);
2383 store_rax(c_entry_fp_address); 2299 store_rax(c_entry_fp_address);
2384 movq(rax, rsi); 2300 movq(rax, rsi);
2385 store_rax(context_address); 2301 store_rax(context_address);
2386 } 2302 }
2387 2303
2388 void MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode, 2304 void MacroAssembler::EnterExitFrameEpilogue(int result_size,
2389 int result_size,
2390 int argc) { 2305 int argc) {
2391 #ifdef ENABLE_DEBUGGER_SUPPORT
2392 // Save the state of all registers to the stack from the memory
2393 // location. This is needed to allow nested break points.
2394 if (mode == ExitFrame::MODE_DEBUG) {
2395 // TODO(1243899): This should be symmetric to
2396 // CopyRegistersFromStackToMemory() but it isn't! esp is assumed
2397 // correct here, but computed for the other call. Very error
2398 // prone! FIX THIS. Actually there are deeper problems with
2399 // register saving than this asymmetry (see the bug report
2400 // associated with this issue).
2401 PushRegistersFromMemory(kJSCallerSaved);
2402 }
2403 #endif
2404
2405 #ifdef _WIN64 2306 #ifdef _WIN64
2406 // Reserve space on stack for result and argument structures, if necessary. 2307 // Reserve space on stack for result and argument structures, if necessary.
2407 int result_stack_space = (result_size < 2) ? 0 : result_size * kPointerSize; 2308 int result_stack_space = (result_size < 2) ? 0 : result_size * kPointerSize;
2408 // Reserve space for the Arguments object. The Windows 64-bit ABI 2309 // Reserve space for the Arguments object. The Windows 64-bit ABI
2409 // requires us to pass this structure as a pointer to its location on 2310 // requires us to pass this structure as a pointer to its location on
2410 // the stack. The structure contains 2 values. 2311 // the stack. The structure contains 2 values.
2411 int argument_stack_space = argc * kPointerSize; 2312 int argument_stack_space = argc * kPointerSize;
2412 // We also need backing space for 4 parameters, even though 2313 // We also need backing space for 4 parameters, even though
2413 // we only pass one or two parameter, and it is in a register. 2314 // we only pass one or two parameter, and it is in a register.
2414 int argument_mirror_space = 4 * kPointerSize; 2315 int argument_mirror_space = 4 * kPointerSize;
2415 int total_stack_space = 2316 int total_stack_space =
2416 argument_mirror_space + argument_stack_space + result_stack_space; 2317 argument_mirror_space + argument_stack_space + result_stack_space;
2417 subq(rsp, Immediate(total_stack_space)); 2318 subq(rsp, Immediate(total_stack_space));
2418 #endif 2319 #endif
2419 2320
2420 // Get the required frame alignment for the OS. 2321 // Get the required frame alignment for the OS.
2421 static const int kFrameAlignment = OS::ActivationFrameAlignment(); 2322 static const int kFrameAlignment = OS::ActivationFrameAlignment();
2422 if (kFrameAlignment > 0) { 2323 if (kFrameAlignment > 0) {
2423 ASSERT(IsPowerOf2(kFrameAlignment)); 2324 ASSERT(IsPowerOf2(kFrameAlignment));
2424 movq(kScratchRegister, Immediate(-kFrameAlignment)); 2325 movq(kScratchRegister, Immediate(-kFrameAlignment));
2425 and_(rsp, kScratchRegister); 2326 and_(rsp, kScratchRegister);
2426 } 2327 }
2427 2328
2428 // Patch the saved entry sp. 2329 // Patch the saved entry sp.
2429 movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp); 2330 movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp);
2430 } 2331 }
2431 2332
2432 2333
2433 void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) { 2334 void MacroAssembler::EnterExitFrame(int result_size) {
2434 EnterExitFramePrologue(mode, true); 2335 EnterExitFramePrologue(true);
2435 2336
2436 // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame, 2337 // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
2437 // so it must be retained across the C-call. 2338 // so it must be retained across the C-call.
2438 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 2339 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
2439 lea(r12, Operand(rbp, r14, times_pointer_size, offset)); 2340 lea(r12, Operand(rbp, r14, times_pointer_size, offset));
2440 2341
2441 EnterExitFrameEpilogue(mode, result_size, 2); 2342 EnterExitFrameEpilogue(result_size, 2);
2442 } 2343 }
2443 2344
2444 2345
2445 void MacroAssembler::EnterApiExitFrame(ExitFrame::Mode mode, 2346 void MacroAssembler::EnterApiExitFrame(int stack_space,
2446 int stack_space,
2447 int argc, 2347 int argc,
2448 int result_size) { 2348 int result_size) {
2449 EnterExitFramePrologue(mode, false); 2349 EnterExitFramePrologue(false);
2450 2350
2451 // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame, 2351 // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
2452 // so it must be retained across the C-call. 2352 // so it must be retained across the C-call.
2453 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; 2353 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
2454 lea(r12, Operand(rbp, (stack_space * kPointerSize) + offset)); 2354 lea(r12, Operand(rbp, (stack_space * kPointerSize) + offset));
2455 2355
2456 EnterExitFrameEpilogue(mode, result_size, argc); 2356 EnterExitFrameEpilogue(result_size, argc);
2457 } 2357 }
2458 2358
2459 2359
2460 void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode, int result_size) { 2360 void MacroAssembler::LeaveExitFrame(int result_size) {
2461 // Registers: 2361 // Registers:
2462 // r12 : argv 2362 // r12 : argv
2463 #ifdef ENABLE_DEBUGGER_SUPPORT
2464 // Restore the memory copy of the registers by digging them out from
2465 // the stack. This is needed to allow nested break points.
2466 if (mode == ExitFrame::MODE_DEBUG) {
2467 // It's okay to clobber register rbx below because we don't need
2468 // the function pointer after this.
2469 const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
2470 int kOffset = ExitFrameConstants::kCodeOffset - kCallerSavedSize;
2471 lea(rbx, Operand(rbp, kOffset));
2472 CopyRegistersFromStackToMemory(rbx, rcx, kJSCallerSaved);
2473 }
2474 #endif
2475 2363
2476 // Get the return address from the stack and restore the frame pointer. 2364 // Get the return address from the stack and restore the frame pointer.
2477 movq(rcx, Operand(rbp, 1 * kPointerSize)); 2365 movq(rcx, Operand(rbp, 1 * kPointerSize));
2478 movq(rbp, Operand(rbp, 0 * kPointerSize)); 2366 movq(rbp, Operand(rbp, 0 * kPointerSize));
2479 2367
2480 // Pop everything up to and including the arguments and the receiver 2368 // Pop everything up to and including the arguments and the receiver
2481 // from the caller stack. 2369 // from the caller stack.
2482 lea(rsp, Operand(r12, 1 * kPointerSize)); 2370 lea(rsp, Operand(r12, 1 * kPointerSize));
2483 2371
2484 // Restore current context from top and clear it in debug mode. 2372 // Restore current context from top and clear it in debug mode.
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
2961 CPU::FlushICache(address_, size_); 2849 CPU::FlushICache(address_, size_);
2962 2850
2963 // Check that the code was patched as expected. 2851 // Check that the code was patched as expected.
2964 ASSERT(masm_.pc_ == address_ + size_); 2852 ASSERT(masm_.pc_ == address_ + size_);
2965 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 2853 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2966 } 2854 }
2967 2855
2968 } } // namespace v8::internal 2856 } } // namespace v8::internal
2969 2857
2970 #endif // V8_TARGET_ARCH_X64 2858 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/macro-assembler-x64.h ('k') | test/cctest/cctest.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698