OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |