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_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/debug.h" | 10 #include "src/debug.h" |
(...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
823 | 823 |
824 // Leave construct frame. | 824 // Leave construct frame. |
825 } | 825 } |
826 | 826 |
827 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); | 827 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); |
828 __ add(sp, sp, Operand(kPointerSize)); | 828 __ add(sp, sp, Operand(kPointerSize)); |
829 __ Jump(lr); | 829 __ Jump(lr); |
830 } | 830 } |
831 | 831 |
832 | 832 |
| 833 enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt }; |
| 834 |
| 835 |
| 836 // Clobbers r2; preserves all other registers. |
| 837 static void Generate_CheckStackOverflow(MacroAssembler* masm, |
| 838 const int calleeOffset, Register argc, |
| 839 IsTagged argc_is_tagged) { |
| 840 // Check the stack for overflow. We are not trying to catch |
| 841 // interruptions (e.g. debug break and preemption) here, so the "real stack |
| 842 // limit" is checked. |
| 843 Label okay; |
| 844 __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); |
| 845 // Make r2 the space we have left. The stack might already be overflowed |
| 846 // here which will cause r2 to become negative. |
| 847 __ sub(r2, sp, r2); |
| 848 // Check if the arguments will overflow the stack. |
| 849 if (argc_is_tagged == kArgcIsSmiTagged) { |
| 850 __ cmp(r2, Operand::PointerOffsetFromSmiKey(argc)); |
| 851 } else { |
| 852 DCHECK(argc_is_tagged == kArgcIsUntaggedInt); |
| 853 __ cmp(r2, Operand(argc, LSL, kPointerSizeLog2)); |
| 854 } |
| 855 __ b(gt, &okay); // Signed comparison. |
| 856 |
| 857 // Out of stack space. |
| 858 __ ldr(r1, MemOperand(fp, calleeOffset)); |
| 859 __ Push(r1, argc); |
| 860 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); |
| 861 |
| 862 __ bind(&okay); |
| 863 } |
| 864 |
| 865 |
833 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 866 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
834 bool is_construct) { | 867 bool is_construct) { |
835 // Called from Generate_JS_Entry | 868 // Called from Generate_JS_Entry |
836 // r0: code entry | 869 // r0: code entry |
837 // r1: function | 870 // r1: function |
838 // r2: receiver | 871 // r2: receiver |
839 // r3: argc | 872 // r3: argc |
840 // r4: argv | 873 // r4: argv |
841 // r5-r6, r8 (if not FLAG_enable_ool_constant_pool) and cp may be clobbered | 874 // r5-r6, r8 (if not FLAG_enable_ool_constant_pool) and cp may be clobbered |
842 ProfileEntryHookStub::MaybeCallEntryHook(masm); | 875 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
843 | 876 |
844 // Clear the context before we push it when entering the internal frame. | 877 // Clear the context before we push it when entering the internal frame. |
845 __ mov(cp, Operand::Zero()); | 878 __ mov(cp, Operand::Zero()); |
846 | 879 |
847 // Enter an internal frame. | 880 // Enter an internal frame. |
848 { | 881 { |
849 FrameScope scope(masm, StackFrame::INTERNAL); | 882 FrameScope scope(masm, StackFrame::INTERNAL); |
850 | 883 |
851 // Set up the context from the function argument. | 884 // Set up the context from the function argument. |
852 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 885 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
853 | 886 |
854 __ InitializeRootRegister(); | 887 __ InitializeRootRegister(); |
855 | 888 |
856 // Push the function and the receiver onto the stack. | 889 // Push the function and the receiver onto the stack. |
857 __ push(r1); | 890 __ push(r1); |
858 __ push(r2); | 891 __ push(r2); |
859 | 892 |
| 893 // Check if we have enough stack space to push all arguments. |
| 894 // The function is the first thing that was pushed above after entering |
| 895 // the internal frame. |
| 896 const int kFunctionOffset = |
| 897 InternalFrameConstants::kCodeOffset - kPointerSize; |
| 898 // Clobbers r2. |
| 899 Generate_CheckStackOverflow(masm, kFunctionOffset, r3, kArgcIsUntaggedInt); |
| 900 |
860 // Copy arguments to the stack in a loop. | 901 // Copy arguments to the stack in a loop. |
861 // r1: function | 902 // r1: function |
862 // r3: argc | 903 // r3: argc |
863 // r4: argv, i.e. points to first arg | 904 // r4: argv, i.e. points to first arg |
864 Label loop, entry; | 905 Label loop, entry; |
865 __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2)); | 906 __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2)); |
866 // r2 points past last arg. | 907 // r2 points past last arg. |
867 __ b(&entry); | 908 __ b(&entry); |
868 __ bind(&loop); | 909 __ bind(&loop); |
869 __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex)); // read next parameter | 910 __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex)); // read next parameter |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1329 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1370 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
1330 RelocInfo::CODE_TARGET, | 1371 RelocInfo::CODE_TARGET, |
1331 ne); | 1372 ne); |
1332 | 1373 |
1333 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 1374 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
1334 ParameterCount expected(0); | 1375 ParameterCount expected(0); |
1335 __ InvokeCode(r3, expected, expected, JUMP_FUNCTION, NullCallWrapper()); | 1376 __ InvokeCode(r3, expected, expected, JUMP_FUNCTION, NullCallWrapper()); |
1336 } | 1377 } |
1337 | 1378 |
1338 | 1379 |
1339 static void Generate_CheckStackOverflow(MacroAssembler* masm, | |
1340 const int calleeOffset) { | |
1341 // Check the stack for overflow. We are not trying to catch | |
1342 // interruptions (e.g. debug break and preemption) here, so the "real stack | |
1343 // limit" is checked. | |
1344 Label okay; | |
1345 __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); | |
1346 // Make r2 the space we have left. The stack might already be overflowed | |
1347 // here which will cause r2 to become negative. | |
1348 __ sub(r2, sp, r2); | |
1349 // Check if the arguments will overflow the stack. | |
1350 __ cmp(r2, Operand::PointerOffsetFromSmiKey(r0)); | |
1351 __ b(gt, &okay); // Signed comparison. | |
1352 | |
1353 // Out of stack space. | |
1354 __ ldr(r1, MemOperand(fp, calleeOffset)); | |
1355 __ Push(r1, r0); | |
1356 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); | |
1357 | |
1358 __ bind(&okay); | |
1359 } | |
1360 | |
1361 | |
1362 static void Generate_PushAppliedArguments(MacroAssembler* masm, | 1380 static void Generate_PushAppliedArguments(MacroAssembler* masm, |
1363 const int argumentsOffset, | 1381 const int argumentsOffset, |
1364 const int indexOffset, | 1382 const int indexOffset, |
1365 const int limitOffset) { | 1383 const int limitOffset) { |
1366 Label entry, loop; | 1384 Label entry, loop; |
1367 __ ldr(r0, MemOperand(fp, indexOffset)); | 1385 __ ldr(r0, MemOperand(fp, indexOffset)); |
1368 __ b(&entry); | 1386 __ b(&entry); |
1369 | 1387 |
1370 // Load the current argument from the arguments array and push it to the | 1388 // Load the current argument from the arguments array and push it to the |
1371 // stack. | 1389 // stack. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1409 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function | 1427 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function |
1410 __ push(r0); | 1428 __ push(r0); |
1411 __ ldr(r0, MemOperand(fp, kArgumentsOffset)); // get the args array | 1429 __ ldr(r0, MemOperand(fp, kArgumentsOffset)); // get the args array |
1412 __ push(r0); | 1430 __ push(r0); |
1413 if (targetIsArgument) { | 1431 if (targetIsArgument) { |
1414 __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION); | 1432 __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION); |
1415 } else { | 1433 } else { |
1416 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); | 1434 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); |
1417 } | 1435 } |
1418 | 1436 |
1419 Generate_CheckStackOverflow(masm, kFunctionOffset); | 1437 Generate_CheckStackOverflow(masm, kFunctionOffset, r0, kArgcIsSmiTagged); |
1420 | 1438 |
1421 // Push current limit and index. | 1439 // Push current limit and index. |
1422 const int kIndexOffset = | 1440 const int kIndexOffset = |
1423 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); | 1441 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); |
1424 const int kLimitOffset = | 1442 const int kLimitOffset = |
1425 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); | 1443 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); |
1426 __ push(r0); // limit | 1444 __ push(r0); // limit |
1427 __ mov(r1, Operand::Zero()); // initial index | 1445 __ mov(r1, Operand::Zero()); // initial index |
1428 __ push(r1); | 1446 __ push(r1); |
1429 | 1447 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1537 // Validate arguments | 1555 // Validate arguments |
1538 __ bind(&validate_arguments); | 1556 __ bind(&validate_arguments); |
1539 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function | 1557 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function |
1540 __ push(r0); | 1558 __ push(r0); |
1541 __ ldr(r0, MemOperand(fp, kArgumentsOffset)); // get the args array | 1559 __ ldr(r0, MemOperand(fp, kArgumentsOffset)); // get the args array |
1542 __ push(r0); | 1560 __ push(r0); |
1543 __ ldr(r0, MemOperand(fp, kNewTargetOffset)); // get the new.target | 1561 __ ldr(r0, MemOperand(fp, kNewTargetOffset)); // get the new.target |
1544 __ push(r0); | 1562 __ push(r0); |
1545 __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION); | 1563 __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION); |
1546 | 1564 |
1547 Generate_CheckStackOverflow(masm, kFunctionOffset); | 1565 Generate_CheckStackOverflow(masm, kFunctionOffset, r0, kArgcIsSmiTagged); |
1548 | 1566 |
1549 // Push current limit and index. | 1567 // Push current limit and index. |
1550 const int kIndexOffset = | 1568 const int kIndexOffset = |
1551 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); | 1569 StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); |
1552 const int kLimitOffset = | 1570 const int kLimitOffset = |
1553 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); | 1571 StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); |
1554 __ push(r0); // limit | 1572 __ push(r0); // limit |
1555 __ mov(r1, Operand::Zero()); // initial index | 1573 __ mov(r1, Operand::Zero()); // initial index |
1556 __ push(r1); | 1574 __ push(r1); |
1557 // Push newTarget and callee functions | 1575 // Push newTarget and callee functions |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1759 __ bkpt(0); | 1777 __ bkpt(0); |
1760 } | 1778 } |
1761 } | 1779 } |
1762 | 1780 |
1763 | 1781 |
1764 #undef __ | 1782 #undef __ |
1765 | 1783 |
1766 } } // namespace v8::internal | 1784 } } // namespace v8::internal |
1767 | 1785 |
1768 #endif // V8_TARGET_ARCH_ARM | 1786 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |