5 #if V8_TARGET_ARCH_ARM64 7 #include "src/api-arguments.h" 8 #include "src/arm64/assembler-arm64-inl.h" 9 #include "src/arm64/macro-assembler-arm64-inl.h" 10 #include "src/bootstrapper.h" 11 #include "src/code-stubs.h" 12 #include "src/counters.h" 13 #include "src/frame-constants.h" 14 #include "src/frames.h" 15 #include "src/ic/ic.h" 16 #include "src/ic/stub-cache.h" 17 #include "src/isolate.h" 18 #include "src/macro-assembler.h" 19 #include "src/objects/api-callbacks.h" 20 #include "src/objects/regexp-match-info.h" 21 #include "src/regexp/jsregexp.h" 22 #include "src/regexp/regexp-macro-assembler.h" 23 #include "src/runtime/runtime.h" 25 #include "src/arm64/code-stubs-arm64.h" 30 #define __ ACCESS_MASM(masm) 42 void JSEntryStub::Generate(MacroAssembler* masm) {
43 Label invoke, handler_entry, exit;
45 Register code_entry = x0;
48 NoRootArrayScope no_root_array(masm);
52 __ EnableInstrumentation();
54 __ PushCalleeSavedRegisters();
57 __ Fmov(fp_zero, 0.0);
60 __ InitializeRootRegister();
64 StackFrame::Type marker = type();
65 int64_t bad_frame_pointer = -1L;
66 __ Mov(x13, bad_frame_pointer);
67 __ Mov(x12, StackFrame::TypeToMarker(marker));
68 __ Mov(x11, ExternalReference::Create(IsolateAddressId::kCEntryFPAddress,
70 __ Ldr(x10, MemOperand(x11));
72 __ Push(x13, x12, xzr, x10);
74 __ Sub(fp, sp, EntryFrameConstants::kCallerFPOffset);
78 Label non_outermost_js, done;
79 ExternalReference js_entry_sp =
80 ExternalReference::Create(IsolateAddressId::kJSEntrySPAddress, isolate());
81 __ Mov(x10, js_entry_sp);
82 __ Ldr(x11, MemOperand(x10));
87 DCHECK_EQ(StackFrame::INNER_JSENTRY_FRAME, 0);
89 __ Csel(x12, xzr, StackFrame::OUTERMOST_JSENTRY_FRAME, ne);
91 __ Str(fp, MemOperand(x10));
114 Assembler::BlockPoolsScope block_pools(masm);
115 __ bind(&handler_entry);
116 handler_offset_ = handler_entry.pos();
121 __ Mov(x10, Operand(ExternalReference::Create(
122 IsolateAddressId::kPendingExceptionAddress, isolate())));
124 __ Str(code_entry, MemOperand(x10));
125 __ LoadRoot(x0, RootIndex::kException);
132 static_assert(StackHandlerConstants::kSize == 2 * kPointerSize,
133 "Unexpected offset for StackHandlerConstants::kSize");
134 static_assert(StackHandlerConstants::kNextOffset == 0 * kPointerSize,
135 "Unexpected offset for StackHandlerConstants::kNextOffset");
138 __ Mov(x11, ExternalReference::Create(IsolateAddressId::kHandlerAddress,
140 __ Ldr(x10, MemOperand(x11));
141 __ Push(padreg, x10);
145 UseScratchRegisterScope temps(masm);
146 Register scratch = temps.AcquireX();
148 __ Str(scratch, MemOperand(x11));
166 __ Call(EntryTrampoline(), RelocInfo::CODE_TARGET);
169 static_assert(StackHandlerConstants::kNextOffset == 0 * kPointerSize,
170 "Unexpected offset for StackHandlerConstants::kNextOffset");
172 __ Mov(x11, ExternalReference::Create(IsolateAddressId::kHandlerAddress,
174 __ Drop(StackHandlerConstants::kSlotCount - 2);
175 __ Str(x10, MemOperand(x11));
189 Label non_outermost_js_2;
191 Register c_entry_fp = x11;
192 __ PeekPair(x10, c_entry_fp, 1 * kPointerSize);
193 __ Cmp(x10, StackFrame::OUTERMOST_JSENTRY_FRAME);
194 __ B(ne, &non_outermost_js_2);
195 __ Mov(x12, js_entry_sp);
196 __ Str(xzr, MemOperand(x12));
197 __ Bind(&non_outermost_js_2);
200 __ Mov(x12, ExternalReference::Create(IsolateAddressId::kCEntryFPAddress,
202 __ Str(c_entry_fp, MemOperand(x12));
206 static_assert(EntryFrameConstants::kFixedFrameSize % (2 * kPointerSize) == 0,
207 "Size of entry frame is not a multiple of 16 bytes");
208 __ Drop(EntryFrameConstants::kFixedFrameSize / kPointerSize);
210 __ PopCalleeSavedRegisters();
214 void DirectCEntryStub::Generate(MacroAssembler* masm) {
221 __ AssertFPCRState();
225 void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
229 __ Call(GetCode(), RelocInfo::CODE_TARGET);
235 static const int kCallApiFunctionSpillSpace = 4;
238 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
239 return static_cast<int>(ref0.address() - ref1.address());
248 static void CallApiFunctionAndReturn(MacroAssembler* masm,
249 Register function_address,
250 ExternalReference thunk_ref,
251 int stack_space,
int spill_offset,
252 MemOperand return_value_operand) {
253 ASM_LOCATION(
"CallApiFunctionAndReturn");
254 Isolate* isolate = masm->isolate();
255 ExternalReference next_address =
256 ExternalReference::handle_scope_next_address(isolate);
257 const int kNextOffset = 0;
258 const int kLimitOffset = AddressOffset(
259 ExternalReference::handle_scope_limit_address(isolate), next_address);
260 const int kLevelOffset = AddressOffset(
261 ExternalReference::handle_scope_level_address(isolate), next_address);
263 DCHECK(function_address.is(x1) || function_address.is(x2));
265 Label profiler_disabled;
266 Label end_profiler_check;
267 __ Mov(x10, ExternalReference::is_profiling_address(isolate));
268 __ Ldrb(w10, MemOperand(x10));
269 __ Cbz(w10, &profiler_disabled);
270 __ Mov(x3, thunk_ref);
271 __ B(&end_profiler_check);
273 __ Bind(&profiler_disabled);
274 __ Mov(x3, function_address);
275 __ Bind(&end_profiler_check);
279 STATIC_ASSERT(kCallApiFunctionSpillSpace == 4);
280 __ Poke(x19, (spill_offset + 0) * kXRegSize);
281 __ Poke(x20, (spill_offset + 1) * kXRegSize);
282 __ Poke(x21, (spill_offset + 2) * kXRegSize);
283 __ Poke(x22, (spill_offset + 3) * kXRegSize);
288 Register handle_scope_base = x22;
289 Register next_address_reg = x19;
290 Register limit_reg = x20;
291 Register level_reg = w21;
293 __ Mov(handle_scope_base, next_address);
294 __ Ldr(next_address_reg, MemOperand(handle_scope_base, kNextOffset));
295 __ Ldr(limit_reg, MemOperand(handle_scope_base, kLimitOffset));
296 __ Ldr(level_reg, MemOperand(handle_scope_base, kLevelOffset));
297 __ Add(level_reg, level_reg, 1);
298 __ Str(level_reg, MemOperand(handle_scope_base, kLevelOffset));
300 if (FLAG_log_timer_events) {
301 FrameScope frame(masm, StackFrame::MANUAL);
302 __ PushSafepointRegisters();
303 __ Mov(x0, ExternalReference::isolate_address(isolate));
304 __ CallCFunction(ExternalReference::log_enter_external_function(), 1);
305 __ PopSafepointRegisters();
311 DirectCEntryStub stub(isolate);
312 stub.GenerateCall(masm, x3);
314 if (FLAG_log_timer_events) {
315 FrameScope frame(masm, StackFrame::MANUAL);
316 __ PushSafepointRegisters();
317 __ Mov(x0, ExternalReference::isolate_address(isolate));
318 __ CallCFunction(ExternalReference::log_leave_external_function(), 1);
319 __ PopSafepointRegisters();
322 Label promote_scheduled_exception;
323 Label delete_allocated_handles;
324 Label leave_exit_frame;
325 Label return_value_loaded;
328 __ Ldr(x0, return_value_operand);
329 __ Bind(&return_value_loaded);
332 __ Str(next_address_reg, MemOperand(handle_scope_base, kNextOffset));
333 if (__ emit_debug_code()) {
334 __ Ldr(w1, MemOperand(handle_scope_base, kLevelOffset));
335 __ Cmp(w1, level_reg);
336 __ Check(eq, AbortReason::kUnexpectedLevelAfterReturnFromApiCall);
338 __ Sub(level_reg, level_reg, 1);
339 __ Str(level_reg, MemOperand(handle_scope_base, kLevelOffset));
340 __ Ldr(x1, MemOperand(handle_scope_base, kLimitOffset));
341 __ Cmp(limit_reg, x1);
342 __ B(ne, &delete_allocated_handles);
345 __ Bind(&leave_exit_frame);
347 __ Peek(x19, (spill_offset + 0) * kXRegSize);
348 __ Peek(x20, (spill_offset + 1) * kXRegSize);
349 __ Peek(x21, (spill_offset + 2) * kXRegSize);
350 __ Peek(x22, (spill_offset + 3) * kXRegSize);
352 __ LeaveExitFrame(
false, x1, x5);
355 __ Mov(x5, ExternalReference::scheduled_exception_address(isolate));
356 __ Ldr(x5, MemOperand(x5));
357 __ JumpIfNotRoot(x5, RootIndex::kTheHoleValue, &promote_scheduled_exception);
359 __ DropSlots(stack_space);
363 __ Bind(&promote_scheduled_exception);
364 __ TailCallRuntime(Runtime::kPromoteScheduledException);
367 __ Bind(&delete_allocated_handles);
368 __ Str(limit_reg, MemOperand(handle_scope_base, kLimitOffset));
370 Register saved_result = x19;
371 __ Mov(saved_result, x0);
372 __ Mov(x0, ExternalReference::isolate_address(isolate));
373 __ CallCFunction(ExternalReference::delete_handle_scope_extensions(), 1);
374 __ Mov(x0, saved_result);
375 __ B(&leave_exit_frame);
378 void CallApiCallbackStub::Generate(MacroAssembler* masm) {
391 Register call_data = x4;
392 Register holder = x2;
393 Register api_function_address = x1;
395 typedef FunctionCallbackArguments FCA;
397 STATIC_ASSERT(FCA::kArgsLength == 6);
398 STATIC_ASSERT(FCA::kNewTargetIndex == 5);
399 STATIC_ASSERT(FCA::kDataIndex == 4);
400 STATIC_ASSERT(FCA::kReturnValueOffset == 3);
401 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
402 STATIC_ASSERT(FCA::kIsolateIndex == 1);
403 STATIC_ASSERT(FCA::kHolderIndex == 0);
406 __ LoadRoot(undef, RootIndex::kUndefinedValue);
409 __ Push(undef, call_data);
411 Register isolate_reg = x5;
412 __ Mov(isolate_reg, ExternalReference::isolate_address(masm->isolate()));
416 __ Push(undef, undef, isolate_reg, holder);
424 const int kApiStackSpace = 3;
428 const int kCallApiFunctionSpillSpace = 4;
430 FrameScope frame_scope(masm, StackFrame::MANUAL);
431 __ EnterExitFrame(
false, x10, kApiStackSpace + kCallApiFunctionSpillSpace);
433 DCHECK(!AreAliased(x0, api_function_address));
436 __ SlotAddress(x0, 1);
438 __ Add(x10, args, Operand((FCA::kArgsLength - 1 + argc()) * kPointerSize));
439 __ Stp(args, x10, MemOperand(x0, 0 * kPointerSize));
442 __ Str(x10, MemOperand(x0, 2 * kPointerSize));
444 ExternalReference thunk_ref = ExternalReference::invoke_function_callback();
446 AllowExternalCallThatCantCauseGC scope(masm);
448 int return_value_offset = 2 + FCA::kReturnValueOffset;
449 MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
453 const int stack_space = (argc() + 1) + FCA::kArgsLength;
456 DCHECK_EQ((stack_space - (argc() + 1)) % 2, 0);
457 const int spill_offset = 1 + kApiStackSpace;
458 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
459 spill_offset, return_value_operand);
463 void CallApiGetterStub::Generate(MacroAssembler* masm) {
464 STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
465 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
466 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
467 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
468 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
469 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
470 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
471 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
473 Register receiver = ApiGetterDescriptor::ReceiverRegister();
474 Register holder = ApiGetterDescriptor::HolderRegister();
475 Register callback = ApiGetterDescriptor::CallbackRegister();
478 Register isolate_address = x6;
480 DCHECK(!AreAliased(receiver, holder, callback, data, undef, isolate_address,
483 __ Ldr(data, FieldMemOperand(callback, AccessorInfo::kDataOffset));
484 __ LoadRoot(undef, RootIndex::kUndefinedValue);
485 __ Mov(isolate_address, ExternalReference::isolate_address(isolate()));
486 __ Ldr(name, FieldMemOperand(callback, AccessorInfo::kNameOffset));
493 __ Push(receiver, data, undef, undef, isolate_address, holder, xzr, name);
496 static const int kStackUnwindSpace =
497 PropertyCallbackArguments::kArgsLength + 1;
498 static_assert(kStackUnwindSpace % 2 == 0,
499 "slots must be a multiple of 2 for stack pointer alignment");
503 __ Add(x1, x0, 1 * kPointerSize);
505 const int kApiStackSpace = 1;
509 const int kCallApiFunctionSpillSpace = 4;
511 FrameScope frame_scope(masm, StackFrame::MANUAL);
512 __ EnterExitFrame(
false, x10, kApiStackSpace + kCallApiFunctionSpillSpace);
516 __ Poke(x1, 1 * kPointerSize);
517 __ SlotAddress(x1, 1);
520 ExternalReference thunk_ref =
521 ExternalReference::invoke_accessor_getter_callback();
523 Register api_function_address = x2;
524 Register js_getter = x4;
525 __ Ldr(js_getter, FieldMemOperand(callback, AccessorInfo::kJsGetterOffset));
526 __ Ldr(api_function_address,
527 FieldMemOperand(js_getter, Foreign::kForeignAddressOffset));
529 const int spill_offset = 1 + kApiStackSpace;
531 MemOperand return_value_operand(
532 fp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize);
533 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
534 kStackUnwindSpace, spill_offset,
535 return_value_operand);
543 #endif // V8_TARGET_ARCH_ARM64