OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 5025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5036 | 5036 |
5037 Label fast_elements_case; | 5037 Label fast_elements_case; |
5038 __ CompareAndBranch(kind, FAST_ELEMENTS, eq, &fast_elements_case); | 5038 __ CompareAndBranch(kind, FAST_ELEMENTS, eq, &fast_elements_case); |
5039 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 5039 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
5040 | 5040 |
5041 __ Bind(&fast_elements_case); | 5041 __ Bind(&fast_elements_case); |
5042 GenerateCase(masm, FAST_ELEMENTS); | 5042 GenerateCase(masm, FAST_ELEMENTS); |
5043 } | 5043 } |
5044 | 5044 |
5045 | 5045 |
| 5046 // The number of register that CallApiFunctionAndReturn will need to save on |
| 5047 // the stack. The space for these registers need to be allocated in the |
| 5048 // ExitFrame before calling CallApiFunctionAndReturn. |
| 5049 static const int kCallApiFunctionSpillSpace = 4; |
| 5050 |
| 5051 |
| 5052 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { |
| 5053 return ref0.address() - ref1.address(); |
| 5054 } |
| 5055 |
| 5056 |
| 5057 // Calls an API function. Allocates HandleScope, extracts returned value |
| 5058 // from handle and propagates exceptions. |
| 5059 // 'stack_space' is the space to be unwound on exit (includes the call JS |
| 5060 // arguments space and the additional space allocated for the fast call). |
| 5061 // 'spill_offset' is the offset from the stack pointer where |
| 5062 // CallApiFunctionAndReturn can spill registers. |
| 5063 static void CallApiFunctionAndReturn( |
| 5064 MacroAssembler* masm, Register function_address, |
| 5065 ExternalReference thunk_ref, int stack_space, |
| 5066 MemOperand* stack_space_operand, int spill_offset, |
| 5067 MemOperand return_value_operand, MemOperand* context_restore_operand) { |
| 5068 ASM_LOCATION("CallApiFunctionAndReturn"); |
| 5069 Isolate* isolate = masm->isolate(); |
| 5070 ExternalReference next_address = |
| 5071 ExternalReference::handle_scope_next_address(isolate); |
| 5072 const int kNextOffset = 0; |
| 5073 const int kLimitOffset = AddressOffset( |
| 5074 ExternalReference::handle_scope_limit_address(isolate), next_address); |
| 5075 const int kLevelOffset = AddressOffset( |
| 5076 ExternalReference::handle_scope_level_address(isolate), next_address); |
| 5077 |
| 5078 DCHECK(function_address.is(x1) || function_address.is(x2)); |
| 5079 |
| 5080 Label profiler_disabled; |
| 5081 Label end_profiler_check; |
| 5082 __ Mov(x10, ExternalReference::is_profiling_address(isolate)); |
| 5083 __ Ldrb(w10, MemOperand(x10)); |
| 5084 __ Cbz(w10, &profiler_disabled); |
| 5085 __ Mov(x3, thunk_ref); |
| 5086 __ B(&end_profiler_check); |
| 5087 |
| 5088 __ Bind(&profiler_disabled); |
| 5089 __ Mov(x3, function_address); |
| 5090 __ Bind(&end_profiler_check); |
| 5091 |
| 5092 // Save the callee-save registers we are going to use. |
| 5093 // TODO(all): Is this necessary? ARM doesn't do it. |
| 5094 STATIC_ASSERT(kCallApiFunctionSpillSpace == 4); |
| 5095 __ Poke(x19, (spill_offset + 0) * kXRegSize); |
| 5096 __ Poke(x20, (spill_offset + 1) * kXRegSize); |
| 5097 __ Poke(x21, (spill_offset + 2) * kXRegSize); |
| 5098 __ Poke(x22, (spill_offset + 3) * kXRegSize); |
| 5099 |
| 5100 // Allocate HandleScope in callee-save registers. |
| 5101 // We will need to restore the HandleScope after the call to the API function, |
| 5102 // by allocating it in callee-save registers they will be preserved by C code. |
| 5103 Register handle_scope_base = x22; |
| 5104 Register next_address_reg = x19; |
| 5105 Register limit_reg = x20; |
| 5106 Register level_reg = w21; |
| 5107 |
| 5108 __ Mov(handle_scope_base, next_address); |
| 5109 __ Ldr(next_address_reg, MemOperand(handle_scope_base, kNextOffset)); |
| 5110 __ Ldr(limit_reg, MemOperand(handle_scope_base, kLimitOffset)); |
| 5111 __ Ldr(level_reg, MemOperand(handle_scope_base, kLevelOffset)); |
| 5112 __ Add(level_reg, level_reg, 1); |
| 5113 __ Str(level_reg, MemOperand(handle_scope_base, kLevelOffset)); |
| 5114 |
| 5115 if (FLAG_log_timer_events) { |
| 5116 FrameScope frame(masm, StackFrame::MANUAL); |
| 5117 __ PushSafepointRegisters(); |
| 5118 __ Mov(x0, ExternalReference::isolate_address(isolate)); |
| 5119 __ CallCFunction(ExternalReference::log_enter_external_function(isolate), |
| 5120 1); |
| 5121 __ PopSafepointRegisters(); |
| 5122 } |
| 5123 |
| 5124 // Native call returns to the DirectCEntry stub which redirects to the |
| 5125 // return address pushed on stack (could have moved after GC). |
| 5126 // DirectCEntry stub itself is generated early and never moves. |
| 5127 DirectCEntryStub stub(isolate); |
| 5128 stub.GenerateCall(masm, x3); |
| 5129 |
| 5130 if (FLAG_log_timer_events) { |
| 5131 FrameScope frame(masm, StackFrame::MANUAL); |
| 5132 __ PushSafepointRegisters(); |
| 5133 __ Mov(x0, ExternalReference::isolate_address(isolate)); |
| 5134 __ CallCFunction(ExternalReference::log_leave_external_function(isolate), |
| 5135 1); |
| 5136 __ PopSafepointRegisters(); |
| 5137 } |
| 5138 |
| 5139 Label promote_scheduled_exception; |
| 5140 Label exception_handled; |
| 5141 Label delete_allocated_handles; |
| 5142 Label leave_exit_frame; |
| 5143 Label return_value_loaded; |
| 5144 |
| 5145 // Load value from ReturnValue. |
| 5146 __ Ldr(x0, return_value_operand); |
| 5147 __ Bind(&return_value_loaded); |
| 5148 // No more valid handles (the result handle was the last one). Restore |
| 5149 // previous handle scope. |
| 5150 __ Str(next_address_reg, MemOperand(handle_scope_base, kNextOffset)); |
| 5151 if (__ emit_debug_code()) { |
| 5152 __ Ldr(w1, MemOperand(handle_scope_base, kLevelOffset)); |
| 5153 __ Cmp(w1, level_reg); |
| 5154 __ Check(eq, kUnexpectedLevelAfterReturnFromApiCall); |
| 5155 } |
| 5156 __ Sub(level_reg, level_reg, 1); |
| 5157 __ Str(level_reg, MemOperand(handle_scope_base, kLevelOffset)); |
| 5158 __ Ldr(x1, MemOperand(handle_scope_base, kLimitOffset)); |
| 5159 __ Cmp(limit_reg, x1); |
| 5160 __ B(ne, &delete_allocated_handles); |
| 5161 |
| 5162 __ Bind(&leave_exit_frame); |
| 5163 // Restore callee-saved registers. |
| 5164 __ Peek(x19, (spill_offset + 0) * kXRegSize); |
| 5165 __ Peek(x20, (spill_offset + 1) * kXRegSize); |
| 5166 __ Peek(x21, (spill_offset + 2) * kXRegSize); |
| 5167 __ Peek(x22, (spill_offset + 3) * kXRegSize); |
| 5168 |
| 5169 // Check if the function scheduled an exception. |
| 5170 __ Mov(x5, ExternalReference::scheduled_exception_address(isolate)); |
| 5171 __ Ldr(x5, MemOperand(x5)); |
| 5172 __ JumpIfNotRoot(x5, Heap::kTheHoleValueRootIndex, |
| 5173 &promote_scheduled_exception); |
| 5174 __ Bind(&exception_handled); |
| 5175 |
| 5176 bool restore_context = context_restore_operand != NULL; |
| 5177 if (restore_context) { |
| 5178 __ Ldr(cp, *context_restore_operand); |
| 5179 } |
| 5180 |
| 5181 if (stack_space_operand != NULL) { |
| 5182 __ Ldr(w2, *stack_space_operand); |
| 5183 } |
| 5184 |
| 5185 __ LeaveExitFrame(false, x1, !restore_context); |
| 5186 if (stack_space_operand != NULL) { |
| 5187 __ Drop(x2, 1); |
| 5188 } else { |
| 5189 __ Drop(stack_space); |
| 5190 } |
| 5191 __ Ret(); |
| 5192 |
| 5193 __ Bind(&promote_scheduled_exception); |
| 5194 { |
| 5195 FrameScope frame(masm, StackFrame::INTERNAL); |
| 5196 __ CallExternalReference( |
| 5197 ExternalReference(Runtime::kPromoteScheduledException, isolate), 0); |
| 5198 } |
| 5199 __ B(&exception_handled); |
| 5200 |
| 5201 // HandleScope limit has changed. Delete allocated extensions. |
| 5202 __ Bind(&delete_allocated_handles); |
| 5203 __ Str(limit_reg, MemOperand(handle_scope_base, kLimitOffset)); |
| 5204 // Save the return value in a callee-save register. |
| 5205 Register saved_result = x19; |
| 5206 __ Mov(saved_result, x0); |
| 5207 __ Mov(x0, ExternalReference::isolate_address(isolate)); |
| 5208 __ CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate), |
| 5209 1); |
| 5210 __ Mov(x0, saved_result); |
| 5211 __ B(&leave_exit_frame); |
| 5212 } |
| 5213 |
| 5214 |
5046 static void CallApiFunctionStubHelper(MacroAssembler* masm, | 5215 static void CallApiFunctionStubHelper(MacroAssembler* masm, |
5047 const ParameterCount& argc, | 5216 const ParameterCount& argc, |
5048 bool return_first_arg, | 5217 bool return_first_arg, |
5049 bool call_data_undefined) { | 5218 bool call_data_undefined) { |
5050 // ----------- S t a t e ------------- | 5219 // ----------- S t a t e ------------- |
5051 // -- x0 : callee | 5220 // -- x0 : callee |
5052 // -- x4 : call_data | 5221 // -- x4 : call_data |
5053 // -- x2 : holder | 5222 // -- x2 : holder |
5054 // -- x1 : api_function_address | 5223 // -- x1 : api_function_address |
5055 // -- x3 : number of arguments if argc is a register | 5224 // -- x3 : number of arguments if argc is a register |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5153 int stack_space = 0; | 5322 int stack_space = 0; |
5154 MemOperand is_construct_call_operand = | 5323 MemOperand is_construct_call_operand = |
5155 MemOperand(masm->StackPointer(), 4 * kPointerSize); | 5324 MemOperand(masm->StackPointer(), 4 * kPointerSize); |
5156 MemOperand* stack_space_operand = &is_construct_call_operand; | 5325 MemOperand* stack_space_operand = &is_construct_call_operand; |
5157 if (argc.is_immediate()) { | 5326 if (argc.is_immediate()) { |
5158 stack_space = argc.immediate() + FCA::kArgsLength + 1; | 5327 stack_space = argc.immediate() + FCA::kArgsLength + 1; |
5159 stack_space_operand = NULL; | 5328 stack_space_operand = NULL; |
5160 } | 5329 } |
5161 | 5330 |
5162 const int spill_offset = 1 + kApiStackSpace; | 5331 const int spill_offset = 1 + kApiStackSpace; |
5163 __ CallApiFunctionAndReturn(api_function_address, thunk_ref, stack_space, | 5332 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space, |
5164 stack_space_operand, spill_offset, | 5333 stack_space_operand, spill_offset, |
5165 return_value_operand, &context_restore_operand); | 5334 return_value_operand, &context_restore_operand); |
5166 } | 5335 } |
5167 | 5336 |
5168 | 5337 |
5169 void CallApiFunctionStub::Generate(MacroAssembler* masm) { | 5338 void CallApiFunctionStub::Generate(MacroAssembler* masm) { |
5170 bool call_data_undefined = this->call_data_undefined(); | 5339 bool call_data_undefined = this->call_data_undefined(); |
5171 CallApiFunctionStubHelper(masm, ParameterCount(x3), false, | 5340 CallApiFunctionStubHelper(masm, ParameterCount(x3), false, |
5172 call_data_undefined); | 5341 call_data_undefined); |
5173 } | 5342 } |
5174 | 5343 |
5175 | 5344 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5209 // x1 (internal::Object** args_) as the data. | 5378 // x1 (internal::Object** args_) as the data. |
5210 __ Poke(x1, 1 * kPointerSize); | 5379 __ Poke(x1, 1 * kPointerSize); |
5211 __ Add(x1, masm->StackPointer(), 1 * kPointerSize); // x1 = AccessorInfo& | 5380 __ Add(x1, masm->StackPointer(), 1 * kPointerSize); // x1 = AccessorInfo& |
5212 | 5381 |
5213 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; | 5382 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; |
5214 | 5383 |
5215 ExternalReference thunk_ref = | 5384 ExternalReference thunk_ref = |
5216 ExternalReference::invoke_accessor_getter_callback(isolate()); | 5385 ExternalReference::invoke_accessor_getter_callback(isolate()); |
5217 | 5386 |
5218 const int spill_offset = 1 + kApiStackSpace; | 5387 const int spill_offset = 1 + kApiStackSpace; |
5219 __ CallApiFunctionAndReturn(api_function_address, thunk_ref, | 5388 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, |
5220 kStackUnwindSpace, NULL, spill_offset, | 5389 kStackUnwindSpace, NULL, spill_offset, |
5221 MemOperand(fp, 6 * kPointerSize), NULL); | 5390 MemOperand(fp, 6 * kPointerSize), NULL); |
5222 } | 5391 } |
5223 | 5392 |
5224 | 5393 |
5225 #undef __ | 5394 #undef __ |
5226 | 5395 |
5227 } } // namespace v8::internal | 5396 } } // namespace v8::internal |
5228 | 5397 |
5229 #endif // V8_TARGET_ARCH_ARM64 | 5398 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |