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/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 4592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4603 Label fast_elements_case; | 4603 Label fast_elements_case; |
4604 __ cmp(r3, Operand(FAST_ELEMENTS)); | 4604 __ cmp(r3, Operand(FAST_ELEMENTS)); |
4605 __ b(eq, &fast_elements_case); | 4605 __ b(eq, &fast_elements_case); |
4606 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 4606 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
4607 | 4607 |
4608 __ bind(&fast_elements_case); | 4608 __ bind(&fast_elements_case); |
4609 GenerateCase(masm, FAST_ELEMENTS); | 4609 GenerateCase(masm, FAST_ELEMENTS); |
4610 } | 4610 } |
4611 | 4611 |
4612 | 4612 |
| 4613 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { |
| 4614 return ref0.address() - ref1.address(); |
| 4615 } |
| 4616 |
| 4617 |
| 4618 // Calls an API function. Allocates HandleScope, extracts returned value |
| 4619 // from handle and propagates exceptions. Restores context. stack_space |
| 4620 // - space to be unwound on exit (includes the call JS arguments space and |
| 4621 // the additional space allocated for the fast call). |
| 4622 static void CallApiFunctionAndReturn(MacroAssembler* masm, |
| 4623 Register function_address, |
| 4624 ExternalReference thunk_ref, |
| 4625 int stack_space, |
| 4626 MemOperand* stack_space_operand, |
| 4627 MemOperand return_value_operand, |
| 4628 MemOperand* context_restore_operand) { |
| 4629 Isolate* isolate = masm->isolate(); |
| 4630 ExternalReference next_address = |
| 4631 ExternalReference::handle_scope_next_address(isolate); |
| 4632 const int kNextOffset = 0; |
| 4633 const int kLimitOffset = AddressOffset( |
| 4634 ExternalReference::handle_scope_limit_address(isolate), next_address); |
| 4635 const int kLevelOffset = AddressOffset( |
| 4636 ExternalReference::handle_scope_level_address(isolate), next_address); |
| 4637 |
| 4638 DCHECK(function_address.is(r1) || function_address.is(r2)); |
| 4639 |
| 4640 Label profiler_disabled; |
| 4641 Label end_profiler_check; |
| 4642 __ mov(r9, Operand(ExternalReference::is_profiling_address(isolate))); |
| 4643 __ ldrb(r9, MemOperand(r9, 0)); |
| 4644 __ cmp(r9, Operand(0)); |
| 4645 __ b(eq, &profiler_disabled); |
| 4646 |
| 4647 // Additional parameter is the address of the actual callback. |
| 4648 __ mov(r3, Operand(thunk_ref)); |
| 4649 __ jmp(&end_profiler_check); |
| 4650 |
| 4651 __ bind(&profiler_disabled); |
| 4652 __ Move(r3, function_address); |
| 4653 __ bind(&end_profiler_check); |
| 4654 |
| 4655 // Allocate HandleScope in callee-save registers. |
| 4656 __ mov(r9, Operand(next_address)); |
| 4657 __ ldr(r4, MemOperand(r9, kNextOffset)); |
| 4658 __ ldr(r5, MemOperand(r9, kLimitOffset)); |
| 4659 __ ldr(r6, MemOperand(r9, kLevelOffset)); |
| 4660 __ add(r6, r6, Operand(1)); |
| 4661 __ str(r6, MemOperand(r9, kLevelOffset)); |
| 4662 |
| 4663 if (FLAG_log_timer_events) { |
| 4664 FrameScope frame(masm, StackFrame::MANUAL); |
| 4665 __ PushSafepointRegisters(); |
| 4666 __ PrepareCallCFunction(1, r0); |
| 4667 __ mov(r0, Operand(ExternalReference::isolate_address(isolate))); |
| 4668 __ CallCFunction(ExternalReference::log_enter_external_function(isolate), |
| 4669 1); |
| 4670 __ PopSafepointRegisters(); |
| 4671 } |
| 4672 |
| 4673 // Native call returns to the DirectCEntry stub which redirects to the |
| 4674 // return address pushed on stack (could have moved after GC). |
| 4675 // DirectCEntry stub itself is generated early and never moves. |
| 4676 DirectCEntryStub stub(isolate); |
| 4677 stub.GenerateCall(masm, r3); |
| 4678 |
| 4679 if (FLAG_log_timer_events) { |
| 4680 FrameScope frame(masm, StackFrame::MANUAL); |
| 4681 __ PushSafepointRegisters(); |
| 4682 __ PrepareCallCFunction(1, r0); |
| 4683 __ mov(r0, Operand(ExternalReference::isolate_address(isolate))); |
| 4684 __ CallCFunction(ExternalReference::log_leave_external_function(isolate), |
| 4685 1); |
| 4686 __ PopSafepointRegisters(); |
| 4687 } |
| 4688 |
| 4689 Label promote_scheduled_exception; |
| 4690 Label exception_handled; |
| 4691 Label delete_allocated_handles; |
| 4692 Label leave_exit_frame; |
| 4693 Label return_value_loaded; |
| 4694 |
| 4695 // load value from ReturnValue |
| 4696 __ ldr(r0, return_value_operand); |
| 4697 __ bind(&return_value_loaded); |
| 4698 // No more valid handles (the result handle was the last one). Restore |
| 4699 // previous handle scope. |
| 4700 __ str(r4, MemOperand(r9, kNextOffset)); |
| 4701 if (__ emit_debug_code()) { |
| 4702 __ ldr(r1, MemOperand(r9, kLevelOffset)); |
| 4703 __ cmp(r1, r6); |
| 4704 __ Check(eq, kUnexpectedLevelAfterReturnFromApiCall); |
| 4705 } |
| 4706 __ sub(r6, r6, Operand(1)); |
| 4707 __ str(r6, MemOperand(r9, kLevelOffset)); |
| 4708 __ ldr(ip, MemOperand(r9, kLimitOffset)); |
| 4709 __ cmp(r5, ip); |
| 4710 __ b(ne, &delete_allocated_handles); |
| 4711 |
| 4712 // Check if the function scheduled an exception. |
| 4713 __ bind(&leave_exit_frame); |
| 4714 __ LoadRoot(r4, Heap::kTheHoleValueRootIndex); |
| 4715 __ mov(ip, Operand(ExternalReference::scheduled_exception_address(isolate))); |
| 4716 __ ldr(r5, MemOperand(ip)); |
| 4717 __ cmp(r4, r5); |
| 4718 __ b(ne, &promote_scheduled_exception); |
| 4719 __ bind(&exception_handled); |
| 4720 |
| 4721 bool restore_context = context_restore_operand != NULL; |
| 4722 if (restore_context) { |
| 4723 __ ldr(cp, *context_restore_operand); |
| 4724 } |
| 4725 // LeaveExitFrame expects unwind space to be in a register. |
| 4726 if (stack_space_operand != NULL) { |
| 4727 __ ldr(r4, *stack_space_operand); |
| 4728 } else { |
| 4729 __ mov(r4, Operand(stack_space)); |
| 4730 } |
| 4731 __ LeaveExitFrame(false, r4, !restore_context, stack_space_operand != NULL); |
| 4732 __ mov(pc, lr); |
| 4733 |
| 4734 __ bind(&promote_scheduled_exception); |
| 4735 { |
| 4736 FrameScope frame(masm, StackFrame::INTERNAL); |
| 4737 __ CallExternalReference( |
| 4738 ExternalReference(Runtime::kPromoteScheduledException, isolate), 0); |
| 4739 } |
| 4740 __ jmp(&exception_handled); |
| 4741 |
| 4742 // HandleScope limit has changed. Delete allocated extensions. |
| 4743 __ bind(&delete_allocated_handles); |
| 4744 __ str(r5, MemOperand(r9, kLimitOffset)); |
| 4745 __ mov(r4, r0); |
| 4746 __ PrepareCallCFunction(1, r5); |
| 4747 __ mov(r0, Operand(ExternalReference::isolate_address(isolate))); |
| 4748 __ CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate), |
| 4749 1); |
| 4750 __ mov(r0, r4); |
| 4751 __ jmp(&leave_exit_frame); |
| 4752 } |
| 4753 |
| 4754 |
4613 static void CallApiFunctionStubHelper(MacroAssembler* masm, | 4755 static void CallApiFunctionStubHelper(MacroAssembler* masm, |
4614 const ParameterCount& argc, | 4756 const ParameterCount& argc, |
4615 bool return_first_arg, | 4757 bool return_first_arg, |
4616 bool call_data_undefined) { | 4758 bool call_data_undefined) { |
4617 // ----------- S t a t e ------------- | 4759 // ----------- S t a t e ------------- |
4618 // -- r0 : callee | 4760 // -- r0 : callee |
4619 // -- r4 : call_data | 4761 // -- r4 : call_data |
4620 // -- r2 : holder | 4762 // -- r2 : holder |
4621 // -- r1 : api_function_address | 4763 // -- r1 : api_function_address |
4622 // -- r3 : number of arguments if argc is a register | 4764 // -- r3 : number of arguments if argc is a register |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4726 return_value_offset = 2 + FCA::kReturnValueOffset; | 4868 return_value_offset = 2 + FCA::kReturnValueOffset; |
4727 } | 4869 } |
4728 MemOperand return_value_operand(fp, return_value_offset * kPointerSize); | 4870 MemOperand return_value_operand(fp, return_value_offset * kPointerSize); |
4729 int stack_space = 0; | 4871 int stack_space = 0; |
4730 MemOperand is_construct_call_operand = MemOperand(sp, 4 * kPointerSize); | 4872 MemOperand is_construct_call_operand = MemOperand(sp, 4 * kPointerSize); |
4731 MemOperand* stack_space_operand = &is_construct_call_operand; | 4873 MemOperand* stack_space_operand = &is_construct_call_operand; |
4732 if (argc.is_immediate()) { | 4874 if (argc.is_immediate()) { |
4733 stack_space = argc.immediate() + FCA::kArgsLength + 1; | 4875 stack_space = argc.immediate() + FCA::kArgsLength + 1; |
4734 stack_space_operand = NULL; | 4876 stack_space_operand = NULL; |
4735 } | 4877 } |
4736 __ CallApiFunctionAndReturn(api_function_address, thunk_ref, stack_space, | 4878 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space, |
4737 stack_space_operand, return_value_operand, | 4879 stack_space_operand, return_value_operand, |
4738 &context_restore_operand); | 4880 &context_restore_operand); |
4739 } | 4881 } |
4740 | 4882 |
4741 | 4883 |
4742 void CallApiFunctionStub::Generate(MacroAssembler* masm) { | 4884 void CallApiFunctionStub::Generate(MacroAssembler* masm) { |
4743 bool call_data_undefined = this->call_data_undefined(); | 4885 bool call_data_undefined = this->call_data_undefined(); |
4744 CallApiFunctionStubHelper(masm, ParameterCount(r3), false, | 4886 CallApiFunctionStubHelper(masm, ParameterCount(r3), false, |
4745 call_data_undefined); | 4887 call_data_undefined); |
4746 } | 4888 } |
4747 | 4889 |
4748 | 4890 |
(...skipping 26 matching lines...) Expand all Loading... |
4775 | 4917 |
4776 // Create PropertyAccessorInfo instance on the stack above the exit frame with | 4918 // Create PropertyAccessorInfo instance on the stack above the exit frame with |
4777 // r1 (internal::Object** args_) as the data. | 4919 // r1 (internal::Object** args_) as the data. |
4778 __ str(r1, MemOperand(sp, 1 * kPointerSize)); | 4920 __ str(r1, MemOperand(sp, 1 * kPointerSize)); |
4779 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& | 4921 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& |
4780 | 4922 |
4781 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; | 4923 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; |
4782 | 4924 |
4783 ExternalReference thunk_ref = | 4925 ExternalReference thunk_ref = |
4784 ExternalReference::invoke_accessor_getter_callback(isolate()); | 4926 ExternalReference::invoke_accessor_getter_callback(isolate()); |
4785 __ CallApiFunctionAndReturn(api_function_address, thunk_ref, | 4927 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, |
4786 kStackUnwindSpace, NULL, | 4928 kStackUnwindSpace, NULL, |
4787 MemOperand(fp, 6 * kPointerSize), NULL); | 4929 MemOperand(fp, 6 * kPointerSize), NULL); |
4788 } | 4930 } |
4789 | 4931 |
4790 | 4932 |
4791 #undef __ | 4933 #undef __ |
4792 | 4934 |
4793 } } // namespace v8::internal | 4935 } } // namespace v8::internal |
4794 | 4936 |
4795 #endif // V8_TARGET_ARCH_ARM | 4937 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |