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