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 #if V8_TARGET_ARCH_ARM | 5 #if V8_TARGET_ARCH_ARM |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 981 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
992 FrameScope scope(masm, StackFrame::MANUAL); | 992 FrameScope scope(masm, StackFrame::MANUAL); |
993 __ EnterExitFrame(save_doubles()); | 993 __ EnterExitFrame(save_doubles()); |
994 | 994 |
995 // Store a copy of argc in callee-saved registers for later. | 995 // Store a copy of argc in callee-saved registers for later. |
996 __ mov(r4, Operand(r0)); | 996 __ mov(r4, Operand(r0)); |
997 | 997 |
998 // r0, r4: number of arguments including receiver (C callee-saved) | 998 // r0, r4: number of arguments including receiver (C callee-saved) |
999 // r1: pointer to the first argument (C callee-saved) | 999 // r1: pointer to the first argument (C callee-saved) |
1000 // r5: pointer to builtin function (C callee-saved) | 1000 // r5: pointer to builtin function (C callee-saved) |
1001 | 1001 |
1002 // Result returned in r0 or r0+r1 by default. | |
1003 | |
1004 #if V8_HOST_ARCH_ARM | |
1005 int frame_alignment = MacroAssembler::ActivationFrameAlignment(); | 1002 int frame_alignment = MacroAssembler::ActivationFrameAlignment(); |
1006 int frame_alignment_mask = frame_alignment - 1; | 1003 int frame_alignment_mask = frame_alignment - 1; |
| 1004 #if V8_HOST_ARCH_ARM |
1007 if (FLAG_debug_code) { | 1005 if (FLAG_debug_code) { |
1008 if (frame_alignment > kPointerSize) { | 1006 if (frame_alignment > kPointerSize) { |
1009 Label alignment_as_expected; | 1007 Label alignment_as_expected; |
1010 DCHECK(base::bits::IsPowerOfTwo32(frame_alignment)); | 1008 DCHECK(base::bits::IsPowerOfTwo32(frame_alignment)); |
1011 __ tst(sp, Operand(frame_alignment_mask)); | 1009 __ tst(sp, Operand(frame_alignment_mask)); |
1012 __ b(eq, &alignment_as_expected); | 1010 __ b(eq, &alignment_as_expected); |
1013 // Don't use Check here, as it will call Runtime_Abort re-entering here. | 1011 // Don't use Check here, as it will call Runtime_Abort re-entering here. |
1014 __ stop("Unexpected alignment"); | 1012 __ stop("Unexpected alignment"); |
1015 __ bind(&alignment_as_expected); | 1013 __ bind(&alignment_as_expected); |
1016 } | 1014 } |
1017 } | 1015 } |
1018 #endif | 1016 #endif |
1019 | 1017 |
1020 // Call C built-in. | 1018 // Call C built-in. |
1021 // r0 = argc, r1 = argv | 1019 int result_stack_size; |
1022 __ mov(r2, Operand(ExternalReference::isolate_address(isolate()))); | 1020 if (result_size() <= 2) { |
| 1021 // r0 = argc, r1 = argv, r2 = isolate |
| 1022 __ mov(r2, Operand(ExternalReference::isolate_address(isolate()))); |
| 1023 result_stack_size = 0; |
| 1024 } else { |
| 1025 DCHECK_EQ(3, result_size()); |
| 1026 // Allocate additional space for the result. |
| 1027 result_stack_size = |
| 1028 ((result_size() * kPointerSize) + frame_alignment_mask) & |
| 1029 ~frame_alignment_mask; |
| 1030 __ sub(sp, sp, Operand(result_stack_size)); |
| 1031 |
| 1032 // r0 = hidden result argument, r1 = argc, r2 = argv, r3 = isolate. |
| 1033 __ mov(r3, Operand(ExternalReference::isolate_address(isolate()))); |
| 1034 __ mov(r2, Operand(r1)); |
| 1035 __ mov(r1, Operand(r0)); |
| 1036 __ mov(r0, Operand(sp)); |
| 1037 } |
1023 | 1038 |
1024 // To let the GC traverse the return address of the exit frames, we need to | 1039 // To let the GC traverse the return address of the exit frames, we need to |
1025 // know where the return address is. The CEntryStub is unmovable, so | 1040 // know where the return address is. The CEntryStub is unmovable, so |
1026 // we can store the address on the stack to be able to find it again and | 1041 // we can store the address on the stack to be able to find it again and |
1027 // we never have to restore it, because it will not change. | 1042 // we never have to restore it, because it will not change. |
1028 // Compute the return address in lr to return to after the jump below. Pc is | 1043 // Compute the return address in lr to return to after the jump below. Pc is |
1029 // already at '+ 8' from the current instruction but return is after three | 1044 // already at '+ 8' from the current instruction but return is after three |
1030 // instructions so add another 4 to pc to get the return address. | 1045 // instructions so add another 4 to pc to get the return address. |
1031 { | 1046 { |
1032 // Prevent literal pool emission before return address. | 1047 // Prevent literal pool emission before return address. |
1033 Assembler::BlockConstPoolScope block_const_pool(masm); | 1048 Assembler::BlockConstPoolScope block_const_pool(masm); |
1034 __ add(lr, pc, Operand(4)); | 1049 __ add(lr, pc, Operand(4)); |
1035 __ str(lr, MemOperand(sp, 0)); | 1050 __ str(lr, MemOperand(sp, result_stack_size)); |
1036 __ Call(r5); | 1051 __ Call(r5); |
1037 } | 1052 } |
| 1053 if (result_size() > 2) { |
| 1054 DCHECK_EQ(3, result_size()); |
| 1055 // Read result values stored on stack. |
| 1056 __ ldr(r2, MemOperand(r0, 2 * kPointerSize)); |
| 1057 __ ldr(r1, MemOperand(r0, 1 * kPointerSize)); |
| 1058 __ ldr(r0, MemOperand(r0, 0 * kPointerSize)); |
| 1059 } |
| 1060 // Result returned in r0, r1:r0 or r2:r1:r0 - do not destroy these registers! |
1038 | 1061 |
1039 __ VFPEnsureFPSCRState(r2); | 1062 __ VFPEnsureFPSCRState(r3); |
1040 | 1063 |
1041 // Check result for exception sentinel. | 1064 // Check result for exception sentinel. |
1042 Label exception_returned; | 1065 Label exception_returned; |
1043 __ CompareRoot(r0, Heap::kExceptionRootIndex); | 1066 __ CompareRoot(r0, Heap::kExceptionRootIndex); |
1044 __ b(eq, &exception_returned); | 1067 __ b(eq, &exception_returned); |
1045 | 1068 |
1046 // Check that there is no pending exception, otherwise we | 1069 // Check that there is no pending exception, otherwise we |
1047 // should have returned the exception sentinel. | 1070 // should have returned the exception sentinel. |
1048 if (FLAG_debug_code) { | 1071 if (FLAG_debug_code) { |
1049 Label okay; | 1072 Label okay; |
1050 ExternalReference pending_exception_address( | 1073 ExternalReference pending_exception_address( |
1051 Isolate::kPendingExceptionAddress, isolate()); | 1074 Isolate::kPendingExceptionAddress, isolate()); |
1052 __ mov(r2, Operand(pending_exception_address)); | 1075 __ mov(r3, Operand(pending_exception_address)); |
1053 __ ldr(r2, MemOperand(r2)); | 1076 __ ldr(r3, MemOperand(r3)); |
1054 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); | 1077 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
1055 // Cannot use check here as it attempts to generate call into runtime. | 1078 // Cannot use check here as it attempts to generate call into runtime. |
1056 __ b(eq, &okay); | 1079 __ b(eq, &okay); |
1057 __ stop("Unexpected pending exception"); | 1080 __ stop("Unexpected pending exception"); |
1058 __ bind(&okay); | 1081 __ bind(&okay); |
1059 } | 1082 } |
1060 | 1083 |
1061 // Exit C frame and return. | 1084 // Exit C frame and return. |
1062 // r0:r1: result | 1085 // r0:r1: result |
1063 // sp: stack pointer | 1086 // sp: stack pointer |
1064 // fp: frame pointer | 1087 // fp: frame pointer |
(...skipping 4319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5384 MemOperand(fp, 6 * kPointerSize), NULL); | 5407 MemOperand(fp, 6 * kPointerSize), NULL); |
5385 } | 5408 } |
5386 | 5409 |
5387 | 5410 |
5388 #undef __ | 5411 #undef __ |
5389 | 5412 |
5390 } // namespace internal | 5413 } // namespace internal |
5391 } // namespace v8 | 5414 } // namespace v8 |
5392 | 5415 |
5393 #endif // V8_TARGET_ARCH_ARM | 5416 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |