| 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 |