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 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 | 348 |
349 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 349 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
350 if (FLAG_debug_code) { | 350 if (FLAG_debug_code) { |
351 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), | 351 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), |
352 Immediate(Smi::FromInt(type))); | 352 Immediate(Smi::FromInt(type))); |
353 Check(equal, "stack frame types must match"); | 353 Check(equal, "stack frame types must match"); |
354 } | 354 } |
355 leave(); | 355 leave(); |
356 } | 356 } |
357 | 357 |
358 | 358 void MacroAssembler::EnterExitFramePrologue(ExitFrame::Mode mode) { |
359 void MacroAssembler::EnterExitFrame(StackFrame::Type type) { | |
360 ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG); | |
361 | |
362 // Setup the frame structure on the stack. | 359 // Setup the frame structure on the stack. |
363 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); | 360 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); |
364 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); | 361 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); |
365 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); | 362 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); |
366 push(ebp); | 363 push(ebp); |
367 mov(ebp, Operand(esp)); | 364 mov(ebp, Operand(esp)); |
368 | 365 |
369 // Reserve room for entry stack pointer and push the debug marker. | 366 // Reserve room for entry stack pointer and push the debug marker. |
370 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); | 367 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); |
371 push(Immediate(0)); // saved entry sp, patched before call | 368 push(Immediate(0)); // saved entry sp, patched before call |
372 push(Immediate(type == StackFrame::EXIT_DEBUG ? 1 : 0)); | 369 if (mode == ExitFrame::MODE_DEBUG) { |
| 370 push(Immediate(0)); |
| 371 } else { |
| 372 push(Immediate(CodeObject())); |
| 373 } |
373 | 374 |
374 // Save the frame pointer and the context in top. | 375 // Save the frame pointer and the context in top. |
375 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); | 376 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); |
376 ExternalReference context_address(Top::k_context_address); | 377 ExternalReference context_address(Top::k_context_address); |
377 mov(Operand::StaticVariable(c_entry_fp_address), ebp); | 378 mov(Operand::StaticVariable(c_entry_fp_address), ebp); |
378 mov(Operand::StaticVariable(context_address), esi); | 379 mov(Operand::StaticVariable(context_address), esi); |
| 380 } |
379 | 381 |
380 // Setup argc and argv in callee-saved registers. | 382 void MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc) { |
381 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; | |
382 mov(edi, Operand(eax)); | |
383 lea(esi, Operand(ebp, eax, times_4, offset)); | |
384 | |
385 #ifdef ENABLE_DEBUGGER_SUPPORT | 383 #ifdef ENABLE_DEBUGGER_SUPPORT |
386 // Save the state of all registers to the stack from the memory | 384 // Save the state of all registers to the stack from the memory |
387 // location. This is needed to allow nested break points. | 385 // location. This is needed to allow nested break points. |
388 if (type == StackFrame::EXIT_DEBUG) { | 386 if (mode == ExitFrame::MODE_DEBUG) { |
389 // TODO(1243899): This should be symmetric to | 387 // TODO(1243899): This should be symmetric to |
390 // CopyRegistersFromStackToMemory() but it isn't! esp is assumed | 388 // CopyRegistersFromStackToMemory() but it isn't! esp is assumed |
391 // correct here, but computed for the other call. Very error | 389 // correct here, but computed for the other call. Very error |
392 // prone! FIX THIS. Actually there are deeper problems with | 390 // prone! FIX THIS. Actually there are deeper problems with |
393 // register saving than this asymmetry (see the bug report | 391 // register saving than this asymmetry (see the bug report |
394 // associated with this issue). | 392 // associated with this issue). |
395 PushRegistersFromMemory(kJSCallerSaved); | 393 PushRegistersFromMemory(kJSCallerSaved); |
396 } | 394 } |
397 #endif | 395 #endif |
398 | 396 |
399 // Reserve space for two arguments: argc and argv. | 397 // Reserve space for arguments. |
400 sub(Operand(esp), Immediate(2 * kPointerSize)); | 398 sub(Operand(esp), Immediate(argc * kPointerSize)); |
401 | 399 |
402 // Get the required frame alignment for the OS. | 400 // Get the required frame alignment for the OS. |
403 static const int kFrameAlignment = OS::ActivationFrameAlignment(); | 401 static const int kFrameAlignment = OS::ActivationFrameAlignment(); |
404 if (kFrameAlignment > 0) { | 402 if (kFrameAlignment > 0) { |
405 ASSERT(IsPowerOf2(kFrameAlignment)); | 403 ASSERT(IsPowerOf2(kFrameAlignment)); |
406 and_(esp, -kFrameAlignment); | 404 and_(esp, -kFrameAlignment); |
407 } | 405 } |
408 | 406 |
409 // Patch the saved entry sp. | 407 // Patch the saved entry sp. |
410 mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp); | 408 mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp); |
411 } | 409 } |
412 | 410 |
413 | 411 |
414 void MacroAssembler::LeaveExitFrame(StackFrame::Type type) { | 412 void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode) { |
| 413 EnterExitFramePrologue(mode); |
| 414 |
| 415 // Setup argc and argv in callee-saved registers. |
| 416 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; |
| 417 mov(edi, Operand(eax)); |
| 418 lea(esi, Operand(ebp, eax, times_4, offset)); |
| 419 |
| 420 EnterExitFrameEpilogue(mode, 2); |
| 421 } |
| 422 |
| 423 |
| 424 void MacroAssembler::EnterApiExitFrame(ExitFrame::Mode mode, |
| 425 int stack_space, |
| 426 int argc) { |
| 427 EnterExitFramePrologue(mode); |
| 428 |
| 429 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; |
| 430 lea(esi, Operand(ebp, (stack_space * kPointerSize) + offset)); |
| 431 |
| 432 EnterExitFrameEpilogue(mode, argc); |
| 433 } |
| 434 |
| 435 |
| 436 void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode) { |
415 #ifdef ENABLE_DEBUGGER_SUPPORT | 437 #ifdef ENABLE_DEBUGGER_SUPPORT |
416 // Restore the memory copy of the registers by digging them out from | 438 // Restore the memory copy of the registers by digging them out from |
417 // the stack. This is needed to allow nested break points. | 439 // the stack. This is needed to allow nested break points. |
418 if (type == StackFrame::EXIT_DEBUG) { | 440 if (mode == ExitFrame::MODE_DEBUG) { |
419 // It's okay to clobber register ebx below because we don't need | 441 // It's okay to clobber register ebx below because we don't need |
420 // the function pointer after this. | 442 // the function pointer after this. |
421 const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize; | 443 const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize; |
422 int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize; | 444 int kOffset = ExitFrameConstants::kCodeOffset - kCallerSavedSize; |
423 lea(ebx, Operand(ebp, kOffset)); | 445 lea(ebx, Operand(ebp, kOffset)); |
424 CopyRegistersFromStackToMemory(ebx, ecx, kJSCallerSaved); | 446 CopyRegistersFromStackToMemory(ebx, ecx, kJSCallerSaved); |
425 } | 447 } |
426 #endif | 448 #endif |
427 | 449 |
428 // Get the return address from the stack and restore the frame pointer. | 450 // Get the return address from the stack and restore the frame pointer. |
429 mov(ecx, Operand(ebp, 1 * kPointerSize)); | 451 mov(ecx, Operand(ebp, 1 * kPointerSize)); |
430 mov(ebp, Operand(ebp, 0 * kPointerSize)); | 452 mov(ebp, Operand(ebp, 0 * kPointerSize)); |
431 | 453 |
432 // Pop the arguments and the receiver from the caller stack. | 454 // Pop the arguments and the receiver from the caller stack. |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
924 int result_size) { | 946 int result_size) { |
925 // TODO(1236192): Most runtime routines don't need the number of | 947 // TODO(1236192): Most runtime routines don't need the number of |
926 // arguments passed in because it is constant. At some point we | 948 // arguments passed in because it is constant. At some point we |
927 // should remove this need and make the runtime routine entry code | 949 // should remove this need and make the runtime routine entry code |
928 // smarter. | 950 // smarter. |
929 Set(eax, Immediate(num_arguments)); | 951 Set(eax, Immediate(num_arguments)); |
930 JumpToRuntime(ext); | 952 JumpToRuntime(ext); |
931 } | 953 } |
932 | 954 |
933 | 955 |
| 956 void MacroAssembler::PushHandleScope(Register scratch) { |
| 957 // Push the number of extensions, smi-tagged so the gc will ignore it. |
| 958 ExternalReference extensions_address = |
| 959 ExternalReference::handle_scope_extensions_address(); |
| 960 mov(scratch, Operand::StaticVariable(extensions_address)); |
| 961 ASSERT_EQ(0, kSmiTag); |
| 962 shl(scratch, kSmiTagSize); |
| 963 push(scratch); |
| 964 mov(Operand::StaticVariable(extensions_address), Immediate(0)); |
| 965 // Push next and limit pointers which will be wordsize aligned and |
| 966 // hence automatically smi tagged. |
| 967 ExternalReference next_address = |
| 968 ExternalReference::handle_scope_next_address(); |
| 969 push(Operand::StaticVariable(next_address)); |
| 970 ExternalReference limit_address = |
| 971 ExternalReference::handle_scope_limit_address(); |
| 972 push(Operand::StaticVariable(limit_address)); |
| 973 } |
| 974 |
| 975 |
| 976 void MacroAssembler::PopHandleScope(Register scratch) { |
| 977 ExternalReference extensions_address = |
| 978 ExternalReference::handle_scope_extensions_address(); |
| 979 Label write_back; |
| 980 mov(scratch, Operand::StaticVariable(extensions_address)); |
| 981 cmp(Operand(scratch), Immediate(0)); |
| 982 j(equal, &write_back); |
| 983 CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); |
| 984 |
| 985 bind(&write_back); |
| 986 ExternalReference limit_address = |
| 987 ExternalReference::handle_scope_limit_address(); |
| 988 pop(Operand::StaticVariable(limit_address)); |
| 989 ExternalReference next_address = |
| 990 ExternalReference::handle_scope_next_address(); |
| 991 pop(Operand::StaticVariable(next_address)); |
| 992 pop(scratch); |
| 993 shr(scratch, kSmiTagSize); |
| 994 mov(Operand::StaticVariable(extensions_address), scratch); |
| 995 } |
| 996 |
| 997 |
934 void MacroAssembler::JumpToRuntime(const ExternalReference& ext) { | 998 void MacroAssembler::JumpToRuntime(const ExternalReference& ext) { |
935 // Set the entry point and jump to the C entry runtime stub. | 999 // Set the entry point and jump to the C entry runtime stub. |
936 mov(ebx, Immediate(ext)); | 1000 mov(ebx, Immediate(ext)); |
937 CEntryStub ces(1); | 1001 CEntryStub ces(1); |
938 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); | 1002 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); |
939 } | 1003 } |
940 | 1004 |
941 | 1005 |
942 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 1006 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
943 const ParameterCount& actual, | 1007 const ParameterCount& actual, |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1205 // Indicate that code has changed. | 1269 // Indicate that code has changed. |
1206 CPU::FlushICache(address_, size_); | 1270 CPU::FlushICache(address_, size_); |
1207 | 1271 |
1208 // Check that the code was patched as expected. | 1272 // Check that the code was patched as expected. |
1209 ASSERT(masm_.pc_ == address_ + size_); | 1273 ASSERT(masm_.pc_ == address_ + size_); |
1210 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 1274 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
1211 } | 1275 } |
1212 | 1276 |
1213 | 1277 |
1214 } } // namespace v8::internal | 1278 } } // namespace v8::internal |
OLD | NEW |