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