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_X64 | 7 #if V8_TARGET_ARCH_X64 |
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 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 | 566 |
567 // Remove caller arguments from the stack and return. | 567 // Remove caller arguments from the stack and return. |
568 __ PopReturnAddressTo(rcx); | 568 __ PopReturnAddressTo(rcx); |
569 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); | 569 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); |
570 __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); | 570 __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); |
571 __ PushReturnAddressFrom(rcx); | 571 __ PushReturnAddressFrom(rcx); |
572 __ ret(0); | 572 __ ret(0); |
573 } | 573 } |
574 | 574 |
575 | 575 |
| 576 enum IsTagged { kRaxIsSmiTagged, kRaxIsUntaggedInt }; |
| 577 |
| 578 |
| 579 // Clobbers rcx, rdx, kScratchRegister; preserves all other registers. |
| 580 static void Generate_CheckStackOverflow(MacroAssembler* masm, |
| 581 const int calleeOffset, |
| 582 IsTagged rax_is_tagged) { |
| 583 // rax : the number of items to be pushed to the stack |
| 584 // |
| 585 // Check the stack for overflow. We are not trying to catch |
| 586 // interruptions (e.g. debug break and preemption) here, so the "real stack |
| 587 // limit" is checked. |
| 588 Label okay; |
| 589 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex); |
| 590 __ movp(rcx, rsp); |
| 591 // Make rcx the space we have left. The stack might already be overflowed |
| 592 // here which will cause rcx to become negative. |
| 593 __ subp(rcx, kScratchRegister); |
| 594 // Make rdx the space we need for the array when it is unrolled onto the |
| 595 // stack. |
| 596 if (rax_is_tagged == kRaxIsSmiTagged) { |
| 597 __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rax, kPointerSizeLog2); |
| 598 } else { |
| 599 DCHECK(rax_is_tagged == kRaxIsUntaggedInt); |
| 600 __ movp(rdx, rax); |
| 601 __ shlq(rdx, Immediate(kPointerSizeLog2)); |
| 602 } |
| 603 // Check if the arguments will overflow the stack. |
| 604 __ cmpp(rcx, rdx); |
| 605 __ j(greater, &okay); // Signed comparison. |
| 606 |
| 607 // Out of stack space. |
| 608 __ Push(Operand(rbp, calleeOffset)); |
| 609 __ Push(rax); |
| 610 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); |
| 611 |
| 612 __ bind(&okay); |
| 613 } |
| 614 |
| 615 |
576 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 616 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
577 bool is_construct) { | 617 bool is_construct) { |
578 ProfileEntryHookStub::MaybeCallEntryHook(masm); | 618 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
579 | 619 |
580 // Expects five C++ function parameters. | 620 // Expects five C++ function parameters. |
581 // - Address entry (ignored) | 621 // - Address entry (ignored) |
582 // - JSFunction* function ( | 622 // - JSFunction* function ( |
583 // - Object* receiver | 623 // - Object* receiver |
584 // - int argc | 624 // - int argc |
585 // - Object*** argv | 625 // - Object*** argv |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 // Current stack contents: | 688 // Current stack contents: |
649 // [rsp + 2 * kPointerSize ... ] : Internal frame | 689 // [rsp + 2 * kPointerSize ... ] : Internal frame |
650 // [rsp + kPointerSize] : function | 690 // [rsp + kPointerSize] : function |
651 // [rsp] : receiver | 691 // [rsp] : receiver |
652 // Current register contents: | 692 // Current register contents: |
653 // rax : argc | 693 // rax : argc |
654 // rbx : argv | 694 // rbx : argv |
655 // rsi : context | 695 // rsi : context |
656 // rdi : function | 696 // rdi : function |
657 | 697 |
| 698 // Check if we have enough stack space to push all arguments. |
| 699 // The function is the first thing that was pushed above after entering |
| 700 // the internal frame. |
| 701 const int kFunctionOffset = |
| 702 InternalFrameConstants::kCodeOffset - kRegisterSize; |
| 703 // Expects argument count in rax. Clobbers rcx, rdx. |
| 704 Generate_CheckStackOverflow(masm, kFunctionOffset, kRaxIsUntaggedInt); |
| 705 |
658 // Copy arguments to the stack in a loop. | 706 // Copy arguments to the stack in a loop. |
659 // Register rbx points to array of pointers to handle locations. | 707 // Register rbx points to array of pointers to handle locations. |
660 // Push the values of these handles. | 708 // Push the values of these handles. |
661 Label loop, entry; | 709 Label loop, entry; |
662 __ Set(rcx, 0); // Set loop variable to 0. | 710 __ Set(rcx, 0); // Set loop variable to 0. |
663 __ jmp(&entry); | 711 __ jmp(&entry); |
664 __ bind(&loop); | 712 __ bind(&loop); |
665 __ movp(kScratchRegister, Operand(rbx, rcx, times_pointer_size, 0)); | 713 __ movp(kScratchRegister, Operand(rbx, rcx, times_pointer_size, 0)); |
666 __ Push(Operand(kScratchRegister, 0)); // dereference handle | 714 __ Push(Operand(kScratchRegister, 0)); // dereference handle |
667 __ addp(rcx, Immediate(1)); | 715 __ addp(rcx, Immediate(1)); |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1044 __ cmpp(rax, rbx); | 1092 __ cmpp(rax, rbx); |
1045 __ j(not_equal, | 1093 __ j(not_equal, |
1046 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1094 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
1047 RelocInfo::CODE_TARGET); | 1095 RelocInfo::CODE_TARGET); |
1048 | 1096 |
1049 ParameterCount expected(0); | 1097 ParameterCount expected(0); |
1050 __ InvokeCode(rdx, expected, expected, JUMP_FUNCTION, NullCallWrapper()); | 1098 __ InvokeCode(rdx, expected, expected, JUMP_FUNCTION, NullCallWrapper()); |
1051 } | 1099 } |
1052 | 1100 |
1053 | 1101 |
1054 static void Generate_CheckStackOverflow(MacroAssembler* masm, | |
1055 const int calleeOffset) { | |
1056 // rax : the number of items to be pushed to the stack | |
1057 // | |
1058 // Check the stack for overflow. We are not trying to catch | |
1059 // interruptions (e.g. debug break and preemption) here, so the "real stack | |
1060 // limit" is checked. | |
1061 Label okay; | |
1062 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex); | |
1063 __ movp(rcx, rsp); | |
1064 // Make rcx the space we have left. The stack might already be overflowed | |
1065 // here which will cause rcx to become negative. | |
1066 __ subp(rcx, kScratchRegister); | |
1067 // Make rdx the space we need for the array when it is unrolled onto the | |
1068 // stack. | |
1069 __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rax, kPointerSizeLog2); | |
1070 // Check if the arguments will overflow the stack. | |
1071 __ cmpp(rcx, rdx); | |
1072 __ j(greater, &okay); // Signed comparison. | |
1073 | |
1074 // Out of stack space. | |
1075 __ Push(Operand(rbp, calleeOffset)); | |
1076 __ Push(rax); | |
1077 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); | |
1078 | |
1079 __ bind(&okay); | |
1080 } | |
1081 | |
1082 | |
1083 static void Generate_PushAppliedArguments(MacroAssembler* masm, | 1102 static void Generate_PushAppliedArguments(MacroAssembler* masm, |
1084 const int argumentsOffset, | 1103 const int argumentsOffset, |
1085 const int indexOffset, | 1104 const int indexOffset, |
1086 const int limitOffset) { | 1105 const int limitOffset) { |
1087 Register receiver = LoadDescriptor::ReceiverRegister(); | 1106 Register receiver = LoadDescriptor::ReceiverRegister(); |
1088 Register key = LoadDescriptor::NameRegister(); | 1107 Register key = LoadDescriptor::NameRegister(); |
1089 | 1108 |
1090 // Copy all arguments from the array to the stack. | 1109 // Copy all arguments from the array to the stack. |
1091 Label entry, loop; | 1110 Label entry, loop; |
1092 __ movp(key, Operand(rbp, indexOffset)); | 1111 __ movp(key, Operand(rbp, indexOffset)); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1150 static const int kFunctionOffset = kReceiverOffset + kPointerSize; | 1169 static const int kFunctionOffset = kReceiverOffset + kPointerSize; |
1151 | 1170 |
1152 __ Push(Operand(rbp, kFunctionOffset)); | 1171 __ Push(Operand(rbp, kFunctionOffset)); |
1153 __ Push(Operand(rbp, kArgumentsOffset)); | 1172 __ Push(Operand(rbp, kArgumentsOffset)); |
1154 if (targetIsArgument) { | 1173 if (targetIsArgument) { |
1155 __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION); | 1174 __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION); |
1156 } else { | 1175 } else { |
1157 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); | 1176 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); |
1158 } | 1177 } |
1159 | 1178 |
1160 Generate_CheckStackOverflow(masm, kFunctionOffset); | 1179 Generate_CheckStackOverflow(masm, kFunctionOffset, kRaxIsSmiTagged); |
1161 | 1180 |
1162 // Push current index and limit. | 1181 // Push current index and limit. |
1163 const int kLimitOffset = | 1182 const int kLimitOffset = |
1164 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; | 1183 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; |
1165 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; | 1184 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; |
1166 __ Push(rax); // limit | 1185 __ Push(rax); // limit |
1167 __ Push(Immediate(0)); // index | 1186 __ Push(Immediate(0)); // index |
1168 | 1187 |
1169 // Get the receiver. | 1188 // Get the receiver. |
1170 __ movp(rbx, Operand(rbp, kReceiverOffset)); | 1189 __ movp(rbx, Operand(rbp, kReceiverOffset)); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1279 __ movp(rax, Operand(rbp, kFunctionOffset)); | 1298 __ movp(rax, Operand(rbp, kFunctionOffset)); |
1280 __ movp(Operand(rbp, kNewTargetOffset), rax); | 1299 __ movp(Operand(rbp, kNewTargetOffset), rax); |
1281 | 1300 |
1282 // Validate arguments | 1301 // Validate arguments |
1283 __ bind(&validate_arguments); | 1302 __ bind(&validate_arguments); |
1284 __ Push(Operand(rbp, kFunctionOffset)); | 1303 __ Push(Operand(rbp, kFunctionOffset)); |
1285 __ Push(Operand(rbp, kArgumentsOffset)); | 1304 __ Push(Operand(rbp, kArgumentsOffset)); |
1286 __ Push(Operand(rbp, kNewTargetOffset)); | 1305 __ Push(Operand(rbp, kNewTargetOffset)); |
1287 __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION); | 1306 __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION); |
1288 | 1307 |
1289 Generate_CheckStackOverflow(masm, kFunctionOffset); | 1308 Generate_CheckStackOverflow(masm, kFunctionOffset, kRaxIsSmiTagged); |
1290 | 1309 |
1291 // Push current index and limit. | 1310 // Push current index and limit. |
1292 const int kLimitOffset = | 1311 const int kLimitOffset = |
1293 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; | 1312 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; |
1294 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; | 1313 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; |
1295 __ Push(rax); // limit | 1314 __ Push(rax); // limit |
1296 __ Push(Immediate(0)); // index | 1315 __ Push(Immediate(0)); // index |
1297 // Push newTarget and callee functions | 1316 // Push newTarget and callee functions |
1298 __ Push(Operand(rbp, kNewTargetOffset)); | 1317 __ Push(Operand(rbp, kNewTargetOffset)); |
1299 __ Push(Operand(rbp, kFunctionOffset)); | 1318 __ Push(Operand(rbp, kFunctionOffset)); |
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1729 __ bind(&ok); | 1748 __ bind(&ok); |
1730 __ ret(0); | 1749 __ ret(0); |
1731 } | 1750 } |
1732 | 1751 |
1733 | 1752 |
1734 #undef __ | 1753 #undef __ |
1735 | 1754 |
1736 } } // namespace v8::internal | 1755 } } // namespace v8::internal |
1737 | 1756 |
1738 #endif // V8_TARGET_ARCH_X64 | 1757 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |