OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
8 | 8 |
9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 __ mov(ebx, Operand(esp, 0)); | 567 __ mov(ebx, Operand(esp, 0)); |
568 } | 568 } |
569 | 569 |
570 __ pop(ecx); // Return address. | 570 __ pop(ecx); // Return address. |
571 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); | 571 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); |
572 __ push(ecx); | 572 __ push(ecx); |
573 __ ret(0); | 573 __ ret(0); |
574 } | 574 } |
575 | 575 |
576 | 576 |
| 577 enum IsTagged { kEaxIsSmiTagged, kEaxIsUntaggedInt }; |
| 578 |
| 579 |
| 580 // Clobbers ecx, edx, edi; preserves all other registers. |
| 581 static void Generate_CheckStackOverflow(MacroAssembler* masm, |
| 582 const int calleeOffset, |
| 583 IsTagged eax_is_tagged) { |
| 584 // eax : the number of items to be pushed to the stack |
| 585 // |
| 586 // Check the stack for overflow. We are not trying to catch |
| 587 // interruptions (e.g. debug break and preemption) here, so the "real stack |
| 588 // limit" is checked. |
| 589 Label okay; |
| 590 ExternalReference real_stack_limit = |
| 591 ExternalReference::address_of_real_stack_limit(masm->isolate()); |
| 592 __ mov(edi, Operand::StaticVariable(real_stack_limit)); |
| 593 // Make ecx the space we have left. The stack might already be overflowed |
| 594 // here which will cause ecx to become negative. |
| 595 __ mov(ecx, esp); |
| 596 __ sub(ecx, edi); |
| 597 // Make edx the space we need for the array when it is unrolled onto the |
| 598 // stack. |
| 599 __ mov(edx, eax); |
| 600 int smi_tag = eax_is_tagged == kEaxIsSmiTagged ? kSmiTagSize : 0; |
| 601 __ shl(edx, kPointerSizeLog2 - smi_tag); |
| 602 // Check if the arguments will overflow the stack. |
| 603 __ cmp(ecx, edx); |
| 604 __ j(greater, &okay); // Signed comparison. |
| 605 |
| 606 // Out of stack space. |
| 607 __ push(Operand(ebp, calleeOffset)); // push this |
| 608 if (eax_is_tagged == kEaxIsUntaggedInt) { |
| 609 __ SmiTag(eax); |
| 610 } |
| 611 __ push(eax); |
| 612 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); |
| 613 |
| 614 __ bind(&okay); |
| 615 } |
| 616 |
| 617 |
577 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 618 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
578 bool is_construct) { | 619 bool is_construct) { |
579 ProfileEntryHookStub::MaybeCallEntryHook(masm); | 620 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
580 | 621 |
581 // Clear the context before we push it when entering the internal frame. | 622 // Clear the context before we push it when entering the internal frame. |
582 __ Move(esi, Immediate(0)); | 623 __ Move(esi, Immediate(0)); |
583 | 624 |
584 { | 625 { |
585 FrameScope scope(masm, StackFrame::INTERNAL); | 626 FrameScope scope(masm, StackFrame::INTERNAL); |
586 | 627 |
587 // Load the previous frame pointer (ebx) to access C arguments | 628 // Load the previous frame pointer (ebx) to access C arguments |
588 __ mov(ebx, Operand(ebp, 0)); | 629 __ mov(ebx, Operand(ebp, 0)); |
589 | 630 |
590 // Get the function from the frame and setup the context. | 631 // Get the function from the frame and setup the context. |
591 __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); | 632 __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); |
592 __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset)); | 633 __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset)); |
593 | 634 |
594 // Push the function and the receiver onto the stack. | 635 // Push the function and the receiver onto the stack. |
595 __ push(ecx); | 636 __ push(ecx); |
596 __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset)); | 637 __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset)); |
597 | 638 |
598 // Load the number of arguments and setup pointer to the arguments. | 639 // Load the number of arguments and setup pointer to the arguments. |
599 __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset)); | 640 __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset)); |
600 __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset)); | 641 __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset)); |
601 | 642 |
| 643 // Check if we have enough stack space to push all arguments. |
| 644 // The function is the first thing that was pushed above after entering |
| 645 // the internal frame. |
| 646 const int kFunctionOffset = |
| 647 InternalFrameConstants::kCodeOffset - kPointerSize; |
| 648 // Expects argument count in eax. Clobbers ecx, edx, edi. |
| 649 Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsUntaggedInt); |
| 650 |
602 // Copy arguments to the stack in a loop. | 651 // Copy arguments to the stack in a loop. |
603 Label loop, entry; | 652 Label loop, entry; |
604 __ Move(ecx, Immediate(0)); | 653 __ Move(ecx, Immediate(0)); |
605 __ jmp(&entry); | 654 __ jmp(&entry); |
606 __ bind(&loop); | 655 __ bind(&loop); |
607 __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv | 656 __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv |
608 __ push(Operand(edx, 0)); // dereference handle | 657 __ push(Operand(edx, 0)); // dereference handle |
609 __ inc(ecx); | 658 __ inc(ecx); |
610 __ bind(&entry); | 659 __ bind(&entry); |
611 __ cmp(ecx, eax); | 660 __ cmp(ecx, eax); |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
983 __ SmiUntag(ebx); | 1032 __ SmiUntag(ebx); |
984 __ cmp(eax, ebx); | 1033 __ cmp(eax, ebx); |
985 __ j(not_equal, | 1034 __ j(not_equal, |
986 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline()); | 1035 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline()); |
987 | 1036 |
988 ParameterCount expected(0); | 1037 ParameterCount expected(0); |
989 __ InvokeCode(edx, expected, expected, JUMP_FUNCTION, NullCallWrapper()); | 1038 __ InvokeCode(edx, expected, expected, JUMP_FUNCTION, NullCallWrapper()); |
990 } | 1039 } |
991 | 1040 |
992 | 1041 |
993 static void Generate_CheckStackOverflow(MacroAssembler* masm, | |
994 const int calleeOffset) { | |
995 // eax : the number of items to be pushed to the stack | |
996 // | |
997 // Check the stack for overflow. We are not trying to catch | |
998 // interruptions (e.g. debug break and preemption) here, so the "real stack | |
999 // limit" is checked. | |
1000 Label okay; | |
1001 ExternalReference real_stack_limit = | |
1002 ExternalReference::address_of_real_stack_limit(masm->isolate()); | |
1003 __ mov(edi, Operand::StaticVariable(real_stack_limit)); | |
1004 // Make ecx the space we have left. The stack might already be overflowed | |
1005 // here which will cause ecx to become negative. | |
1006 __ mov(ecx, esp); | |
1007 __ sub(ecx, edi); | |
1008 // Make edx the space we need for the array when it is unrolled onto the | |
1009 // stack. | |
1010 __ mov(edx, eax); | |
1011 __ shl(edx, kPointerSizeLog2 - kSmiTagSize); | |
1012 // Check if the arguments will overflow the stack. | |
1013 __ cmp(ecx, edx); | |
1014 __ j(greater, &okay); // Signed comparison. | |
1015 | |
1016 // Out of stack space. | |
1017 __ push(Operand(ebp, calleeOffset)); // push this | |
1018 __ push(eax); | |
1019 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); | |
1020 | |
1021 __ bind(&okay); | |
1022 } | |
1023 | |
1024 | |
1025 static void Generate_PushAppliedArguments(MacroAssembler* masm, | 1042 static void Generate_PushAppliedArguments(MacroAssembler* masm, |
1026 const int argumentsOffset, | 1043 const int argumentsOffset, |
1027 const int indexOffset, | 1044 const int indexOffset, |
1028 const int limitOffset) { | 1045 const int limitOffset) { |
1029 // Copy all arguments from the array to the stack. | 1046 // Copy all arguments from the array to the stack. |
1030 Label entry, loop; | 1047 Label entry, loop; |
1031 Register receiver = LoadDescriptor::ReceiverRegister(); | 1048 Register receiver = LoadDescriptor::ReceiverRegister(); |
1032 Register key = LoadDescriptor::NameRegister(); | 1049 Register key = LoadDescriptor::NameRegister(); |
1033 __ mov(key, Operand(ebp, indexOffset)); | 1050 __ mov(key, Operand(ebp, indexOffset)); |
1034 __ jmp(&entry); | 1051 __ jmp(&entry); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1092 static const int kFunctionOffset = kReceiverOffset + kPointerSize; | 1109 static const int kFunctionOffset = kReceiverOffset + kPointerSize; |
1093 | 1110 |
1094 __ push(Operand(ebp, kFunctionOffset)); // push this | 1111 __ push(Operand(ebp, kFunctionOffset)); // push this |
1095 __ push(Operand(ebp, kArgumentsOffset)); // push arguments | 1112 __ push(Operand(ebp, kArgumentsOffset)); // push arguments |
1096 if (targetIsArgument) { | 1113 if (targetIsArgument) { |
1097 __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION); | 1114 __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION); |
1098 } else { | 1115 } else { |
1099 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); | 1116 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); |
1100 } | 1117 } |
1101 | 1118 |
1102 Generate_CheckStackOverflow(masm, kFunctionOffset); | 1119 Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsSmiTagged); |
1103 | 1120 |
1104 // Push current index and limit. | 1121 // Push current index and limit. |
1105 const int kLimitOffset = | 1122 const int kLimitOffset = |
1106 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; | 1123 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; |
1107 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; | 1124 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; |
1108 __ push(eax); // limit | 1125 __ push(eax); // limit |
1109 __ push(Immediate(0)); // index | 1126 __ push(Immediate(0)); // index |
1110 | 1127 |
1111 // Get the receiver. | 1128 // Get the receiver. |
1112 __ mov(ebx, Operand(ebp, kReceiverOffset)); | 1129 __ mov(ebx, Operand(ebp, kReceiverOffset)); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1222 __ mov(eax, Operand(ebp, kFunctionOffset)); | 1239 __ mov(eax, Operand(ebp, kFunctionOffset)); |
1223 __ mov(Operand(ebp, kNewTargetOffset), eax); | 1240 __ mov(Operand(ebp, kNewTargetOffset), eax); |
1224 | 1241 |
1225 // Validate arguments | 1242 // Validate arguments |
1226 __ bind(&validate_arguments); | 1243 __ bind(&validate_arguments); |
1227 __ push(Operand(ebp, kFunctionOffset)); | 1244 __ push(Operand(ebp, kFunctionOffset)); |
1228 __ push(Operand(ebp, kArgumentsOffset)); | 1245 __ push(Operand(ebp, kArgumentsOffset)); |
1229 __ push(Operand(ebp, kNewTargetOffset)); | 1246 __ push(Operand(ebp, kNewTargetOffset)); |
1230 __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION); | 1247 __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION); |
1231 | 1248 |
1232 Generate_CheckStackOverflow(masm, kFunctionOffset); | 1249 Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsSmiTagged); |
1233 | 1250 |
1234 // Push current index and limit. | 1251 // Push current index and limit. |
1235 const int kLimitOffset = | 1252 const int kLimitOffset = |
1236 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; | 1253 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; |
1237 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; | 1254 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; |
1238 __ Push(eax); // limit | 1255 __ Push(eax); // limit |
1239 __ push(Immediate(0)); // index | 1256 __ push(Immediate(0)); // index |
1240 // Push newTarget and callee functions | 1257 // Push newTarget and callee functions |
1241 __ push(Operand(ebp, kNewTargetOffset)); | 1258 __ push(Operand(ebp, kNewTargetOffset)); |
1242 __ push(Operand(ebp, kFunctionOffset)); | 1259 __ push(Operand(ebp, kFunctionOffset)); |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1673 | 1690 |
1674 __ bind(&ok); | 1691 __ bind(&ok); |
1675 __ ret(0); | 1692 __ ret(0); |
1676 } | 1693 } |
1677 | 1694 |
1678 #undef __ | 1695 #undef __ |
1679 } | 1696 } |
1680 } // namespace v8::internal | 1697 } // namespace v8::internal |
1681 | 1698 |
1682 #endif // V8_TARGET_ARCH_X87 | 1699 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |