| 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 |