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
3// found in the LICENSE file.
4
5#if V8_TARGET_ARCH_X64
6
7#include "src/api/api-arguments.h"
8#include "src/base/bits-iterator.h"
9#include "src/base/iterator.h"
10#include "src/codegen/code-factory.h"
11#include "src/codegen/interface-descriptors-inl.h"
12// For interpreter_entry_return_pc_offset. TODO(jkummerow): Drop.
13#include "src/codegen/macro-assembler-inl.h"
14#include "src/codegen/register-configuration.h"
15#include "src/codegen/x64/assembler-x64.h"
16#include "src/common/globals.h"
17#include "src/deoptimizer/deoptimizer.h"
18#include "src/execution/frame-constants.h"
19#include "src/execution/frames.h"
20#include "src/heap/heap-inl.h"
21#include "src/logging/counters.h"
22#include "src/objects/cell.h"
23#include "src/objects/code.h"
24#include "src/objects/debug-objects.h"
25#include "src/objects/foreign.h"
26#include "src/objects/heap-number.h"
27#include "src/objects/js-generator.h"
28#include "src/objects/objects-inl.h"
29#include "src/objects/smi.h"
30
31#if V8_ENABLE_WEBASSEMBLY
32#include "src/wasm/baseline/liftoff-assembler-defs.h"
33#include "src/wasm/object-access.h"
34#include "src/wasm/wasm-constants.h"
35#include "src/wasm/wasm-linkage.h"
36#include "src/wasm/wasm-objects.h"
37#endif  // V8_ENABLE_WEBASSEMBLY
38
39namespace v8 {
40namespace internal {
41
42#define __ ACCESS_MASM(masm)
43
44void Builtins::Generate_Adaptor(MacroAssembler* masm, Address address) {
45  __ LoadAddress(kJavaScriptCallExtraArg1Register,
46                 ExternalReference::Create(address));
47  __ Jump(BUILTIN_CODE(masm->isolate(), AdaptorWithBuiltinExitFrame),
48          RelocInfo::CODE_TARGET);
49}
50
51static void GenerateTailCallToReturnedCode(
52    MacroAssembler* masm, Runtime::FunctionId function_id,
53    JumpMode jump_mode = JumpMode::kJump) {
54  // ----------- S t a t e -------------
55  //  -- rax : actual argument count
56  //  -- rdx : new target (preserved for callee)
57  //  -- rdi : target function (preserved for callee)
58  // -----------------------------------
59  ASM_CODE_COMMENT(masm);
60  {
61    FrameScope scope(masm, StackFrame::INTERNAL);
62    // Push a copy of the target function, the new target and the actual
63    // argument count.
64    __ Push(kJavaScriptCallTargetRegister);
65    __ Push(kJavaScriptCallNewTargetRegister);
66    __ SmiTag(kJavaScriptCallArgCountRegister);
67    __ Push(kJavaScriptCallArgCountRegister);
68    // Function is also the parameter to the runtime call.
69    __ Push(kJavaScriptCallTargetRegister);
70
71    __ CallRuntime(function_id, 1);
72    __ movq(rcx, rax);
73
74    // Restore target function, new target and actual argument count.
75    __ Pop(kJavaScriptCallArgCountRegister);
76    __ SmiUntag(kJavaScriptCallArgCountRegister);
77    __ Pop(kJavaScriptCallNewTargetRegister);
78    __ Pop(kJavaScriptCallTargetRegister);
79  }
80  static_assert(kJavaScriptCallCodeStartRegister == rcx, "ABI mismatch");
81  __ JumpCodeTObject(rcx, jump_mode);
82}
83
84namespace {
85
86enum class ArgumentsElementType {
87  kRaw,    // Push arguments as they are.
88  kHandle  // Dereference arguments before pushing.
89};
90
91void Generate_PushArguments(MacroAssembler* masm, Register array, Register argc,
92                            Register scratch,
93                            ArgumentsElementType element_type) {
94  DCHECK(!AreAliased(array, argc, scratch, kScratchRegister));
95  Register counter = scratch;
96  Label loop, entry;
97  __ leaq(counter, Operand(argc, -kJSArgcReceiverSlots));
98  __ jmp(&entry);
99  __ bind(&loop);
100  Operand value(array, counter, times_system_pointer_size, 0);
101  if (element_type == ArgumentsElementType::kHandle) {
102    __ movq(kScratchRegister, value);
103    value = Operand(kScratchRegister, 0);
104  }
105  __ Push(value);
106  __ bind(&entry);
107  __ decq(counter);
108  __ j(greater_equal, &loop, Label::kNear);
109}
110
111void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
112  // ----------- S t a t e -------------
113  //  -- rax: number of arguments
114  //  -- rdi: constructor function
115  //  -- rdx: new target
116  //  -- rsi: context
117  // -----------------------------------
118
119  Label stack_overflow;
120  __ StackOverflowCheck(rax, &stack_overflow, Label::kFar);
121
122  // Enter a construct frame.
123  {
124    FrameScope scope(masm, StackFrame::CONSTRUCT);
125
126    // Preserve the incoming parameters on the stack.
127    __ SmiTag(rcx, rax);
128    __ Push(rsi);
129    __ Push(rcx);
130
131    // TODO(victorgomes): When the arguments adaptor is completely removed, we
132    // should get the formal parameter count and copy the arguments in its
133    // correct position (including any undefined), instead of delaying this to
134    // InvokeFunction.
135
136    // Set up pointer to first argument (skip receiver).
137    __ leaq(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset +
138                                  kSystemPointerSize));
139    // Copy arguments to the expression stack.
140    // rbx: Pointer to start of arguments.
141    // rax: Number of arguments.
142    Generate_PushArguments(masm, rbx, rax, rcx, ArgumentsElementType::kRaw);
143    // The receiver for the builtin/api call.
144    __ PushRoot(RootIndex::kTheHoleValue);
145
146    // Call the function.
147    // rax: number of arguments (untagged)
148    // rdi: constructor function
149    // rdx: new target
150    __ InvokeFunction(rdi, rdx, rax, InvokeType::kCall);
151
152    // Restore smi-tagged arguments count from the frame.
153    __ movq(rbx, Operand(rbp, ConstructFrameConstants::kLengthOffset));
154
155    // Leave construct frame.
156  }
157
158  // Remove caller arguments from the stack and return.
159  __ DropArguments(rbx, rcx, MacroAssembler::kCountIsSmi,
160                   TurboAssembler::kCountIncludesReceiver);
161
162  __ ret(0);
163
164  __ bind(&stack_overflow);
165  {
166    FrameScope scope(masm, StackFrame::INTERNAL);
167    __ CallRuntime(Runtime::kThrowStackOverflow);
168    __ int3();  // This should be unreachable.
169  }
170}
171
172}  // namespace
173
174// The construct stub for ES5 constructor functions and ES6 class constructors.
175void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
176  // ----------- S t a t e -------------
177  //  -- rax: number of arguments (untagged)
178  //  -- rdi: constructor function
179  //  -- rdx: new target
180  //  -- rsi: context
181  //  -- sp[...]: constructor arguments
182  // -----------------------------------
183
184  FrameScope scope(masm, StackFrame::MANUAL);
185  // Enter a construct frame.
186  __ EnterFrame(StackFrame::CONSTRUCT);
187  Label post_instantiation_deopt_entry, not_create_implicit_receiver;
188
189  // Preserve the incoming parameters on the stack.
190  __ SmiTag(rcx, rax);
191  __ Push(rsi);
192  __ Push(rcx);
193  __ Push(rdi);
194  __ PushRoot(RootIndex::kTheHoleValue);
195  __ Push(rdx);
196
197  // ----------- S t a t e -------------
198  //  --         sp[0*kSystemPointerSize]: new target
199  //  --         sp[1*kSystemPointerSize]: padding
200  //  -- rdi and sp[2*kSystemPointerSize]: constructor function
201  //  --         sp[3*kSystemPointerSize]: argument count
202  //  --         sp[4*kSystemPointerSize]: context
203  // -----------------------------------
204
205  __ LoadTaggedPointerField(
206      rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
207  __ movl(rbx, FieldOperand(rbx, SharedFunctionInfo::kFlagsOffset));
208  __ DecodeField<SharedFunctionInfo::FunctionKindBits>(rbx);
209  __ JumpIfIsInRange(
210      rbx, static_cast<uint32_t>(FunctionKind::kDefaultDerivedConstructor),
211      static_cast<uint32_t>(FunctionKind::kDerivedConstructor),
212      &not_create_implicit_receiver, Label::kNear);
213
214  // If not derived class constructor: Allocate the new receiver object.
215  __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
216  __ Call(BUILTIN_CODE(masm->isolate(), FastNewObject), RelocInfo::CODE_TARGET);
217  __ jmp(&post_instantiation_deopt_entry, Label::kNear);
218
219  // Else: use TheHoleValue as receiver for constructor call
220  __ bind(&not_create_implicit_receiver);
221  __ LoadRoot(rax, RootIndex::kTheHoleValue);
222
223  // ----------- S t a t e -------------
224  //  -- rax                          implicit receiver
225  //  -- Slot 4 / sp[0*kSystemPointerSize]  new target
226  //  -- Slot 3 / sp[1*kSystemPointerSize]  padding
227  //  -- Slot 2 / sp[2*kSystemPointerSize]  constructor function
228  //  -- Slot 1 / sp[3*kSystemPointerSize]  number of arguments (tagged)
229  //  -- Slot 0 / sp[4*kSystemPointerSize]  context
230  // -----------------------------------
231  // Deoptimizer enters here.
232  masm->isolate()->heap()->SetConstructStubCreateDeoptPCOffset(
233      masm->pc_offset());
234  __ bind(&post_instantiation_deopt_entry);
235
236  // Restore new target.
237  __ Pop(rdx);
238
239  // Push the allocated receiver to the stack.
240  __ Push(rax);
241
242  // We need two copies because we may have to return the original one
243  // and the calling conventions dictate that the called function pops the
244  // receiver. The second copy is pushed after the arguments, we saved in r8
245  // since rax needs to store the number of arguments before
246  // InvokingFunction.
247  __ movq(r8, rax);
248
249  // Set up pointer to first argument (skip receiver).
250  __ leaq(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset +
251                                kSystemPointerSize));
252
253  // Restore constructor function and argument count.
254  __ movq(rdi, Operand(rbp, ConstructFrameConstants::kConstructorOffset));
255  __ SmiUntag(rax, Operand(rbp, ConstructFrameConstants::kLengthOffset));
256
257  // Check if we have enough stack space to push all arguments.
258  // Argument count in rax.
259  Label stack_overflow;
260  __ StackOverflowCheck(rax, &stack_overflow);
261
262  // TODO(victorgomes): When the arguments adaptor is completely removed, we
263  // should get the formal parameter count and copy the arguments in its
264  // correct position (including any undefined), instead of delaying this to
265  // InvokeFunction.
266
267  // Copy arguments to the expression stack.
268  // rbx: Pointer to start of arguments.
269  // rax: Number of arguments.
270  Generate_PushArguments(masm, rbx, rax, rcx, ArgumentsElementType::kRaw);
271
272  // Push implicit receiver.
273  __ Push(r8);
274
275  // Call the function.
276  __ InvokeFunction(rdi, rdx, rax, InvokeType::kCall);
277
278  // ----------- S t a t e -------------
279  //  -- rax                 constructor result
280  //  -- sp[0*kSystemPointerSize]  implicit receiver
281  //  -- sp[1*kSystemPointerSize]  padding
282  //  -- sp[2*kSystemPointerSize]  constructor function
283  //  -- sp[3*kSystemPointerSize]  number of arguments
284  //  -- sp[4*kSystemPointerSize]  context
285  // -----------------------------------
286
287  // Store offset of return address for deoptimizer.
288  masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset(
289      masm->pc_offset());
290
291  // If the result is an object (in the ECMA sense), we should get rid
292  // of the receiver and use the result; see ECMA-262 section 13.2.2-7
293  // on page 74.
294  Label use_receiver, do_throw, leave_and_return, check_result;
295
296  // If the result is undefined, we'll use the implicit receiver. Otherwise we
297  // do a smi check and fall through to check if the return value is a valid
298  // receiver.
299  __ JumpIfNotRoot(rax, RootIndex::kUndefinedValue, &check_result,
300                   Label::kNear);
301
302  // Throw away the result of the constructor invocation and use the
303  // on-stack receiver as the result.
304  __ bind(&use_receiver);
305  __ movq(rax, Operand(rsp, 0 * kSystemPointerSize));
306  __ JumpIfRoot(rax, RootIndex::kTheHoleValue, &do_throw, Label::kNear);
307
308  __ bind(&leave_and_return);
309  // Restore the arguments count.
310  __ movq(rbx, Operand(rbp, ConstructFrameConstants::kLengthOffset));
311  __ LeaveFrame(StackFrame::CONSTRUCT);
312  // Remove caller arguments from the stack and return.
313  __ DropArguments(rbx, rcx, MacroAssembler::kCountIsSmi,
314                   TurboAssembler::kCountIncludesReceiver);
315  __ ret(0);
316
317  // If the result is a smi, it is *not* an object in the ECMA sense.
318  __ bind(&check_result);
319  __ JumpIfSmi(rax, &use_receiver, Label::kNear);
320
321  // If the type of the result (stored in its map) is less than
322  // FIRST_JS_RECEIVER_TYPE, it is not an object in the ECMA sense.
323  STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
324  __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rcx);
325  __ j(above_equal, &leave_and_return, Label::kNear);
326  __ jmp(&use_receiver);
327
328  __ bind(&do_throw);
329  // Restore context from the frame.
330  __ movq(rsi, Operand(rbp, ConstructFrameConstants::kContextOffset));
331  __ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
332  // We don't return here.
333  __ int3();
334
335  __ bind(&stack_overflow);
336  // Restore the context from the frame.
337  __ movq(rsi, Operand(rbp, ConstructFrameConstants::kContextOffset));
338  __ CallRuntime(Runtime::kThrowStackOverflow);
339  // This should be unreachable.
340  __ int3();
341}
342
343void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
344  Generate_JSBuiltinsConstructStubHelper(masm);
345}
346
347void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
348  FrameScope scope(masm, StackFrame::INTERNAL);
349  __ Push(rdi);
350  __ CallRuntime(Runtime::kThrowConstructedNonConstructable);
351}
352
353namespace {
354
355// Called with the native C calling convention. The corresponding function
356// signature is either:
357//   using JSEntryFunction = GeneratedCode<Address(
358//       Address root_register_value, Address new_target, Address target,
359//       Address receiver, intptr_t argc, Address** argv)>;
360// or
361//   using JSEntryFunction = GeneratedCode<Address(
362//       Address root_register_value, MicrotaskQueue* microtask_queue)>;
363void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
364                             Builtin entry_trampoline) {
365  Label invoke, handler_entry, exit;
366  Label not_outermost_js, not_outermost_js_2;
367
368  {
369    NoRootArrayScope uninitialized_root_register(masm);
370    // Set up frame.
371    __ pushq(rbp);
372    __ movq(rbp, rsp);
373
374    // Push the stack frame type.
375    __ Push(Immediate(StackFrame::TypeToMarker(type)));
376    // Reserve a slot for the context. It is filled after the root register has
377    // been set up.
378    __ AllocateStackSpace(kSystemPointerSize);
379    // Save callee-saved registers (X64/X32/Win64 calling conventions).
380    __ pushq(r12);
381    __ pushq(r13);
382    __ pushq(r14);
383    __ pushq(r15);
384#ifdef V8_TARGET_OS_WIN
385    __ pushq(rdi);  // Only callee save in Win64 ABI, argument in AMD64 ABI.
386    __ pushq(rsi);  // Only callee save in Win64 ABI, argument in AMD64 ABI.
387#endif
388    __ pushq(rbx);
389
390#ifdef V8_TARGET_OS_WIN
391    // On Win64 XMM6-XMM15 are callee-save.
392    __ AllocateStackSpace(EntryFrameConstants::kXMMRegistersBlockSize);
393    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 0), xmm6);
394    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 1), xmm7);
395    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 2), xmm8);
396    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 3), xmm9);
397    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 4), xmm10);
398    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 5), xmm11);
399    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 6), xmm12);
400    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 7), xmm13);
401    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 8), xmm14);
402    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 9), xmm15);
403    STATIC_ASSERT(EntryFrameConstants::kCalleeSaveXMMRegisters == 10);
404    STATIC_ASSERT(EntryFrameConstants::kXMMRegistersBlockSize ==
405                  EntryFrameConstants::kXMMRegisterSize *
406                      EntryFrameConstants::kCalleeSaveXMMRegisters);
407#endif
408
409    // Initialize the root register.
410    // C calling convention. The first argument is passed in arg_reg_1.
411    __ movq(kRootRegister, arg_reg_1);
412
413#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
414    // Initialize the pointer cage base register.
415    __ LoadRootRelative(kPtrComprCageBaseRegister,
416                        IsolateData::cage_base_offset());
417#endif
418  }
419
420  // Save copies of the top frame descriptor on the stack.
421  ExternalReference c_entry_fp = ExternalReference::Create(
422      IsolateAddressId::kCEntryFPAddress, masm->isolate());
423  {
424    Operand c_entry_fp_operand = masm->ExternalReferenceAsOperand(c_entry_fp);
425    __ Push(c_entry_fp_operand);
426
427    // Clear c_entry_fp, now we've pushed its previous value to the stack.
428    // If the c_entry_fp is not already zero and we don't clear it, the
429    // SafeStackFrameIterator will assume we are executing C++ and miss the JS
430    // frames on top.
431    __ Move(c_entry_fp_operand, 0);
432  }
433
434  // Store the context address in the previously-reserved slot.
435  ExternalReference context_address = ExternalReference::Create(
436      IsolateAddressId::kContextAddress, masm->isolate());
437  __ Load(kScratchRegister, context_address);
438  static constexpr int kOffsetToContextSlot = -2 * kSystemPointerSize;
439  __ movq(Operand(rbp, kOffsetToContextSlot), kScratchRegister);
440
441  // If this is the outermost JS call, set js_entry_sp value.
442  ExternalReference js_entry_sp = ExternalReference::Create(
443      IsolateAddressId::kJSEntrySPAddress, masm->isolate());
444  __ Load(rax, js_entry_sp);
445  __ testq(rax, rax);
446  __ j(not_zero, &not_outermost_js);
447  __ Push(Immediate(StackFrame::OUTERMOST_JSENTRY_FRAME));
448  __ movq(rax, rbp);
449  __ Store(js_entry_sp, rax);
450  Label cont;
451  __ jmp(&cont);
452  __ bind(&not_outermost_js);
453  __ Push(Immediate(StackFrame::INNER_JSENTRY_FRAME));
454  __ bind(&cont);
455
456  // Jump to a faked try block that does the invoke, with a faked catch
457  // block that sets the pending exception.
458  __ jmp(&invoke);
459  __ bind(&handler_entry);
460
461  // Store the current pc as the handler offset. It's used later to create the
462  // handler table.
463  masm->isolate()->builtins()->SetJSEntryHandlerOffset(handler_entry.pos());
464
465  // Caught exception: Store result (exception) in the pending exception
466  // field in the JSEnv and return a failure sentinel.
467  ExternalReference pending_exception = ExternalReference::Create(
468      IsolateAddressId::kPendingExceptionAddress, masm->isolate());
469  __ Store(pending_exception, rax);
470  __ LoadRoot(rax, RootIndex::kException);
471  __ jmp(&exit);
472
473  // Invoke: Link this frame into the handler chain.
474  __ bind(&invoke);
475  __ PushStackHandler();
476
477  // Invoke the function by calling through JS entry trampoline builtin and
478  // pop the faked function when we return.
479  Handle<CodeT> trampoline_code =
480      masm->isolate()->builtins()->code_handle(entry_trampoline);
481  __ Call(trampoline_code, RelocInfo::CODE_TARGET);
482
483  // Unlink this frame from the handler chain.
484  __ PopStackHandler();
485
486  __ bind(&exit);
487  // Check if the current stack frame is marked as the outermost JS frame.
488  __ Pop(rbx);
489  __ cmpq(rbx, Immediate(StackFrame::OUTERMOST_JSENTRY_FRAME));
490  __ j(not_equal, &not_outermost_js_2);
491  __ Move(kScratchRegister, js_entry_sp);
492  __ movq(Operand(kScratchRegister, 0), Immediate(0));
493  __ bind(&not_outermost_js_2);
494
495  // Restore the top frame descriptor from the stack.
496  {
497    Operand c_entry_fp_operand = masm->ExternalReferenceAsOperand(c_entry_fp);
498    __ Pop(c_entry_fp_operand);
499  }
500
501  // Restore callee-saved registers (X64 conventions).
502#ifdef V8_TARGET_OS_WIN
503  // On Win64 XMM6-XMM15 are callee-save
504  __ movdqu(xmm6, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 0));
505  __ movdqu(xmm7, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 1));
506  __ movdqu(xmm8, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 2));
507  __ movdqu(xmm9, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 3));
508  __ movdqu(xmm10, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 4));
509  __ movdqu(xmm11, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 5));
510  __ movdqu(xmm12, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 6));
511  __ movdqu(xmm13, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 7));
512  __ movdqu(xmm14, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 8));
513  __ movdqu(xmm15, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 9));
514  __ addq(rsp, Immediate(EntryFrameConstants::kXMMRegistersBlockSize));
515#endif
516
517  __ popq(rbx);
518#ifdef V8_TARGET_OS_WIN
519  // Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI.
520  __ popq(rsi);
521  __ popq(rdi);
522#endif
523  __ popq(r15);
524  __ popq(r14);
525  __ popq(r13);
526  __ popq(r12);
527  __ addq(rsp, Immediate(2 * kSystemPointerSize));  // remove markers
528
529  // Restore frame pointer and return.
530  __ popq(rbp);
531  __ ret(0);
532}
533
534}  // namespace
535
536void Builtins::Generate_JSEntry(MacroAssembler* masm) {
537  Generate_JSEntryVariant(masm, StackFrame::ENTRY, Builtin::kJSEntryTrampoline);
538}
539
540void Builtins::Generate_JSConstructEntry(MacroAssembler* masm) {
541  Generate_JSEntryVariant(masm, StackFrame::CONSTRUCT_ENTRY,
542                          Builtin::kJSConstructEntryTrampoline);
543}
544
545void Builtins::Generate_JSRunMicrotasksEntry(MacroAssembler* masm) {
546  Generate_JSEntryVariant(masm, StackFrame::ENTRY,
547                          Builtin::kRunMicrotasksTrampoline);
548}
549
550static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
551                                             bool is_construct) {
552  // Expects six C++ function parameters.
553  // - Address root_register_value
554  // - Address new_target (tagged Object pointer)
555  // - Address function (tagged JSFunction pointer)
556  // - Address receiver (tagged Object pointer)
557  // - intptr_t argc
558  // - Address** argv (pointer to array of tagged Object pointers)
559  // (see Handle::Invoke in execution.cc).
560
561  // Open a C++ scope for the FrameScope.
562  {
563    // Platform specific argument handling. After this, the stack contains
564    // an internal frame and the pushed function and receiver, and
565    // register rax and rbx holds the argument count and argument array,
566    // while rdi holds the function pointer, rsi the context, and rdx the
567    // new.target.
568
569    // MSVC parameters in:
570    // rcx        : root_register_value
571    // rdx        : new_target
572    // r8         : function
573    // r9         : receiver
574    // [rsp+0x20] : argc
575    // [rsp+0x28] : argv
576    //
577    // GCC parameters in:
578    // rdi : root_register_value
579    // rsi : new_target
580    // rdx : function
581    // rcx : receiver
582    // r8  : argc
583    // r9  : argv
584
585    __ movq(rdi, arg_reg_3);
586    __ Move(rdx, arg_reg_2);
587    // rdi : function
588    // rdx : new_target
589
590    // Clear the context before we push it when entering the internal frame.
591    __ Move(rsi, 0);
592
593    // Enter an internal frame.
594    FrameScope scope(masm, StackFrame::INTERNAL);
595
596    // Setup the context (we need to use the caller context from the isolate).
597    ExternalReference context_address = ExternalReference::Create(
598        IsolateAddressId::kContextAddress, masm->isolate());
599    __ movq(rsi, masm->ExternalReferenceAsOperand(context_address));
600
601    // Push the function onto the stack.
602    __ Push(rdi);
603
604#ifdef V8_TARGET_OS_WIN
605    // Load the previous frame pointer to access C arguments on stack
606    __ movq(kScratchRegister, Operand(rbp, 0));
607    // Load the number of arguments and setup pointer to the arguments.
608    __ movq(rax, Operand(kScratchRegister, EntryFrameConstants::kArgcOffset));
609    __ movq(rbx, Operand(kScratchRegister, EntryFrameConstants::kArgvOffset));
610#else   // V8_TARGET_OS_WIN
611    // Load the number of arguments and setup pointer to the arguments.
612    __ movq(rax, r8);
613    __ movq(rbx, r9);
614    __ movq(r9, arg_reg_4);  // Temporarily saving the receiver.
615#endif  // V8_TARGET_OS_WIN
616
617    // Current stack contents:
618    // [rsp + kSystemPointerSize]     : Internal frame
619    // [rsp]                          : function
620    // Current register contents:
621    // rax : argc
622    // rbx : argv
623    // rsi : context
624    // rdi : function
625    // rdx : new.target
626    // r9  : receiver
627
628    // Check if we have enough stack space to push all arguments.
629    // Argument count in rax.
630    Label enough_stack_space, stack_overflow;
631    __ StackOverflowCheck(rax, &stack_overflow, Label::kNear);
632    __ jmp(&enough_stack_space, Label::kNear);
633
634    __ bind(&stack_overflow);
635    __ CallRuntime(Runtime::kThrowStackOverflow);
636    // This should be unreachable.
637    __ int3();
638
639    __ bind(&enough_stack_space);
640
641    // Copy arguments to the stack.
642    // Register rbx points to array of pointers to handle locations.
643    // Push the values of these handles.
644    // rbx: Pointer to start of arguments.
645    // rax: Number of arguments.
646    Generate_PushArguments(masm, rbx, rax, rcx, ArgumentsElementType::kHandle);
647
648    // Push the receiver.
649    __ Push(r9);
650
651    // Invoke the builtin code.
652    Handle<CodeT> builtin = is_construct
653                                ? BUILTIN_CODE(masm->isolate(), Construct)
654                                : masm->isolate()->builtins()->Call();
655    __ Call(builtin, RelocInfo::CODE_TARGET);
656
657    // Exit the internal frame. Notice that this also removes the empty
658    // context and the function left on the stack by the code
659    // invocation.
660  }
661
662  __ ret(0);
663}
664
665void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
666  Generate_JSEntryTrampolineHelper(masm, false);
667}
668
669void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
670  Generate_JSEntryTrampolineHelper(masm, true);
671}
672
673void Builtins::Generate_RunMicrotasksTrampoline(MacroAssembler* masm) {
674  // arg_reg_2: microtask_queue
675  __ movq(RunMicrotasksDescriptor::MicrotaskQueueRegister(), arg_reg_2);
676  __ Jump(BUILTIN_CODE(masm->isolate(), RunMicrotasks), RelocInfo::CODE_TARGET);
677}
678
679static void AssertCodeTIsBaselineAllowClobber(MacroAssembler* masm,
680                                              Register code, Register scratch) {
681  // Verify that the code kind is baseline code via the CodeKind.
682  __ movl(scratch, FieldOperand(code, CodeT::kFlagsOffset));
683  __ DecodeField<CodeT::KindField>(scratch);
684  __ cmpl(scratch, Immediate(static_cast<int>(CodeKind::BASELINE)));
685  __ Assert(equal, AbortReason::kExpectedBaselineData);
686}
687
688static void AssertCodeTIsBaseline(MacroAssembler* masm, Register code,
689                                  Register scratch) {
690  DCHECK(!AreAliased(code, scratch));
691  return AssertCodeTIsBaselineAllowClobber(masm, code, scratch);
692}
693
694static void GetSharedFunctionInfoBytecodeOrBaseline(MacroAssembler* masm,
695                                                    Register sfi_data,
696                                                    Register scratch1,
697                                                    Label* is_baseline) {
698  ASM_CODE_COMMENT(masm);
699  Label done;
700  __ LoadMap(scratch1, sfi_data);
701
702  __ CmpInstanceType(scratch1, CODET_TYPE);
703  if (FLAG_debug_code) {
704    Label not_baseline;
705    __ j(not_equal, &not_baseline);
706    AssertCodeTIsBaseline(masm, sfi_data, scratch1);
707    __ j(equal, is_baseline);
708    __ bind(&not_baseline);
709  } else {
710    __ j(equal, is_baseline);
711  }
712
713  __ CmpInstanceType(scratch1, INTERPRETER_DATA_TYPE);
714  __ j(not_equal, &done, Label::kNear);
715
716  __ LoadTaggedPointerField(
717      sfi_data, FieldOperand(sfi_data, InterpreterData::kBytecodeArrayOffset));
718
719  __ bind(&done);
720}
721
722// static
723void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
724  // ----------- S t a t e -------------
725  //  -- rax    : the value to pass to the generator
726  //  -- rdx    : the JSGeneratorObject to resume
727  //  -- rsp[0] : return address
728  // -----------------------------------
729
730  // Store input value into generator object.
731  __ StoreTaggedField(
732      FieldOperand(rdx, JSGeneratorObject::kInputOrDebugPosOffset), rax);
733  Register object = WriteBarrierDescriptor::ObjectRegister();
734  __ Move(object, rdx);
735  __ RecordWriteField(object, JSGeneratorObject::kInputOrDebugPosOffset, rax,
736                      WriteBarrierDescriptor::SlotAddressRegister(),
737                      SaveFPRegsMode::kIgnore);
738  // Check that rdx is still valid, RecordWrite might have clobbered it.
739  __ AssertGeneratorObject(rdx);
740
741  Register decompr_scratch1 = COMPRESS_POINTERS_BOOL ? r8 : no_reg;
742
743  // Load suspended function and context.
744  __ LoadTaggedPointerField(
745      rdi, FieldOperand(rdx, JSGeneratorObject::kFunctionOffset));
746  __ LoadTaggedPointerField(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
747
748  // Flood function if we are stepping.
749  Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator;
750  Label stepping_prepared;
751  ExternalReference debug_hook =
752      ExternalReference::debug_hook_on_function_call_address(masm->isolate());
753  Operand debug_hook_operand = masm->ExternalReferenceAsOperand(debug_hook);
754  __ cmpb(debug_hook_operand, Immediate(0));
755  __ j(not_equal, &prepare_step_in_if_stepping);
756
757  // Flood function if we need to continue stepping in the suspended generator.
758  ExternalReference debug_suspended_generator =
759      ExternalReference::debug_suspended_generator_address(masm->isolate());
760  Operand debug_suspended_generator_operand =
761      masm->ExternalReferenceAsOperand(debug_suspended_generator);
762  __ cmpq(rdx, debug_suspended_generator_operand);
763  __ j(equal, &prepare_step_in_suspended_generator);
764  __ bind(&stepping_prepared);
765
766  // Check the stack for overflow. We are not trying to catch interruptions
767  // (i.e. debug break and preemption) here, so check the "real stack limit".
768  Label stack_overflow;
769  __ cmpq(rsp, __ StackLimitAsOperand(StackLimitKind::kRealStackLimit));
770  __ j(below, &stack_overflow);
771
772  // Pop return address.
773  __ PopReturnAddressTo(rax);
774
775  // ----------- S t a t e -------------
776  //  -- rax    : return address
777  //  -- rdx    : the JSGeneratorObject to resume
778  //  -- rdi    : generator function
779  //  -- rsi    : generator context
780  // -----------------------------------
781
782  // Copy the function arguments from the generator object's register file.
783  __ LoadTaggedPointerField(
784      rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
785  __ movzxwq(
786      rcx, FieldOperand(rcx, SharedFunctionInfo::kFormalParameterCountOffset));
787  __ decq(rcx);  // Exclude receiver.
788  __ LoadTaggedPointerField(
789      rbx, FieldOperand(rdx, JSGeneratorObject::kParametersAndRegistersOffset));
790
791  {
792    Label done_loop, loop;
793    __ bind(&loop);
794    __ decq(rcx);
795    __ j(less, &done_loop, Label::kNear);
796    __ PushTaggedAnyField(
797        FieldOperand(rbx, rcx, times_tagged_size, FixedArray::kHeaderSize),
798        decompr_scratch1);
799    __ jmp(&loop);
800    __ bind(&done_loop);
801
802    // Push the receiver.
803    __ PushTaggedPointerField(
804        FieldOperand(rdx, JSGeneratorObject::kReceiverOffset),
805        decompr_scratch1);
806  }
807
808  // Underlying function needs to have bytecode available.
809  if (FLAG_debug_code) {
810    Label is_baseline, ok;
811    __ LoadTaggedPointerField(
812        rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
813    __ LoadTaggedPointerField(
814        rcx, FieldOperand(rcx, SharedFunctionInfo::kFunctionDataOffset));
815    GetSharedFunctionInfoBytecodeOrBaseline(masm, rcx, kScratchRegister,
816                                            &is_baseline);
817    __ CmpObjectType(rcx, BYTECODE_ARRAY_TYPE, rcx);
818    __ Assert(equal, AbortReason::kMissingBytecodeArray);
819    __ jmp(&ok);
820
821    __ bind(&is_baseline);
822    __ CmpObjectType(rcx, CODET_TYPE, rcx);
823    __ Assert(equal, AbortReason::kMissingBytecodeArray);
824
825    __ bind(&ok);
826  }
827
828  // Resume (Ignition/TurboFan) generator object.
829  {
830    __ PushReturnAddressFrom(rax);
831    __ LoadTaggedPointerField(
832        rax, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
833    __ movzxwq(rax, FieldOperand(
834                        rax, SharedFunctionInfo::kFormalParameterCountOffset));
835    // We abuse new.target both to indicate that this is a resume call and to
836    // pass in the generator object.  In ordinary calls, new.target is always
837    // undefined because generator functions are non-constructable.
838    static_assert(kJavaScriptCallCodeStartRegister == rcx, "ABI mismatch");
839    __ LoadTaggedPointerField(rcx, FieldOperand(rdi, JSFunction::kCodeOffset));
840    __ JumpCodeTObject(rcx);
841  }
842
843  __ bind(&prepare_step_in_if_stepping);
844  {
845    FrameScope scope(masm, StackFrame::INTERNAL);
846    __ Push(rdx);
847    __ Push(rdi);
848    // Push hole as receiver since we do not use it for stepping.
849    __ PushRoot(RootIndex::kTheHoleValue);
850    __ CallRuntime(Runtime::kDebugOnFunctionCall);
851    __ Pop(rdx);
852    __ LoadTaggedPointerField(
853        rdi, FieldOperand(rdx, JSGeneratorObject::kFunctionOffset));
854  }
855  __ jmp(&stepping_prepared);
856
857  __ bind(&prepare_step_in_suspended_generator);
858  {
859    FrameScope scope(masm, StackFrame::INTERNAL);
860    __ Push(rdx);
861    __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator);
862    __ Pop(rdx);
863    __ LoadTaggedPointerField(
864        rdi, FieldOperand(rdx, JSGeneratorObject::kFunctionOffset));
865  }
866  __ jmp(&stepping_prepared);
867
868  __ bind(&stack_overflow);
869  {
870    FrameScope scope(masm, StackFrame::INTERNAL);
871    __ CallRuntime(Runtime::kThrowStackOverflow);
872    __ int3();  // This should be unreachable.
873  }
874}
875
876static void ReplaceClosureCodeWithOptimizedCode(MacroAssembler* masm,
877                                                Register optimized_code,
878                                                Register closure,
879                                                Register scratch1,
880                                                Register slot_address) {
881  ASM_CODE_COMMENT(masm);
882  DCHECK(!AreAliased(optimized_code, closure, scratch1, slot_address));
883  DCHECK_EQ(closure, kJSFunctionRegister);
884  // Store the optimized code in the closure.
885  __ AssertCodeT(optimized_code);
886  __ StoreTaggedField(FieldOperand(closure, JSFunction::kCodeOffset),
887                      optimized_code);
888  // Write barrier clobbers scratch1 below.
889  Register value = scratch1;
890  __ movq(value, optimized_code);
891
892  __ RecordWriteField(closure, JSFunction::kCodeOffset, value, slot_address,
893                      SaveFPRegsMode::kIgnore, RememberedSetAction::kOmit,
894                      SmiCheck::kOmit);
895}
896
897static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch1,
898                                  Register scratch2) {
899  ASM_CODE_COMMENT(masm);
900  Register params_size = scratch1;
901  // Get the size of the formal parameters (in bytes).
902  __ movq(params_size,
903          Operand(rbp, InterpreterFrameConstants::kBytecodeArrayFromFp));
904  __ movl(params_size,
905          FieldOperand(params_size, BytecodeArray::kParameterSizeOffset));
906
907  Register actual_params_size = scratch2;
908  // Compute the size of the actual parameters (in bytes).
909  __ movq(actual_params_size,
910          Operand(rbp, StandardFrameConstants::kArgCOffset));
911  __ leaq(actual_params_size,
912          Operand(actual_params_size, times_system_pointer_size, 0));
913
914  // If actual is bigger than formal, then we should use it to free up the stack
915  // arguments.
916  Label corrected_args_count;
917  __ cmpq(params_size, actual_params_size);
918  __ j(greater_equal, &corrected_args_count, Label::kNear);
919  __ movq(params_size, actual_params_size);
920  __ bind(&corrected_args_count);
921
922  // Leave the frame (also dropping the register file).
923  __ leave();
924
925  // Drop receiver + arguments.
926  __ DropArguments(params_size, scratch2, TurboAssembler::kCountIsBytes,
927                   TurboAssembler::kCountIncludesReceiver);
928}
929
930// Tail-call |function_id| if |actual_state| == |expected_state|
931static void TailCallRuntimeIfStateEquals(MacroAssembler* masm,
932                                         Register actual_state,
933                                         TieringState expected_state,
934                                         Runtime::FunctionId function_id) {
935  ASM_CODE_COMMENT(masm);
936  Label no_match;
937  __ Cmp(actual_state, static_cast<int>(expected_state));
938  __ j(not_equal, &no_match);
939  GenerateTailCallToReturnedCode(masm, function_id);
940  __ bind(&no_match);
941}
942
943static void MaybeOptimizeCode(MacroAssembler* masm, Register feedback_vector,
944                              Register tiering_state) {
945  // ----------- S t a t e -------------
946  //  -- rax : actual argument count
947  //  -- rdx : new target (preserved for callee if needed, and caller)
948  //  -- rdi : target function (preserved for callee if needed, and caller)
949  //  -- feedback vector (preserved for caller if needed)
950  //  -- tiering_state : a Smi containing a non-zero tiering state.
951  // -----------------------------------
952  ASM_CODE_COMMENT(masm);
953  DCHECK(!AreAliased(feedback_vector, rdx, rdi, tiering_state));
954
955  TailCallRuntimeIfStateEquals(masm, tiering_state,
956                               TieringState::kRequestMaglev_Synchronous,
957                               Runtime::kCompileMaglev_Synchronous);
958  TailCallRuntimeIfStateEquals(masm, tiering_state,
959                               TieringState::kRequestMaglev_Concurrent,
960                               Runtime::kCompileMaglev_Concurrent);
961  TailCallRuntimeIfStateEquals(masm, tiering_state,
962                               TieringState::kRequestTurbofan_Synchronous,
963                               Runtime::kCompileTurbofan_Synchronous);
964  TailCallRuntimeIfStateEquals(masm, tiering_state,
965                               TieringState::kRequestTurbofan_Concurrent,
966                               Runtime::kCompileTurbofan_Concurrent);
967
968  __ int3();
969}
970
971static void TailCallOptimizedCodeSlot(MacroAssembler* masm,
972                                      Register optimized_code_entry,
973                                      Register closure, Register scratch1,
974                                      Register scratch2, JumpMode jump_mode) {
975  // ----------- S t a t e -------------
976  //  rax : actual argument count
977  //  rdx : new target (preserved for callee if needed, and caller)
978  //  rsi : current context, used for the runtime call
979  //  rdi : target function (preserved for callee if needed, and caller)
980  // -----------------------------------
981  ASM_CODE_COMMENT(masm);
982  DCHECK_EQ(closure, kJSFunctionRegister);
983  DCHECK(!AreAliased(rax, rdx, closure, rsi, optimized_code_entry, scratch1,
984                     scratch2));
985
986  Label heal_optimized_code_slot;
987
988  // If the optimized code is cleared, go to runtime to update the optimization
989  // marker field.
990  __ LoadWeakValue(optimized_code_entry, &heal_optimized_code_slot);
991
992  // Check if the optimized code is marked for deopt. If it is, call the
993  // runtime to clear it.
994  __ AssertCodeT(optimized_code_entry);
995  if (V8_EXTERNAL_CODE_SPACE_BOOL) {
996    __ testl(FieldOperand(optimized_code_entry,
997                          CodeDataContainer::kKindSpecificFlagsOffset),
998             Immediate(1 << Code::kMarkedForDeoptimizationBit));
999  } else {
1000    __ LoadTaggedPointerField(
1001        scratch1,
1002        FieldOperand(optimized_code_entry, Code::kCodeDataContainerOffset));
1003    __ testl(
1004        FieldOperand(scratch1, CodeDataContainer::kKindSpecificFlagsOffset),
1005        Immediate(1 << Code::kMarkedForDeoptimizationBit));
1006  }
1007  __ j(not_zero, &heal_optimized_code_slot);
1008
1009  // Optimized code is good, get it into the closure and link the closure into
1010  // the optimized functions list, then tail call the optimized code.
1011  ReplaceClosureCodeWithOptimizedCode(masm, optimized_code_entry, closure,
1012                                      scratch1, scratch2);
1013  static_assert(kJavaScriptCallCodeStartRegister == rcx, "ABI mismatch");
1014  __ Move(rcx, optimized_code_entry);
1015  __ JumpCodeTObject(rcx, jump_mode);
1016
1017  // Optimized code slot contains deoptimized code or code is cleared and
1018  // optimized code marker isn't updated. Evict the code, update the marker
1019  // and re-enter the closure's code.
1020  __ bind(&heal_optimized_code_slot);
1021  GenerateTailCallToReturnedCode(masm, Runtime::kHealOptimizedCodeSlot,
1022                                 jump_mode);
1023}
1024
1025// Advance the current bytecode offset. This simulates what all bytecode
1026// handlers do upon completion of the underlying operation. Will bail out to a
1027// label if the bytecode (without prefix) is a return bytecode. Will not advance
1028// the bytecode offset if the current bytecode is a JumpLoop, instead just
1029// re-executing the JumpLoop to jump to the correct bytecode.
1030static void AdvanceBytecodeOffsetOrReturn(MacroAssembler* masm,
1031                                          Register bytecode_array,
1032                                          Register bytecode_offset,
1033                                          Register bytecode, Register scratch1,
1034                                          Register scratch2, Label* if_return) {
1035  ASM_CODE_COMMENT(masm);
1036  Register bytecode_size_table = scratch1;
1037
1038  // The bytecode offset value will be increased by one in wide and extra wide
1039  // cases. In the case of having a wide or extra wide JumpLoop bytecode, we
1040  // will restore the original bytecode. In order to simplify the code, we have
1041  // a backup of it.
1042  Register original_bytecode_offset = scratch2;
1043  DCHECK(!AreAliased(bytecode_array, bytecode_offset, bytecode,
1044                     bytecode_size_table, original_bytecode_offset));
1045
1046  __ movq(original_bytecode_offset, bytecode_offset);
1047
1048  __ Move(bytecode_size_table,
1049          ExternalReference::bytecode_size_table_address());
1050
1051  // Check if the bytecode is a Wide or ExtraWide prefix bytecode.
1052  Label process_bytecode, extra_wide;
1053  STATIC_ASSERT(0 == static_cast<int>(interpreter::Bytecode::kWide));
1054  STATIC_ASSERT(1 == static_cast<int>(interpreter::Bytecode::kExtraWide));
1055  STATIC_ASSERT(2 == static_cast<int>(interpreter::Bytecode::kDebugBreakWide));
1056  STATIC_ASSERT(3 ==
1057                static_cast<int>(interpreter::Bytecode::kDebugBreakExtraWide));
1058  __ cmpb(bytecode, Immediate(0x3));
1059  __ j(above, &process_bytecode, Label::kNear);
1060  // The code to load the next bytecode is common to both wide and extra wide.
1061  // We can hoist them up here. incl has to happen before testb since it
1062  // modifies the ZF flag.
1063  __ incl(bytecode_offset);
1064  __ testb(bytecode, Immediate(0x1));
1065  __ movzxbq(bytecode, Operand(bytecode_array, bytecode_offset, times_1, 0));
1066  __ j(not_equal, &extra_wide, Label::kNear);
1067
1068  // Update table to the wide scaled table.
1069  __ addq(bytecode_size_table,
1070          Immediate(kByteSize * interpreter::Bytecodes::kBytecodeCount));
1071  __ jmp(&process_bytecode, Label::kNear);
1072
1073  __ bind(&extra_wide);
1074  // Update table to the extra wide scaled table.
1075  __ addq(bytecode_size_table,
1076          Immediate(2 * kByteSize * interpreter::Bytecodes::kBytecodeCount));
1077
1078  __ bind(&process_bytecode);
1079
1080// Bailout to the return label if this is a return bytecode.
1081#define JUMP_IF_EQUAL(NAME)                                             \
1082  __ cmpb(bytecode,                                                     \
1083          Immediate(static_cast<int>(interpreter::Bytecode::k##NAME))); \
1084  __ j(equal, if_return, Label::kFar);
1085  RETURN_BYTECODE_LIST(JUMP_IF_EQUAL)
1086#undef JUMP_IF_EQUAL
1087
1088  // If this is a JumpLoop, re-execute it to perform the jump to the beginning
1089  // of the loop.
1090  Label end, not_jump_loop;
1091  __ cmpb(bytecode,
1092          Immediate(static_cast<int>(interpreter::Bytecode::kJumpLoop)));
1093  __ j(not_equal, &not_jump_loop, Label::kNear);
1094  // We need to restore the original bytecode_offset since we might have
1095  // increased it to skip the wide / extra-wide prefix bytecode.
1096  __ movq(bytecode_offset, original_bytecode_offset);
1097  __ jmp(&end, Label::kNear);
1098
1099  __ bind(&not_jump_loop);
1100  // Otherwise, load the size of the current bytecode and advance the offset.
1101  __ movzxbl(kScratchRegister,
1102             Operand(bytecode_size_table, bytecode, times_1, 0));
1103  __ addl(bytecode_offset, kScratchRegister);
1104
1105  __ bind(&end);
1106}
1107
1108// Read off the optimization state in the feedback vector and check if there
1109// is optimized code or a tiering state that needs to be processed.
1110static void LoadTieringStateAndJumpIfNeedsProcessing(
1111    MacroAssembler* masm, Register optimization_state, Register feedback_vector,
1112    Label* has_optimized_code_or_state) {
1113  ASM_CODE_COMMENT(masm);
1114  __ movl(optimization_state,
1115          FieldOperand(feedback_vector, FeedbackVector::kFlagsOffset));
1116  __ testl(
1117      optimization_state,
1118      Immediate(
1119          FeedbackVector::kHasOptimizedCodeOrTieringStateIsAnyRequestMask));
1120  __ j(not_zero, has_optimized_code_or_state);
1121}
1122
1123static void MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(
1124    MacroAssembler* masm, Register optimization_state, Register feedback_vector,
1125    Register closure, JumpMode jump_mode = JumpMode::kJump) {
1126  ASM_CODE_COMMENT(masm);
1127  DCHECK(!AreAliased(optimization_state, feedback_vector, closure));
1128  Label maybe_has_optimized_code;
1129  __ testl(optimization_state,
1130           Immediate(FeedbackVector::kTieringStateIsAnyRequestMask));
1131  __ j(zero, &maybe_has_optimized_code);
1132
1133  Register tiering_state = optimization_state;
1134  __ DecodeField<FeedbackVector::TieringStateBits>(tiering_state);
1135  MaybeOptimizeCode(masm, feedback_vector, tiering_state);
1136
1137  __ bind(&maybe_has_optimized_code);
1138  Register optimized_code_entry = optimization_state;
1139  __ LoadAnyTaggedField(
1140      optimized_code_entry,
1141      FieldOperand(feedback_vector, FeedbackVector::kMaybeOptimizedCodeOffset));
1142  TailCallOptimizedCodeSlot(masm, optimized_code_entry, closure, r9,
1143                            WriteBarrierDescriptor::SlotAddressRegister(),
1144                            jump_mode);
1145}
1146
1147namespace {
1148
1149void ResetBytecodeAgeAndOsrState(MacroAssembler* masm,
1150                                 Register bytecode_array) {
1151  // Reset the bytecode age and OSR state (optimized to a single write).
1152  static_assert(BytecodeArray::kOsrStateAndBytecodeAgeAreContiguous32Bits);
1153  STATIC_ASSERT(BytecodeArray::kNoAgeBytecodeAge == 0);
1154  __ movl(FieldOperand(bytecode_array,
1155                       BytecodeArray::kOsrUrgencyAndInstallTargetOffset),
1156          Immediate(0));
1157}
1158
1159}  // namespace
1160
1161// Generate code for entering a JS function with the interpreter.
1162// On entry to the function the receiver and arguments have been pushed on the
1163// stack left to right.
1164//
1165// The live registers are:
1166//   o rax: actual argument count
1167//   o rdi: the JS function object being called
1168//   o rdx: the incoming new target or generator object
1169//   o rsi: our context
1170//   o rbp: the caller's frame pointer
1171//   o rsp: stack pointer (pointing to return address)
1172//
1173// The function builds an interpreter frame. See InterpreterFrameConstants in
1174// frame-constants.h for its layout.
1175void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
1176  Register closure = rdi;
1177  Register feedback_vector = rbx;
1178
1179  // Get the bytecode array from the function object and load it into
1180  // kInterpreterBytecodeArrayRegister.
1181  __ LoadTaggedPointerField(
1182      kScratchRegister,
1183      FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset));
1184  __ LoadTaggedPointerField(
1185      kInterpreterBytecodeArrayRegister,
1186      FieldOperand(kScratchRegister, SharedFunctionInfo::kFunctionDataOffset));
1187
1188  Label is_baseline;
1189  GetSharedFunctionInfoBytecodeOrBaseline(
1190      masm, kInterpreterBytecodeArrayRegister, kScratchRegister, &is_baseline);
1191
1192  // The bytecode array could have been flushed from the shared function info,
1193  // if so, call into CompileLazy.
1194  Label compile_lazy;
1195  __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE,
1196                   kScratchRegister);
1197  __ j(not_equal, &compile_lazy);
1198
1199  // Load the feedback vector from the closure.
1200  __ LoadTaggedPointerField(
1201      feedback_vector, FieldOperand(closure, JSFunction::kFeedbackCellOffset));
1202  __ LoadTaggedPointerField(feedback_vector,
1203                            FieldOperand(feedback_vector, Cell::kValueOffset));
1204
1205  Label push_stack_frame;
1206  // Check if feedback vector is valid. If valid, check for optimized code
1207  // and update invocation count. Otherwise, setup the stack frame.
1208  __ LoadMap(rcx, feedback_vector);
1209  __ CmpInstanceType(rcx, FEEDBACK_VECTOR_TYPE);
1210  __ j(not_equal, &push_stack_frame);
1211
1212  // Check the tiering state.
1213  Label has_optimized_code_or_state;
1214  Register optimization_state = rcx;
1215  LoadTieringStateAndJumpIfNeedsProcessing(
1216      masm, optimization_state, feedback_vector, &has_optimized_code_or_state);
1217
1218  Label not_optimized;
1219  __ bind(&not_optimized);
1220
1221  // Increment invocation count for the function.
1222  __ incl(
1223      FieldOperand(feedback_vector, FeedbackVector::kInvocationCountOffset));
1224
1225  // Open a frame scope to indicate that there is a frame on the stack.  The
1226  // MANUAL indicates that the scope shouldn't actually generate code to set up
1227  // the frame (that is done below).
1228  __ bind(&push_stack_frame);
1229  FrameScope frame_scope(masm, StackFrame::MANUAL);
1230  __ pushq(rbp);  // Caller's frame pointer.
1231  __ movq(rbp, rsp);
1232  __ Push(kContextRegister);                 // Callee's context.
1233  __ Push(kJavaScriptCallTargetRegister);    // Callee's JS function.
1234  __ Push(kJavaScriptCallArgCountRegister);  // Actual argument count.
1235
1236  ResetBytecodeAgeAndOsrState(masm, kInterpreterBytecodeArrayRegister);
1237
1238  // Load initial bytecode offset.
1239  __ Move(kInterpreterBytecodeOffsetRegister,
1240          BytecodeArray::kHeaderSize - kHeapObjectTag);
1241
1242  // Push bytecode array and Smi tagged bytecode offset.
1243  __ Push(kInterpreterBytecodeArrayRegister);
1244  __ SmiTag(rcx, kInterpreterBytecodeOffsetRegister);
1245  __ Push(rcx);
1246
1247  // Allocate the local and temporary register file on the stack.
1248  Label stack_overflow;
1249  {
1250    // Load frame size from the BytecodeArray object.
1251    __ movl(rcx, FieldOperand(kInterpreterBytecodeArrayRegister,
1252                              BytecodeArray::kFrameSizeOffset));
1253
1254    // Do a stack check to ensure we don't go over the limit.
1255    __ movq(rax, rsp);
1256    __ subq(rax, rcx);
1257    __ cmpq(rax, __ StackLimitAsOperand(StackLimitKind::kRealStackLimit));
1258    __ j(below, &stack_overflow);
1259
1260    // If ok, push undefined as the initial value for all register file entries.
1261    Label loop_header;
1262    Label loop_check;
1263    __ LoadRoot(kInterpreterAccumulatorRegister, RootIndex::kUndefinedValue);
1264    __ j(always, &loop_check, Label::kNear);
1265    __ bind(&loop_header);
1266    // TODO(rmcilroy): Consider doing more than one push per loop iteration.
1267    __ Push(kInterpreterAccumulatorRegister);
1268    // Continue loop if not done.
1269    __ bind(&loop_check);
1270    __ subq(rcx, Immediate(kSystemPointerSize));
1271    __ j(greater_equal, &loop_header, Label::kNear);
1272  }
1273
1274  // If the bytecode array has a valid incoming new target or generator object
1275  // register, initialize it with incoming value which was passed in rdx.
1276  Label no_incoming_new_target_or_generator_register;
1277  __ movsxlq(
1278      rcx,
1279      FieldOperand(kInterpreterBytecodeArrayRegister,
1280                   BytecodeArray::kIncomingNewTargetOrGeneratorRegisterOffset));
1281  __ testl(rcx, rcx);
1282  __ j(zero, &no_incoming_new_target_or_generator_register, Label::kNear);
1283  __ movq(Operand(rbp, rcx, times_system_pointer_size, 0), rdx);
1284  __ bind(&no_incoming_new_target_or_generator_register);
1285
1286  // Perform interrupt stack check.
1287  // TODO(solanes): Merge with the real stack limit check above.
1288  Label stack_check_interrupt, after_stack_check_interrupt;
1289  __ cmpq(rsp, __ StackLimitAsOperand(StackLimitKind::kInterruptStackLimit));
1290  __ j(below, &stack_check_interrupt);
1291  __ bind(&after_stack_check_interrupt);
1292
1293  // The accumulator is already loaded with undefined.
1294
1295  // Load the dispatch table into a register and dispatch to the bytecode
1296  // handler at the current bytecode offset.
1297  Label do_dispatch;
1298  __ bind(&do_dispatch);
1299  __ Move(
1300      kInterpreterDispatchTableRegister,
1301      ExternalReference::interpreter_dispatch_table_address(masm->isolate()));
1302  __ movzxbq(kScratchRegister,
1303             Operand(kInterpreterBytecodeArrayRegister,
1304                     kInterpreterBytecodeOffsetRegister, times_1, 0));
1305  __ movq(kJavaScriptCallCodeStartRegister,
1306          Operand(kInterpreterDispatchTableRegister, kScratchRegister,
1307                  times_system_pointer_size, 0));
1308  __ call(kJavaScriptCallCodeStartRegister);
1309  masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
1310
1311  // Any returns to the entry trampoline are either due to the return bytecode
1312  // or the interpreter tail calling a builtin and then a dispatch.
1313
1314  // Get bytecode array and bytecode offset from the stack frame.
1315  __ movq(kInterpreterBytecodeArrayRegister,
1316          Operand(rbp, InterpreterFrameConstants::kBytecodeArrayFromFp));
1317  __ SmiUntag(kInterpreterBytecodeOffsetRegister,
1318              Operand(rbp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
1319
1320  // Either return, or advance to the next bytecode and dispatch.
1321  Label do_return;
1322  __ movzxbq(rbx, Operand(kInterpreterBytecodeArrayRegister,
1323                          kInterpreterBytecodeOffsetRegister, times_1, 0));
1324  AdvanceBytecodeOffsetOrReturn(masm, kInterpreterBytecodeArrayRegister,
1325                                kInterpreterBytecodeOffsetRegister, rbx, rcx,
1326                                r8, &do_return);
1327  __ jmp(&do_dispatch);
1328
1329  __ bind(&do_return);
1330  // The return value is in rax.
1331  LeaveInterpreterFrame(masm, rbx, rcx);
1332  __ ret(0);
1333
1334  __ bind(&stack_check_interrupt);
1335  // Modify the bytecode offset in the stack to be kFunctionEntryBytecodeOffset
1336  // for the call to the StackGuard.
1337  __ Move(Operand(rbp, InterpreterFrameConstants::kBytecodeOffsetFromFp),
1338          Smi::FromInt(BytecodeArray::kHeaderSize - kHeapObjectTag +
1339                       kFunctionEntryBytecodeOffset));
1340  __ CallRuntime(Runtime::kStackGuard);
1341
1342  // After the call, restore the bytecode array, bytecode offset and accumulator
1343  // registers again. Also, restore the bytecode offset in the stack to its
1344  // previous value.
1345  __ movq(kInterpreterBytecodeArrayRegister,
1346          Operand(rbp, InterpreterFrameConstants::kBytecodeArrayFromFp));
1347  __ Move(kInterpreterBytecodeOffsetRegister,
1348          BytecodeArray::kHeaderSize - kHeapObjectTag);
1349  __ LoadRoot(kInterpreterAccumulatorRegister, RootIndex::kUndefinedValue);
1350
1351  __ SmiTag(rcx, kInterpreterBytecodeArrayRegister);
1352  __ movq(Operand(rbp, InterpreterFrameConstants::kBytecodeOffsetFromFp), rcx);
1353
1354  __ jmp(&after_stack_check_interrupt);
1355
1356  __ bind(&compile_lazy);
1357  GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
1358  __ int3();  // Should not return.
1359
1360  __ bind(&has_optimized_code_or_state);
1361  MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(masm, optimization_state,
1362                                               feedback_vector, closure);
1363
1364  __ bind(&is_baseline);
1365  {
1366    // Load the feedback vector from the closure.
1367    __ LoadTaggedPointerField(
1368        feedback_vector,
1369        FieldOperand(closure, JSFunction::kFeedbackCellOffset));
1370    __ LoadTaggedPointerField(
1371        feedback_vector, FieldOperand(feedback_vector, Cell::kValueOffset));
1372
1373    Label install_baseline_code;
1374    // Check if feedback vector is valid. If not, call prepare for baseline to
1375    // allocate it.
1376    __ LoadMap(rcx, feedback_vector);
1377    __ CmpInstanceType(rcx, FEEDBACK_VECTOR_TYPE);
1378    __ j(not_equal, &install_baseline_code);
1379
1380    // Check the tiering state.
1381    LoadTieringStateAndJumpIfNeedsProcessing(masm, optimization_state,
1382                                             feedback_vector,
1383                                             &has_optimized_code_or_state);
1384
1385    // Load the baseline code into the closure.
1386    __ Move(rcx, kInterpreterBytecodeArrayRegister);
1387    static_assert(kJavaScriptCallCodeStartRegister == rcx, "ABI mismatch");
1388    ReplaceClosureCodeWithOptimizedCode(
1389        masm, rcx, closure, kInterpreterBytecodeArrayRegister,
1390        WriteBarrierDescriptor::SlotAddressRegister());
1391    __ JumpCodeTObject(rcx);
1392
1393    __ bind(&install_baseline_code);
1394    GenerateTailCallToReturnedCode(masm, Runtime::kInstallBaselineCode);
1395  }
1396
1397  __ bind(&stack_overflow);
1398  __ CallRuntime(Runtime::kThrowStackOverflow);
1399  __ int3();  // Should not return.
1400}
1401
1402static void GenerateInterpreterPushArgs(MacroAssembler* masm, Register num_args,
1403                                        Register start_address,
1404                                        Register scratch) {
1405  ASM_CODE_COMMENT(masm);
1406  // Find the argument with lowest address.
1407  __ movq(scratch, num_args);
1408  __ negq(scratch);
1409  __ leaq(start_address,
1410          Operand(start_address, scratch, times_system_pointer_size,
1411                  kSystemPointerSize));
1412  // Push the arguments.
1413  __ PushArray(start_address, num_args, scratch,
1414               TurboAssembler::PushArrayOrder::kReverse);
1415}
1416
1417// static
1418void Builtins::Generate_InterpreterPushArgsThenCallImpl(
1419    MacroAssembler* masm, ConvertReceiverMode receiver_mode,
1420    InterpreterPushArgsMode mode) {
1421  DCHECK(mode != InterpreterPushArgsMode::kArrayFunction);
1422  // ----------- S t a t e -------------
1423  //  -- rax : the number of arguments
1424  //  -- rbx : the address of the first argument to be pushed. Subsequent
1425  //           arguments should be consecutive above this, in the same order as
1426  //           they are to be pushed onto the stack.
1427  //  -- rdi : the target to call (can be any Object).
1428  // -----------------------------------
1429  Label stack_overflow;
1430
1431  if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
1432    // The spread argument should not be pushed.
1433    __ decl(rax);
1434  }
1435
1436  __ movl(rcx, rax);
1437  if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
1438    __ decl(rcx);  // Exclude receiver.
1439  }
1440
1441  // Add a stack check before pushing arguments.
1442  __ StackOverflowCheck(rcx, &stack_overflow);
1443
1444  // Pop return address to allow tail-call after pushing arguments.
1445  __ PopReturnAddressTo(kScratchRegister);
1446
1447  // rbx and rdx will be modified.
1448  GenerateInterpreterPushArgs(masm, rcx, rbx, rdx);
1449
1450  // Push "undefined" as the receiver arg if we need to.
1451  if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
1452    __ PushRoot(RootIndex::kUndefinedValue);
1453  }
1454
1455  if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
1456    // Pass the spread in the register rbx.
1457    // rbx already points to the penultime argument, the spread
1458    // is below that.
1459    __ movq(rbx, Operand(rbx, -kSystemPointerSize));
1460  }
1461
1462  // Call the target.
1463  __ PushReturnAddressFrom(kScratchRegister);  // Re-push return address.
1464
1465  if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
1466    __ Jump(BUILTIN_CODE(masm->isolate(), CallWithSpread),
1467            RelocInfo::CODE_TARGET);
1468  } else {
1469    __ Jump(masm->isolate()->builtins()->Call(receiver_mode),
1470            RelocInfo::CODE_TARGET);
1471  }
1472
1473  // Throw stack overflow exception.
1474  __ bind(&stack_overflow);
1475  {
1476    __ TailCallRuntime(Runtime::kThrowStackOverflow);
1477    // This should be unreachable.
1478    __ int3();
1479  }
1480}
1481
1482// static
1483void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
1484    MacroAssembler* masm, InterpreterPushArgsMode mode) {
1485  // ----------- S t a t e -------------
1486  //  -- rax : the number of arguments
1487  //  -- rdx : the new target (either the same as the constructor or
1488  //           the JSFunction on which new was invoked initially)
1489  //  -- rdi : the constructor to call (can be any Object)
1490  //  -- rbx : the allocation site feedback if available, undefined otherwise
1491  //  -- rcx : the address of the first argument to be pushed. Subsequent
1492  //           arguments should be consecutive above this, in the same order as
1493  //           they are to be pushed onto the stack.
1494  // -----------------------------------
1495  Label stack_overflow;
1496
1497  // Add a stack check before pushing arguments.
1498  __ StackOverflowCheck(rax, &stack_overflow);
1499
1500  // Pop return address to allow tail-call after pushing arguments.
1501  __ PopReturnAddressTo(kScratchRegister);
1502
1503  if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
1504    // The spread argument should not be pushed.
1505    __ decl(rax);
1506  }
1507
1508  // rcx and r8 will be modified.
1509  Register argc_without_receiver = r11;
1510  __ leaq(argc_without_receiver, Operand(rax, -kJSArgcReceiverSlots));
1511  GenerateInterpreterPushArgs(masm, argc_without_receiver, rcx, r8);
1512
1513  // Push slot for the receiver to be constructed.
1514  __ Push(Immediate(0));
1515
1516  if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
1517    // Pass the spread in the register rbx.
1518    __ movq(rbx, Operand(rcx, -kSystemPointerSize));
1519    // Push return address in preparation for the tail-call.
1520    __ PushReturnAddressFrom(kScratchRegister);
1521  } else {
1522    __ PushReturnAddressFrom(kScratchRegister);
1523    __ AssertUndefinedOrAllocationSite(rbx);
1524  }
1525
1526  if (mode == InterpreterPushArgsMode::kArrayFunction) {
1527    // Tail call to the array construct stub (still in the caller
1528    // context at this point).
1529    __ AssertFunction(rdi);
1530    // Jump to the constructor function (rax, rbx, rdx passed on).
1531    __ Jump(BUILTIN_CODE(masm->isolate(), ArrayConstructorImpl),
1532            RelocInfo::CODE_TARGET);
1533  } else if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
1534    // Call the constructor (rax, rdx, rdi passed on).
1535    __ Jump(BUILTIN_CODE(masm->isolate(), ConstructWithSpread),
1536            RelocInfo::CODE_TARGET);
1537  } else {
1538    DCHECK_EQ(InterpreterPushArgsMode::kOther, mode);
1539    // Call the constructor (rax, rdx, rdi passed on).
1540    __ Jump(BUILTIN_CODE(masm->isolate(), Construct), RelocInfo::CODE_TARGET);
1541  }
1542
1543  // Throw stack overflow exception.
1544  __ bind(&stack_overflow);
1545  {
1546    __ TailCallRuntime(Runtime::kThrowStackOverflow);
1547    // This should be unreachable.
1548    __ int3();
1549  }
1550}
1551
1552static void Generate_InterpreterEnterBytecode(MacroAssembler* masm) {
1553  // Set the return address to the correct point in the interpreter entry
1554  // trampoline.
1555  Label builtin_trampoline, trampoline_loaded;
1556  Smi interpreter_entry_return_pc_offset(
1557      masm->isolate()->heap()->interpreter_entry_return_pc_offset());
1558  DCHECK_NE(interpreter_entry_return_pc_offset, Smi::zero());
1559
1560  // If the SFI function_data is an InterpreterData, the function will have a
1561  // custom copy of the interpreter entry trampoline for profiling. If so,
1562  // get the custom trampoline, otherwise grab the entry address of the global
1563  // trampoline.
1564  __ movq(rbx, Operand(rbp, StandardFrameConstants::kFunctionOffset));
1565  __ LoadTaggedPointerField(
1566      rbx, FieldOperand(rbx, JSFunction::kSharedFunctionInfoOffset));
1567  __ LoadTaggedPointerField(
1568      rbx, FieldOperand(rbx, SharedFunctionInfo::kFunctionDataOffset));
1569  __ CmpObjectType(rbx, INTERPRETER_DATA_TYPE, kScratchRegister);
1570  __ j(not_equal, &builtin_trampoline, Label::kNear);
1571
1572  __ LoadTaggedPointerField(
1573      rbx, FieldOperand(rbx, InterpreterData::kInterpreterTrampolineOffset));
1574  __ LoadCodeTEntry(rbx, rbx);
1575  __ jmp(&trampoline_loaded, Label::kNear);
1576
1577  __ bind(&builtin_trampoline);
1578  // TODO(jgruber): Replace this by a lookup in the builtin entry table.
1579  __ movq(rbx,
1580          __ ExternalReferenceAsOperand(
1581              ExternalReference::
1582                  address_of_interpreter_entry_trampoline_instruction_start(
1583                      masm->isolate()),
1584              kScratchRegister));
1585
1586  __ bind(&trampoline_loaded);
1587  __ addq(rbx, Immediate(interpreter_entry_return_pc_offset.value()));
1588  __ Push(rbx);
1589
1590  // Initialize dispatch table register.
1591  __ Move(
1592      kInterpreterDispatchTableRegister,
1593      ExternalReference::interpreter_dispatch_table_address(masm->isolate()));
1594
1595  // Get the bytecode array pointer from the frame.
1596  __ movq(kInterpreterBytecodeArrayRegister,
1597          Operand(rbp, InterpreterFrameConstants::kBytecodeArrayFromFp));
1598
1599  if (FLAG_debug_code) {
1600    // Check function data field is actually a BytecodeArray object.
1601    __ AssertNotSmi(kInterpreterBytecodeArrayRegister);
1602    __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE,
1603                     rbx);
1604    __ Assert(
1605        equal,
1606        AbortReason::kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
1607  }
1608
1609  // Get the target bytecode offset from the frame.
1610  __ SmiUntag(kInterpreterBytecodeOffsetRegister,
1611              Operand(rbp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
1612
1613  if (FLAG_debug_code) {
1614    Label okay;
1615    __ cmpq(kInterpreterBytecodeOffsetRegister,
1616            Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
1617    __ j(greater_equal, &okay, Label::kNear);
1618    __ int3();
1619    __ bind(&okay);
1620  }
1621
1622  // Dispatch to the target bytecode.
1623  __ movzxbq(kScratchRegister,
1624             Operand(kInterpreterBytecodeArrayRegister,
1625                     kInterpreterBytecodeOffsetRegister, times_1, 0));
1626  __ movq(kJavaScriptCallCodeStartRegister,
1627          Operand(kInterpreterDispatchTableRegister, kScratchRegister,
1628                  times_system_pointer_size, 0));
1629  __ jmp(kJavaScriptCallCodeStartRegister);
1630}
1631
1632void Builtins::Generate_InterpreterEnterAtNextBytecode(MacroAssembler* masm) {
1633  // Get bytecode array and bytecode offset from the stack frame.
1634  __ movq(kInterpreterBytecodeArrayRegister,
1635          Operand(rbp, InterpreterFrameConstants::kBytecodeArrayFromFp));
1636  __ SmiUntag(kInterpreterBytecodeOffsetRegister,
1637              Operand(rbp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
1638
1639  Label enter_bytecode, function_entry_bytecode;
1640  __ cmpq(kInterpreterBytecodeOffsetRegister,
1641          Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag +
1642                    kFunctionEntryBytecodeOffset));
1643  __ j(equal, &function_entry_bytecode);
1644
1645  // Load the current bytecode.
1646  __ movzxbq(rbx, Operand(kInterpreterBytecodeArrayRegister,
1647                          kInterpreterBytecodeOffsetRegister, times_1, 0));
1648
1649  // Advance to the next bytecode.
1650  Label if_return;
1651  AdvanceBytecodeOffsetOrReturn(masm, kInterpreterBytecodeArrayRegister,
1652                                kInterpreterBytecodeOffsetRegister, rbx, rcx,
1653                                r8, &if_return);
1654
1655  __ bind(&enter_bytecode);
1656  // Convert new bytecode offset to a Smi and save in the stackframe.
1657  __ SmiTag(kInterpreterBytecodeOffsetRegister);
1658  __ movq(Operand(rbp, InterpreterFrameConstants::kBytecodeOffsetFromFp),
1659          kInterpreterBytecodeOffsetRegister);
1660
1661  Generate_InterpreterEnterBytecode(masm);
1662
1663  __ bind(&function_entry_bytecode);
1664  // If the code deoptimizes during the implicit function entry stack interrupt
1665  // check, it will have a bailout ID of kFunctionEntryBytecodeOffset, which is
1666  // not a valid bytecode offset. Detect this case and advance to the first
1667  // actual bytecode.
1668  __ Move(kInterpreterBytecodeOffsetRegister,
1669          BytecodeArray::kHeaderSize - kHeapObjectTag);
1670  __ jmp(&enter_bytecode);
1671
1672  // We should never take the if_return path.
1673  __ bind(&if_return);
1674  __ Abort(AbortReason::kInvalidBytecodeAdvance);
1675}
1676
1677void Builtins::Generate_InterpreterEnterAtBytecode(MacroAssembler* masm) {
1678  Generate_InterpreterEnterBytecode(masm);
1679}
1680
1681// static
1682void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
1683  Register feedback_vector = r8;
1684  Register optimization_state = rcx;
1685  Register return_address = r15;
1686
1687#ifdef DEBUG
1688  for (auto reg : BaselineOutOfLinePrologueDescriptor::registers()) {
1689    DCHECK(
1690        !AreAliased(feedback_vector, optimization_state, return_address, reg));
1691  }
1692#endif
1693
1694  auto descriptor =
1695      Builtins::CallInterfaceDescriptorFor(Builtin::kBaselineOutOfLinePrologue);
1696  Register closure = descriptor.GetRegisterParameter(
1697      BaselineOutOfLinePrologueDescriptor::kClosure);
1698  // Load the feedback vector from the closure.
1699  __ LoadTaggedPointerField(
1700      feedback_vector, FieldOperand(closure, JSFunction::kFeedbackCellOffset));
1701  __ LoadTaggedPointerField(feedback_vector,
1702                            FieldOperand(feedback_vector, Cell::kValueOffset));
1703  if (FLAG_debug_code) {
1704    __ CmpObjectType(feedback_vector, FEEDBACK_VECTOR_TYPE, kScratchRegister);
1705    __ Assert(equal, AbortReason::kExpectedFeedbackVector);
1706  }
1707
1708  // Check the tiering state.
1709  Label has_optimized_code_or_state;
1710  LoadTieringStateAndJumpIfNeedsProcessing(
1711      masm, optimization_state, feedback_vector, &has_optimized_code_or_state);
1712
1713  // Increment invocation count for the function.
1714  __ incl(
1715      FieldOperand(feedback_vector, FeedbackVector::kInvocationCountOffset));
1716
1717    // Save the return address, so that we can push it to the end of the newly
1718    // set-up frame once we're done setting it up.
1719    __ PopReturnAddressTo(return_address);
1720    FrameScope frame_scope(masm, StackFrame::MANUAL);
1721    {
1722      ASM_CODE_COMMENT_STRING(masm, "Frame Setup");
1723      __ EnterFrame(StackFrame::BASELINE);
1724
1725      __ Push(descriptor.GetRegisterParameter(
1726          BaselineOutOfLinePrologueDescriptor::kCalleeContext));  // Callee's
1727                                                                  // context.
1728      Register callee_js_function = descriptor.GetRegisterParameter(
1729          BaselineOutOfLinePrologueDescriptor::kClosure);
1730      DCHECK_EQ(callee_js_function, kJavaScriptCallTargetRegister);
1731      DCHECK_EQ(callee_js_function, kJSFunctionRegister);
1732      __ Push(callee_js_function);  // Callee's JS function.
1733      __ Push(descriptor.GetRegisterParameter(
1734          BaselineOutOfLinePrologueDescriptor::
1735              kJavaScriptCallArgCount));  // Actual argument
1736                                          // count.
1737
1738      // We'll use the bytecode for both code age/OSR resetting, and pushing
1739      // onto the frame, so load it into a register.
1740      Register bytecode_array = descriptor.GetRegisterParameter(
1741          BaselineOutOfLinePrologueDescriptor::kInterpreterBytecodeArray);
1742      ResetBytecodeAgeAndOsrState(masm, bytecode_array);
1743      __ Push(bytecode_array);
1744
1745      // Baseline code frames store the feedback vector where interpreter would
1746      // store the bytecode offset.
1747      __ Push(feedback_vector);
1748    }
1749
1750  Register new_target = descriptor.GetRegisterParameter(
1751      BaselineOutOfLinePrologueDescriptor::kJavaScriptCallNewTarget);
1752
1753  Label call_stack_guard;
1754  Register frame_size = descriptor.GetRegisterParameter(
1755      BaselineOutOfLinePrologueDescriptor::kStackFrameSize);
1756  {
1757    ASM_CODE_COMMENT_STRING(masm, " Stack/interrupt check");
1758    // Stack check. This folds the checks for both the interrupt stack limit
1759    // check and the real stack limit into one by just checking for the
1760    // interrupt limit. The interrupt limit is either equal to the real stack
1761    // limit or tighter. By ensuring we have space until that limit after
1762    // building the frame we can quickly precheck both at once.
1763    //
1764    // TODO(v8:11429): Backport this folded check to the
1765    // InterpreterEntryTrampoline.
1766    __ Move(kScratchRegister, rsp);
1767    DCHECK_NE(frame_size, new_target);
1768    __ subq(kScratchRegister, frame_size);
1769    __ cmpq(kScratchRegister,
1770            __ StackLimitAsOperand(StackLimitKind::kInterruptStackLimit));
1771    __ j(below, &call_stack_guard);
1772  }
1773
1774  // Push the return address back onto the stack for return.
1775  __ PushReturnAddressFrom(return_address);
1776  // Return to caller pushed pc, without any frame teardown.
1777  __ LoadRoot(kInterpreterAccumulatorRegister, RootIndex::kUndefinedValue);
1778  __ Ret();
1779
1780  __ bind(&has_optimized_code_or_state);
1781  {
1782    ASM_CODE_COMMENT_STRING(masm, "Optimized marker check");
1783    // Drop the return address, rebalancing the return stack buffer by using
1784    // JumpMode::kPushAndReturn. We can't leave the slot and overwrite it on
1785    // return since we may do a runtime call along the way that requires the
1786    // stack to only contain valid frames.
1787    __ Drop(1);
1788    MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(masm, optimization_state,
1789                                                 feedback_vector, closure,
1790                                                 JumpMode::kPushAndReturn);
1791    __ Trap();
1792  }
1793
1794  __ bind(&call_stack_guard);
1795  {
1796    ASM_CODE_COMMENT_STRING(masm, "Stack/interrupt call");
1797    {
1798      // Push the baseline code return address now, as if it had been pushed by
1799      // the call to this builtin.
1800      __ PushReturnAddressFrom(return_address);
1801      FrameScope inner_frame_scope(masm, StackFrame::INTERNAL);
1802      // Save incoming new target or generator
1803      __ Push(new_target);
1804      __ SmiTag(frame_size);
1805      __ Push(frame_size);
1806      __ CallRuntime(Runtime::kStackGuardWithGap, 1);
1807      __ Pop(new_target);
1808    }
1809
1810    // Return to caller pushed pc, without any frame teardown.
1811    __ LoadRoot(kInterpreterAccumulatorRegister, RootIndex::kUndefinedValue);
1812    __ Ret();
1813  }
1814}
1815
1816namespace {
1817void Generate_ContinueToBuiltinHelper(MacroAssembler* masm,
1818                                      bool java_script_builtin,
1819                                      bool with_result) {
1820  ASM_CODE_COMMENT(masm);
1821  const RegisterConfiguration* config(RegisterConfiguration::Default());
1822  int allocatable_register_count = config->num_allocatable_general_registers();
1823  if (with_result) {
1824    if (java_script_builtin) {
1825      // kScratchRegister is not included in the allocateable registers.
1826      __ movq(kScratchRegister, rax);
1827    } else {
1828      // Overwrite the hole inserted by the deoptimizer with the return value
1829      // from the LAZY deopt point.
1830      __ movq(
1831          Operand(rsp, config->num_allocatable_general_registers() *
1832                               kSystemPointerSize +
1833                           BuiltinContinuationFrameConstants::kFixedFrameSize),
1834          rax);
1835    }
1836  }
1837  for (int i = allocatable_register_count - 1; i >= 0; --i) {
1838    int code = config->GetAllocatableGeneralCode(i);
1839    __ popq(Register::from_code(code));
1840    if (java_script_builtin && code == kJavaScriptCallArgCountRegister.code()) {
1841      __ SmiUntag(Register::from_code(code));
1842    }
1843  }
1844  if (with_result && java_script_builtin) {
1845    // Overwrite the hole inserted by the deoptimizer with the return value from
1846    // the LAZY deopt point. rax contains the arguments count, the return value
1847    // from LAZY is always the last argument.
1848    __ movq(Operand(rsp, rax, times_system_pointer_size,
1849                    BuiltinContinuationFrameConstants::kFixedFrameSize -
1850                        kJSArgcReceiverSlots * kSystemPointerSize),
1851            kScratchRegister);
1852  }
1853  __ movq(
1854      rbp,
1855      Operand(rsp, BuiltinContinuationFrameConstants::kFixedFrameSizeFromFp));
1856  const int offsetToPC =
1857      BuiltinContinuationFrameConstants::kFixedFrameSizeFromFp -
1858      kSystemPointerSize;
1859  __ popq(Operand(rsp, offsetToPC));
1860  __ Drop(offsetToPC / kSystemPointerSize);
1861
1862  // Replace the builtin index Smi on the stack with the instruction start
1863  // address of the builtin from the builtins table, and then Ret to this
1864  // address
1865  __ movq(kScratchRegister, Operand(rsp, 0));
1866  __ movq(kScratchRegister,
1867          __ EntryFromBuiltinIndexAsOperand(kScratchRegister));
1868  __ movq(Operand(rsp, 0), kScratchRegister);
1869
1870  __ Ret();
1871}
1872}  // namespace
1873
1874void Builtins::Generate_ContinueToCodeStubBuiltin(MacroAssembler* masm) {
1875  Generate_ContinueToBuiltinHelper(masm, false, false);
1876}
1877
1878void Builtins::Generate_ContinueToCodeStubBuiltinWithResult(
1879    MacroAssembler* masm) {
1880  Generate_ContinueToBuiltinHelper(masm, false, true);
1881}
1882
1883void Builtins::Generate_ContinueToJavaScriptBuiltin(MacroAssembler* masm) {
1884  Generate_ContinueToBuiltinHelper(masm, true, false);
1885}
1886
1887void Builtins::Generate_ContinueToJavaScriptBuiltinWithResult(
1888    MacroAssembler* masm) {
1889  Generate_ContinueToBuiltinHelper(masm, true, true);
1890}
1891
1892void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
1893  // Enter an internal frame.
1894  {
1895    FrameScope scope(masm, StackFrame::INTERNAL);
1896    __ CallRuntime(Runtime::kNotifyDeoptimized);
1897    // Tear down internal frame.
1898  }
1899
1900  DCHECK_EQ(kInterpreterAccumulatorRegister.code(), rax.code());
1901  __ movq(rax, Operand(rsp, kPCOnStackSize));
1902  __ ret(1 * kSystemPointerSize);  // Remove rax.
1903}
1904
1905// static
1906void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
1907  // ----------- S t a t e -------------
1908  //  -- rax     : argc
1909  //  -- rsp[0]  : return address
1910  //  -- rsp[1]  : receiver
1911  //  -- rsp[2]  : thisArg
1912  //  -- rsp[3]  : argArray
1913  // -----------------------------------
1914
1915  // 1. Load receiver into rdi, argArray into rbx (if present), remove all
1916  // arguments from the stack (including the receiver), and push thisArg (if
1917  // present) instead.
1918  {
1919    Label no_arg_array, no_this_arg;
1920    StackArgumentsAccessor args(rax);
1921    __ LoadRoot(rdx, RootIndex::kUndefinedValue);
1922    __ movq(rbx, rdx);
1923    __ movq(rdi, args[0]);
1924    __ cmpq(rax, Immediate(JSParameterCount(0)));
1925    __ j(equal, &no_this_arg, Label::kNear);
1926    {
1927      __ movq(rdx, args[1]);
1928      __ cmpq(rax, Immediate(JSParameterCount(1)));
1929      __ j(equal, &no_arg_array, Label::kNear);
1930      __ movq(rbx, args[2]);
1931      __ bind(&no_arg_array);
1932    }
1933    __ bind(&no_this_arg);
1934    __ DropArgumentsAndPushNewReceiver(rax, rdx, rcx,
1935                                       TurboAssembler::kCountIsInteger,
1936                                       TurboAssembler::kCountIncludesReceiver);
1937  }
1938
1939  // ----------- S t a t e -------------
1940  //  -- rbx     : argArray
1941  //  -- rdi     : receiver
1942  //  -- rsp[0]  : return address
1943  //  -- rsp[8]  : thisArg
1944  // -----------------------------------
1945
1946  // 2. We don't need to check explicitly for callable receiver here,
1947  // since that's the first thing the Call/CallWithArrayLike builtins
1948  // will do.
1949
1950  // 3. Tail call with no arguments if argArray is null or undefined.
1951  Label no_arguments;
1952  __ JumpIfRoot(rbx, RootIndex::kNullValue, &no_arguments, Label::kNear);
1953  __ JumpIfRoot(rbx, RootIndex::kUndefinedValue, &no_arguments, Label::kNear);
1954
1955  // 4a. Apply the receiver to the given argArray.
1956  __ Jump(BUILTIN_CODE(masm->isolate(), CallWithArrayLike),
1957          RelocInfo::CODE_TARGET);
1958
1959  // 4b. The argArray is either null or undefined, so we tail call without any
1960  // arguments to the receiver. Since we did not create a frame for
1961  // Function.prototype.apply() yet, we use a normal Call builtin here.
1962  __ bind(&no_arguments);
1963  {
1964    __ Move(rax, JSParameterCount(0));
1965    __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1966  }
1967}
1968
1969// static
1970void Builtins::Generate_FunctionPrototypeCall(MacroAssembler* masm) {
1971  // Stack Layout:
1972  // rsp[0]           : Return address
1973  // rsp[8]           : Argument 0 (receiver: callable to call)
1974  // rsp[16]          : Argument 1
1975  //  ...
1976  // rsp[8 * n]       : Argument n-1
1977  // rsp[8 * (n + 1)] : Argument n
1978  // rax contains the number of arguments, n.
1979
1980  // 1. Get the callable to call (passed as receiver) from the stack.
1981  {
1982    StackArgumentsAccessor args(rax);
1983    __ movq(rdi, args.GetReceiverOperand());
1984  }
1985
1986  // 2. Save the return address and drop the callable.
1987  __ PopReturnAddressTo(rbx);
1988  __ Pop(kScratchRegister);
1989
1990  // 3. Make sure we have at least one argument.
1991  {
1992    Label done;
1993    __ cmpq(rax, Immediate(JSParameterCount(0)));
1994    __ j(greater, &done, Label::kNear);
1995    __ PushRoot(RootIndex::kUndefinedValue);
1996    __ incq(rax);
1997    __ bind(&done);
1998  }
1999
2000  // 4. Push back the return address one slot down on the stack (overwriting the
2001  // original callable), making the original first argument the new receiver.
2002  __ PushReturnAddressFrom(rbx);
2003  __ decq(rax);  // One fewer argument (first argument is new receiver).
2004
2005  // 5. Call the callable.
2006  // Since we did not create a frame for Function.prototype.call() yet,
2007  // we use a normal Call builtin here.
2008  __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
2009}
2010
2011void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
2012  // ----------- S t a t e -------------
2013  //  -- rax     : argc
2014  //  -- rsp[0]  : return address
2015  //  -- rsp[8]  : receiver
2016  //  -- rsp[16] : target         (if argc >= 1)
2017  //  -- rsp[24] : thisArgument   (if argc >= 2)
2018  //  -- rsp[32] : argumentsList  (if argc == 3)
2019  // -----------------------------------
2020
2021  // 1. Load target into rdi (if present), argumentsList into rbx (if present),
2022  // remove all arguments from the stack (including the receiver), and push
2023  // thisArgument (if present) instead.
2024  {
2025    Label done;
2026    StackArgumentsAccessor args(rax);
2027    __ LoadRoot(rdi, RootIndex::kUndefinedValue);
2028    __ movq(rdx, rdi);
2029    __ movq(rbx, rdi);
2030    __ cmpq(rax, Immediate(JSParameterCount(1)));
2031    __ j(below, &done, Label::kNear);
2032    __ movq(rdi, args[1]);  // target
2033    __ j(equal, &done, Label::kNear);
2034    __ movq(rdx, args[2]);  // thisArgument
2035    __ cmpq(rax, Immediate(JSParameterCount(3)));
2036    __ j(below, &done, Label::kNear);
2037    __ movq(rbx, args[3]);  // argumentsList
2038    __ bind(&done);
2039    __ DropArgumentsAndPushNewReceiver(rax, rdx, rcx,
2040                                       TurboAssembler::kCountIsInteger,
2041                                       TurboAssembler::kCountIncludesReceiver);
2042  }
2043
2044  // ----------- S t a t e -------------
2045  //  -- rbx     : argumentsList
2046  //  -- rdi     : target
2047  //  -- rsp[0]  : return address
2048  //  -- rsp[8]  : thisArgument
2049  // -----------------------------------
2050
2051  // 2. We don't need to check explicitly for callable target here,
2052  // since that's the first thing the Call/CallWithArrayLike builtins
2053  // will do.
2054
2055  // 3. Apply the target to the given argumentsList.
2056  __ Jump(BUILTIN_CODE(masm->isolate(), CallWithArrayLike),
2057          RelocInfo::CODE_TARGET);
2058}
2059
2060void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
2061  // ----------- S t a t e -------------
2062  //  -- rax     : argc
2063  //  -- rsp[0]  : return address
2064  //  -- rsp[8]  : receiver
2065  //  -- rsp[16] : target
2066  //  -- rsp[24] : argumentsList
2067  //  -- rsp[32] : new.target (optional)
2068  // -----------------------------------
2069
2070  // 1. Load target into rdi (if present), argumentsList into rbx (if present),
2071  // new.target into rdx (if present, otherwise use target), remove all
2072  // arguments from the stack (including the receiver), and push thisArgument
2073  // (if present) instead.
2074  {
2075    Label done;
2076    StackArgumentsAccessor args(rax);
2077    __ LoadRoot(rdi, RootIndex::kUndefinedValue);
2078    __ movq(rdx, rdi);
2079    __ movq(rbx, rdi);
2080    __ cmpq(rax, Immediate(JSParameterCount(1)));
2081    __ j(below, &done, Label::kNear);
2082    __ movq(rdi, args[1]);                     // target
2083    __ movq(rdx, rdi);                         // new.target defaults to target
2084    __ j(equal, &done, Label::kNear);
2085    __ movq(rbx, args[2]);  // argumentsList
2086    __ cmpq(rax, Immediate(JSParameterCount(3)));
2087    __ j(below, &done, Label::kNear);
2088    __ movq(rdx, args[3]);  // new.target
2089    __ bind(&done);
2090    __ DropArgumentsAndPushNewReceiver(
2091        rax, masm->RootAsOperand(RootIndex::kUndefinedValue), rcx,
2092        TurboAssembler::kCountIsInteger,
2093        TurboAssembler::kCountIncludesReceiver);
2094  }
2095
2096  // ----------- S t a t e -------------
2097  //  -- rbx     : argumentsList
2098  //  -- rdx     : new.target
2099  //  -- rdi     : target
2100  //  -- rsp[0]  : return address
2101  //  -- rsp[8]  : receiver (undefined)
2102  // -----------------------------------
2103
2104  // 2. We don't need to check explicitly for constructor target here,
2105  // since that's the first thing the Construct/ConstructWithArrayLike
2106  // builtins will do.
2107
2108  // 3. We don't need to check explicitly for constructor new.target here,
2109  // since that's the second thing the Construct/ConstructWithArrayLike
2110  // builtins will do.
2111
2112  // 4. Construct the target with the given new.target and argumentsList.
2113  __ Jump(BUILTIN_CODE(masm->isolate(), ConstructWithArrayLike),
2114          RelocInfo::CODE_TARGET);
2115}
2116
2117namespace {
2118
2119// Allocate new stack space for |count| arguments and shift all existing
2120// arguments already on the stack. |pointer_to_new_space_out| points to the
2121// first free slot on the stack to copy additional arguments to and
2122// |argc_in_out| is updated to include |count|.
2123void Generate_AllocateSpaceAndShiftExistingArguments(
2124    MacroAssembler* masm, Register count, Register argc_in_out,
2125    Register pointer_to_new_space_out, Register scratch1, Register scratch2) {
2126  DCHECK(!AreAliased(count, argc_in_out, pointer_to_new_space_out, scratch1,
2127                     scratch2, kScratchRegister));
2128  // Use pointer_to_new_space_out as scratch until we set it to the correct
2129  // value at the end.
2130  Register old_rsp = pointer_to_new_space_out;
2131  Register new_space = kScratchRegister;
2132  __ movq(old_rsp, rsp);
2133
2134  __ leaq(new_space, Operand(count, times_system_pointer_size, 0));
2135  __ AllocateStackSpace(new_space);
2136
2137  Register copy_count = argc_in_out;
2138  Register current = scratch2;
2139  Register value = kScratchRegister;
2140
2141  Label loop, entry;
2142  __ Move(current, 0);
2143  __ jmp(&entry);
2144  __ bind(&loop);
2145  __ movq(value, Operand(old_rsp, current, times_system_pointer_size, 0));
2146  __ movq(Operand(rsp, current, times_system_pointer_size, 0), value);
2147  __ incq(current);
2148  __ bind(&entry);
2149  __ cmpq(current, copy_count);
2150  __ j(less_equal, &loop, Label::kNear);
2151
2152  // Point to the next free slot above the shifted arguments (copy_count + 1
2153  // slot for the return address).
2154  __ leaq(
2155      pointer_to_new_space_out,
2156      Operand(rsp, copy_count, times_system_pointer_size, kSystemPointerSize));
2157  // We use addl instead of addq here because we can omit REX.W, saving 1 byte.
2158  // We are especially constrained here because we are close to reaching the
2159  // limit for a near jump to the stackoverflow label, so every byte counts.
2160  __ addl(argc_in_out, count);  // Update total number of arguments.
2161}
2162
2163}  // namespace
2164
2165// static
2166// TODO(v8:11615): Observe Code::kMaxArguments in CallOrConstructVarargs
2167void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
2168                                               Handle<CodeT> code) {
2169  // ----------- S t a t e -------------
2170  //  -- rdi    : target
2171  //  -- rax    : number of parameters on the stack
2172  //  -- rbx    : arguments list (a FixedArray)
2173  //  -- rcx    : len (number of elements to push from args)
2174  //  -- rdx    : new.target (for [[Construct]])
2175  //  -- rsp[0] : return address
2176  // -----------------------------------
2177
2178  if (FLAG_debug_code) {
2179    // Allow rbx to be a FixedArray, or a FixedDoubleArray if rcx == 0.
2180    Label ok, fail;
2181    __ AssertNotSmi(rbx);
2182    Register map = r9;
2183    __ LoadMap(map, rbx);
2184    __ CmpInstanceType(map, FIXED_ARRAY_TYPE);
2185    __ j(equal, &ok);
2186    __ CmpInstanceType(map, FIXED_DOUBLE_ARRAY_TYPE);
2187    __ j(not_equal, &fail);
2188    __ Cmp(rcx, 0);
2189    __ j(equal, &ok);
2190    // Fall through.
2191    __ bind(&fail);
2192    __ Abort(AbortReason::kOperandIsNotAFixedArray);
2193
2194    __ bind(&ok);
2195  }
2196
2197  Label stack_overflow;
2198  __ StackOverflowCheck(rcx, &stack_overflow, Label::kNear);
2199
2200  // Push additional arguments onto the stack.
2201  // Move the arguments already in the stack,
2202  // including the receiver and the return address.
2203  // rcx: Number of arguments to make room for.
2204  // rax: Number of arguments already on the stack.
2205  // r8: Points to first free slot on the stack after arguments were shifted.
2206  Generate_AllocateSpaceAndShiftExistingArguments(masm, rcx, rax, r8, r9, r12);
2207  // Copy the additional arguments onto the stack.
2208  {
2209    Register value = r12;
2210    Register src = rbx, dest = r8, num = rcx, current = r9;
2211    __ Move(current, 0);
2212    Label done, push, loop;
2213    __ bind(&loop);
2214    __ cmpl(current, num);
2215    __ j(equal, &done, Label::kNear);
2216    // Turn the hole into undefined as we go.
2217    __ LoadAnyTaggedField(value, FieldOperand(src, current, times_tagged_size,
2218                                              FixedArray::kHeaderSize));
2219    __ CompareRoot(value, RootIndex::kTheHoleValue);
2220    __ j(not_equal, &push, Label::kNear);
2221    __ LoadRoot(value, RootIndex::kUndefinedValue);
2222    __ bind(&push);
2223    __ movq(Operand(dest, current, times_system_pointer_size, 0), value);
2224    __ incl(current);
2225    __ jmp(&loop);
2226    __ bind(&done);
2227  }
2228
2229  // Tail-call to the actual Call or Construct builtin.
2230  __ Jump(code, RelocInfo::CODE_TARGET);
2231
2232  __ bind(&stack_overflow);
2233  __ TailCallRuntime(Runtime::kThrowStackOverflow);
2234}
2235
2236// static
2237void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm,
2238                                                      CallOrConstructMode mode,
2239                                                      Handle<CodeT> code) {
2240  // ----------- S t a t e -------------
2241  //  -- rax : the number of arguments
2242  //  -- rdx : the new target (for [[Construct]] calls)
2243  //  -- rdi : the target to call (can be any Object)
2244  //  -- rcx : start index (to support rest parameters)
2245  // -----------------------------------
2246
2247  // Check if new.target has a [[Construct]] internal method.
2248  if (mode == CallOrConstructMode::kConstruct) {
2249    Label new_target_constructor, new_target_not_constructor;
2250    __ JumpIfSmi(rdx, &new_target_not_constructor, Label::kNear);
2251    __ LoadMap(rbx, rdx);
2252    __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2253             Immediate(Map::Bits1::IsConstructorBit::kMask));
2254    __ j(not_zero, &new_target_constructor, Label::kNear);
2255    __ bind(&new_target_not_constructor);
2256    {
2257      FrameScope scope(masm, StackFrame::MANUAL);
2258      __ EnterFrame(StackFrame::INTERNAL);
2259      __ Push(rdx);
2260      __ CallRuntime(Runtime::kThrowNotConstructor);
2261    }
2262    __ bind(&new_target_constructor);
2263  }
2264
2265  Label stack_done, stack_overflow;
2266  __ movq(r8, Operand(rbp, StandardFrameConstants::kArgCOffset));
2267  __ decq(r8);  // Exclude receiver.
2268  __ subl(r8, rcx);
2269  __ j(less_equal, &stack_done);
2270  {
2271    // ----------- S t a t e -------------
2272    //  -- rax : the number of arguments already in the stack
2273    //  -- rbp : point to the caller stack frame
2274    //  -- rcx : start index (to support rest parameters)
2275    //  -- rdx : the new target (for [[Construct]] calls)
2276    //  -- rdi : the target to call (can be any Object)
2277    //  -- r8  : number of arguments to copy, i.e. arguments count - start index
2278    // -----------------------------------
2279
2280    // Check for stack overflow.
2281    __ StackOverflowCheck(r8, &stack_overflow, Label::kNear);
2282
2283    // Forward the arguments from the caller frame.
2284    // Move the arguments already in the stack,
2285    // including the receiver and the return address.
2286    // r8: Number of arguments to make room for.
2287    // rax: Number of arguments already on the stack.
2288    // r9: Points to first free slot on the stack after arguments were shifted.
2289    Generate_AllocateSpaceAndShiftExistingArguments(masm, r8, rax, r9, r12,
2290                                                    r15);
2291
2292    // Point to the first argument to copy (skipping receiver).
2293    __ leaq(rcx, Operand(rcx, times_system_pointer_size,
2294                         CommonFrameConstants::kFixedFrameSizeAboveFp +
2295                             kSystemPointerSize));
2296    __ addq(rcx, rbp);
2297
2298    // Copy the additional caller arguments onto the stack.
2299    // TODO(victorgomes): Consider using forward order as potentially more cache
2300    // friendly.
2301    {
2302      Register src = rcx, dest = r9, num = r8;
2303      Label loop;
2304      __ bind(&loop);
2305      __ decq(num);
2306      __ movq(kScratchRegister,
2307              Operand(src, num, times_system_pointer_size, 0));
2308      __ movq(Operand(dest, num, times_system_pointer_size, 0),
2309              kScratchRegister);
2310      __ j(not_zero, &loop);
2311    }
2312  }
2313  __ jmp(&stack_done, Label::kNear);
2314  __ bind(&stack_overflow);
2315  __ TailCallRuntime(Runtime::kThrowStackOverflow);
2316  __ bind(&stack_done);
2317
2318  // Tail-call to the {code} handler.
2319  __ Jump(code, RelocInfo::CODE_TARGET);
2320}
2321
2322// static
2323void Builtins::Generate_CallFunction(MacroAssembler* masm,
2324                                     ConvertReceiverMode mode) {
2325  // ----------- S t a t e -------------
2326  //  -- rax : the number of arguments
2327  //  -- rdi : the function to call (checked to be a JSFunction)
2328  // -----------------------------------
2329
2330  StackArgumentsAccessor args(rax);
2331  __ AssertCallableFunction(rdi);
2332
2333  __ LoadTaggedPointerField(
2334      rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
2335  // ----------- S t a t e -------------
2336  //  -- rax : the number of arguments
2337  //  -- rdx : the shared function info.
2338  //  -- rdi : the function to call (checked to be a JSFunction)
2339  // -----------------------------------
2340
2341  // Enter the context of the function; ToObject has to run in the function
2342  // context, and we also need to take the global proxy from the function
2343  // context in case of conversion.
2344  __ LoadTaggedPointerField(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
2345  // We need to convert the receiver for non-native sloppy mode functions.
2346  Label done_convert;
2347  __ testl(FieldOperand(rdx, SharedFunctionInfo::kFlagsOffset),
2348           Immediate(SharedFunctionInfo::IsNativeBit::kMask |
2349                     SharedFunctionInfo::IsStrictBit::kMask));
2350  __ j(not_zero, &done_convert);
2351  {
2352    // ----------- S t a t e -------------
2353    //  -- rax : the number of arguments
2354    //  -- rdx : the shared function info.
2355    //  -- rdi : the function to call (checked to be a JSFunction)
2356    //  -- rsi : the function context.
2357    // -----------------------------------
2358
2359    if (mode == ConvertReceiverMode::kNullOrUndefined) {
2360      // Patch receiver to global proxy.
2361      __ LoadGlobalProxy(rcx);
2362    } else {
2363      Label convert_to_object, convert_receiver;
2364      __ movq(rcx, args.GetReceiverOperand());
2365      __ JumpIfSmi(rcx, &convert_to_object, Label::kNear);
2366      STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
2367      __ CmpObjectType(rcx, FIRST_JS_RECEIVER_TYPE, rbx);
2368      __ j(above_equal, &done_convert);
2369      if (mode != ConvertReceiverMode::kNotNullOrUndefined) {
2370        Label convert_global_proxy;
2371        __ JumpIfRoot(rcx, RootIndex::kUndefinedValue, &convert_global_proxy,
2372                      Label::kNear);
2373        __ JumpIfNotRoot(rcx, RootIndex::kNullValue, &convert_to_object,
2374                         Label::kNear);
2375        __ bind(&convert_global_proxy);
2376        {
2377          // Patch receiver to global proxy.
2378          __ LoadGlobalProxy(rcx);
2379        }
2380        __ jmp(&convert_receiver);
2381      }
2382      __ bind(&convert_to_object);
2383      {
2384        // Convert receiver using ToObject.
2385        // TODO(bmeurer): Inline the allocation here to avoid building the frame
2386        // in the fast case? (fall back to AllocateInNewSpace?)
2387        FrameScope scope(masm, StackFrame::INTERNAL);
2388        __ SmiTag(rax);
2389        __ Push(rax);
2390        __ Push(rdi);
2391        __ movq(rax, rcx);
2392        __ Push(rsi);
2393        __ Call(BUILTIN_CODE(masm->isolate(), ToObject),
2394                RelocInfo::CODE_TARGET);
2395        __ Pop(rsi);
2396        __ movq(rcx, rax);
2397        __ Pop(rdi);
2398        __ Pop(rax);
2399        __ SmiUntag(rax);
2400      }
2401      __ LoadTaggedPointerField(
2402          rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
2403      __ bind(&convert_receiver);
2404    }
2405    __ movq(args.GetReceiverOperand(), rcx);
2406  }
2407  __ bind(&done_convert);
2408
2409  // ----------- S t a t e -------------
2410  //  -- rax : the number of arguments
2411  //  -- rdx : the shared function info.
2412  //  -- rdi : the function to call (checked to be a JSFunction)
2413  //  -- rsi : the function context.
2414  // -----------------------------------
2415
2416  __ movzxwq(
2417      rbx, FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
2418  __ InvokeFunctionCode(rdi, no_reg, rbx, rax, InvokeType::kJump);
2419}
2420
2421namespace {
2422
2423void Generate_PushBoundArguments(MacroAssembler* masm) {
2424  // ----------- S t a t e -------------
2425  //  -- rax : the number of arguments
2426  //  -- rdx : new.target (only in case of [[Construct]])
2427  //  -- rdi : target (checked to be a JSBoundFunction)
2428  // -----------------------------------
2429
2430  // Load [[BoundArguments]] into rcx and length of that into rbx.
2431  Label no_bound_arguments;
2432  __ LoadTaggedPointerField(
2433      rcx, FieldOperand(rdi, JSBoundFunction::kBoundArgumentsOffset));
2434  __ SmiUntagField(rbx, FieldOperand(rcx, FixedArray::kLengthOffset));
2435  __ testl(rbx, rbx);
2436  __ j(zero, &no_bound_arguments);
2437  {
2438    // ----------- S t a t e -------------
2439    //  -- rax : the number of arguments
2440    //  -- rdx : new.target (only in case of [[Construct]])
2441    //  -- rdi : target (checked to be a JSBoundFunction)
2442    //  -- rcx : the [[BoundArguments]] (implemented as FixedArray)
2443    //  -- rbx : the number of [[BoundArguments]] (checked to be non-zero)
2444    // -----------------------------------
2445
2446    // TODO(victor): Use Generate_StackOverflowCheck here.
2447    // Check the stack for overflow.
2448    {
2449      Label done;
2450      __ shlq(rbx, Immediate(kSystemPointerSizeLog2));
2451      __ movq(kScratchRegister, rsp);
2452      __ subq(kScratchRegister, rbx);
2453
2454      // We are not trying to catch interruptions (i.e. debug break and
2455      // preemption) here, so check the "real stack limit".
2456      __ cmpq(kScratchRegister,
2457              __ StackLimitAsOperand(StackLimitKind::kRealStackLimit));
2458      __ j(above_equal, &done, Label::kNear);
2459      {
2460        FrameScope scope(masm, StackFrame::MANUAL);
2461        __ EnterFrame(StackFrame::INTERNAL);
2462        __ CallRuntime(Runtime::kThrowStackOverflow);
2463      }
2464      __ bind(&done);
2465    }
2466
2467    // Save Return Address and Receiver into registers.
2468    __ Pop(r8);
2469    __ Pop(r10);
2470
2471    // Push [[BoundArguments]] to the stack.
2472    {
2473      Label loop;
2474      __ LoadTaggedPointerField(
2475          rcx, FieldOperand(rdi, JSBoundFunction::kBoundArgumentsOffset));
2476      __ SmiUntagField(rbx, FieldOperand(rcx, FixedArray::kLengthOffset));
2477      __ addq(rax, rbx);  // Adjust effective number of arguments.
2478      __ bind(&loop);
2479      // Instead of doing decl(rbx) here subtract kTaggedSize from the header
2480      // offset in order to be able to move decl(rbx) right before the loop
2481      // condition. This is necessary in order to avoid flags corruption by
2482      // pointer decompression code.
2483      __ LoadAnyTaggedField(
2484          r12, FieldOperand(rcx, rbx, times_tagged_size,
2485                            FixedArray::kHeaderSize - kTaggedSize));
2486      __ Push(r12);
2487      __ decl(rbx);
2488      __ j(greater, &loop);
2489    }
2490
2491    // Recover Receiver and Return Address.
2492    __ Push(r10);
2493    __ Push(r8);
2494  }
2495  __ bind(&no_bound_arguments);
2496}
2497
2498}  // namespace
2499
2500// static
2501void Builtins::Generate_CallBoundFunctionImpl(MacroAssembler* masm) {
2502  // ----------- S t a t e -------------
2503  //  -- rax : the number of arguments
2504  //  -- rdi : the function to call (checked to be a JSBoundFunction)
2505  // -----------------------------------
2506  __ AssertBoundFunction(rdi);
2507
2508  // Patch the receiver to [[BoundThis]].
2509  StackArgumentsAccessor args(rax);
2510  __ LoadAnyTaggedField(rbx,
2511                        FieldOperand(rdi, JSBoundFunction::kBoundThisOffset));
2512  __ movq(args.GetReceiverOperand(), rbx);
2513
2514  // Push the [[BoundArguments]] onto the stack.
2515  Generate_PushBoundArguments(masm);
2516
2517  // Call the [[BoundTargetFunction]] via the Call builtin.
2518  __ LoadTaggedPointerField(
2519      rdi, FieldOperand(rdi, JSBoundFunction::kBoundTargetFunctionOffset));
2520  __ Jump(BUILTIN_CODE(masm->isolate(), Call_ReceiverIsAny),
2521          RelocInfo::CODE_TARGET);
2522}
2523
2524// static
2525void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
2526  // ----------- S t a t e -------------
2527  //  -- rax : the number of arguments
2528  //  -- rdi : the target to call (can be any Object)
2529  // -----------------------------------
2530  Register argc = rax;
2531  Register target = rdi;
2532  Register map = rcx;
2533  Register instance_type = rdx;
2534  DCHECK(!AreAliased(argc, target, map, instance_type));
2535
2536  StackArgumentsAccessor args(argc);
2537
2538  Label non_callable, class_constructor;
2539  __ JumpIfSmi(target, &non_callable);
2540  __ LoadMap(map, target);
2541  __ CmpInstanceTypeRange(map, instance_type, FIRST_CALLABLE_JS_FUNCTION_TYPE,
2542                          LAST_CALLABLE_JS_FUNCTION_TYPE);
2543  __ Jump(masm->isolate()->builtins()->CallFunction(mode),
2544          RelocInfo::CODE_TARGET, below_equal);
2545
2546  __ cmpw(instance_type, Immediate(JS_BOUND_FUNCTION_TYPE));
2547  __ Jump(BUILTIN_CODE(masm->isolate(), CallBoundFunction),
2548          RelocInfo::CODE_TARGET, equal);
2549
2550  // Check if target has a [[Call]] internal method.
2551  __ testb(FieldOperand(map, Map::kBitFieldOffset),
2552           Immediate(Map::Bits1::IsCallableBit::kMask));
2553  __ j(zero, &non_callable, Label::kNear);
2554
2555  // Check if target is a proxy and call CallProxy external builtin
2556  __ cmpw(instance_type, Immediate(JS_PROXY_TYPE));
2557  __ Jump(BUILTIN_CODE(masm->isolate(), CallProxy), RelocInfo::CODE_TARGET,
2558          equal);
2559
2560  // Check if target is a wrapped function and call CallWrappedFunction external
2561  // builtin
2562  __ cmpw(instance_type, Immediate(JS_WRAPPED_FUNCTION_TYPE));
2563  __ Jump(BUILTIN_CODE(masm->isolate(), CallWrappedFunction),
2564          RelocInfo::CODE_TARGET, equal);
2565
2566  // ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
2567  // Check that the function is not a "classConstructor".
2568  __ cmpw(instance_type, Immediate(JS_CLASS_CONSTRUCTOR_TYPE));
2569  __ j(equal, &class_constructor);
2570
2571  // 2. Call to something else, which might have a [[Call]] internal method (if
2572  // not we raise an exception).
2573
2574  // Overwrite the original receiver with the (original) target.
2575  __ movq(args.GetReceiverOperand(), target);
2576  // Let the "call_as_function_delegate" take care of the rest.
2577  __ LoadNativeContextSlot(target, Context::CALL_AS_FUNCTION_DELEGATE_INDEX);
2578  __ Jump(masm->isolate()->builtins()->CallFunction(
2579              ConvertReceiverMode::kNotNullOrUndefined),
2580          RelocInfo::CODE_TARGET);
2581
2582  // 3. Call to something that is not callable.
2583  __ bind(&non_callable);
2584  {
2585    FrameScope scope(masm, StackFrame::INTERNAL);
2586    __ Push(target);
2587    __ CallRuntime(Runtime::kThrowCalledNonCallable);
2588    __ Trap();  // Unreachable.
2589  }
2590
2591  // 4. The function is a "classConstructor", need to raise an exception.
2592  __ bind(&class_constructor);
2593  {
2594    FrameScope frame(masm, StackFrame::INTERNAL);
2595    __ Push(target);
2596    __ CallRuntime(Runtime::kThrowConstructorNonCallableError);
2597    __ Trap();  // Unreachable.
2598  }
2599}
2600
2601// static
2602void Builtins::Generate_ConstructFunction(MacroAssembler* masm) {
2603  // ----------- S t a t e -------------
2604  //  -- rax : the number of arguments
2605  //  -- rdx : the new target (checked to be a constructor)
2606  //  -- rdi : the constructor to call (checked to be a JSFunction)
2607  // -----------------------------------
2608  __ AssertConstructor(rdi);
2609  __ AssertFunction(rdi);
2610
2611  // Calling convention for function specific ConstructStubs require
2612  // rbx to contain either an AllocationSite or undefined.
2613  __ LoadRoot(rbx, RootIndex::kUndefinedValue);
2614
2615  // Jump to JSBuiltinsConstructStub or JSConstructStubGeneric.
2616  __ LoadTaggedPointerField(
2617      rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
2618  __ testl(FieldOperand(rcx, SharedFunctionInfo::kFlagsOffset),
2619           Immediate(SharedFunctionInfo::ConstructAsBuiltinBit::kMask));
2620  __ Jump(BUILTIN_CODE(masm->isolate(), JSBuiltinsConstructStub),
2621          RelocInfo::CODE_TARGET, not_zero);
2622
2623  __ Jump(BUILTIN_CODE(masm->isolate(), JSConstructStubGeneric),
2624          RelocInfo::CODE_TARGET);
2625}
2626
2627// static
2628void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) {
2629  // ----------- S t a t e -------------
2630  //  -- rax : the number of arguments
2631  //  -- rdx : the new target (checked to be a constructor)
2632  //  -- rdi : the constructor to call (checked to be a JSBoundFunction)
2633  // -----------------------------------
2634  __ AssertConstructor(rdi);
2635  __ AssertBoundFunction(rdi);
2636
2637  // Push the [[BoundArguments]] onto the stack.
2638  Generate_PushBoundArguments(masm);
2639
2640  // Patch new.target to [[BoundTargetFunction]] if new.target equals target.
2641  {
2642    Label done;
2643    __ cmpq(rdi, rdx);
2644    __ j(not_equal, &done, Label::kNear);
2645    __ LoadTaggedPointerField(
2646        rdx, FieldOperand(rdi, JSBoundFunction::kBoundTargetFunctionOffset));
2647    __ bind(&done);
2648  }
2649
2650  // Construct the [[BoundTargetFunction]] via the Construct builtin.
2651  __ LoadTaggedPointerField(
2652      rdi, FieldOperand(rdi, JSBoundFunction::kBoundTargetFunctionOffset));
2653  __ Jump(BUILTIN_CODE(masm->isolate(), Construct), RelocInfo::CODE_TARGET);
2654}
2655
2656// static
2657void Builtins::Generate_Construct(MacroAssembler* masm) {
2658  // ----------- S t a t e -------------
2659  //  -- rax : the number of arguments
2660  //  -- rdx : the new target (either the same as the constructor or
2661  //           the JSFunction on which new was invoked initially)
2662  //  -- rdi : the constructor to call (can be any Object)
2663  // -----------------------------------
2664  Register argc = rax;
2665  Register target = rdi;
2666  Register map = rcx;
2667  Register instance_type = r8;
2668  DCHECK(!AreAliased(argc, target, map, instance_type));
2669
2670  StackArgumentsAccessor args(argc);
2671
2672  // Check if target is a Smi.
2673  Label non_constructor;
2674  __ JumpIfSmi(target, &non_constructor);
2675
2676  // Check if target has a [[Construct]] internal method.
2677  __ LoadMap(map, target);
2678  __ testb(FieldOperand(map, Map::kBitFieldOffset),
2679           Immediate(Map::Bits1::IsConstructorBit::kMask));
2680  __ j(zero, &non_constructor);
2681
2682  // Dispatch based on instance type.
2683  __ CmpInstanceTypeRange(map, instance_type, FIRST_JS_FUNCTION_TYPE,
2684                          LAST_JS_FUNCTION_TYPE);
2685  __ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction),
2686          RelocInfo::CODE_TARGET, below_equal);
2687
2688  // Only dispatch to bound functions after checking whether they are
2689  // constructors.
2690  __ cmpw(instance_type, Immediate(JS_BOUND_FUNCTION_TYPE));
2691  __ Jump(BUILTIN_CODE(masm->isolate(), ConstructBoundFunction),
2692          RelocInfo::CODE_TARGET, equal);
2693
2694  // Only dispatch to proxies after checking whether they are constructors.
2695  __ cmpw(instance_type, Immediate(JS_PROXY_TYPE));
2696  __ Jump(BUILTIN_CODE(masm->isolate(), ConstructProxy), RelocInfo::CODE_TARGET,
2697          equal);
2698
2699  // Called Construct on an exotic Object with a [[Construct]] internal method.
2700  {
2701    // Overwrite the original receiver with the (original) target.
2702    __ movq(args.GetReceiverOperand(), target);
2703    // Let the "call_as_constructor_delegate" take care of the rest.
2704    __ LoadNativeContextSlot(target,
2705                             Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX);
2706    __ Jump(masm->isolate()->builtins()->CallFunction(),
2707            RelocInfo::CODE_TARGET);
2708  }
2709
2710  // Called Construct on an Object that doesn't have a [[Construct]] internal
2711  // method.
2712  __ bind(&non_constructor);
2713  __ Jump(BUILTIN_CODE(masm->isolate(), ConstructedNonConstructable),
2714          RelocInfo::CODE_TARGET);
2715}
2716
2717namespace {
2718
2719void Generate_OSREntry(MacroAssembler* masm, Register entry_address) {
2720  // Overwrite the return address on the stack.
2721  __ movq(StackOperandForReturnAddress(0), entry_address);
2722
2723  // And "return" to the OSR entry point of the function.
2724  __ ret(0);
2725}
2726
2727enum class OsrSourceTier {
2728  kInterpreter,
2729  kBaseline,
2730};
2731
2732void OnStackReplacement(MacroAssembler* masm, OsrSourceTier source) {
2733  {
2734    FrameScope scope(masm, StackFrame::INTERNAL);
2735    __ CallRuntime(Runtime::kCompileOptimizedOSR);
2736  }
2737
2738  Label jump_to_returned_code;
2739  // If the code object is null, just return to the caller.
2740  __ testq(rax, rax);
2741  __ j(not_equal, &jump_to_returned_code, Label::kNear);
2742  __ ret(0);
2743
2744  __ bind(&jump_to_returned_code);
2745
2746  if (source == OsrSourceTier::kInterpreter) {
2747    // Drop the handler frame that is be sitting on top of the actual
2748    // JavaScript frame. This is the case then OSR is triggered from bytecode.
2749    __ leave();
2750  }
2751
2752  if (V8_EXTERNAL_CODE_SPACE_BOOL) {
2753    __ LoadCodeDataContainerCodeNonBuiltin(rax, rax);
2754  }
2755
2756  // Load deoptimization data from the code object.
2757  __ LoadTaggedPointerField(
2758      rbx, FieldOperand(rax, Code::kDeoptimizationDataOrInterpreterDataOffset));
2759
2760  // Load the OSR entrypoint offset from the deoptimization data.
2761  __ SmiUntagField(
2762      rbx, FieldOperand(rbx, FixedArray::OffsetOfElementAt(
2763                                 DeoptimizationData::kOsrPcOffsetIndex)));
2764
2765  // Compute the target address = code_obj + header_size + osr_offset
2766  __ leaq(rax, FieldOperand(rax, rbx, times_1, Code::kHeaderSize));
2767
2768  Generate_OSREntry(masm, rax);
2769}
2770
2771}  // namespace
2772
2773void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) {
2774  OnStackReplacement(masm, OsrSourceTier::kInterpreter);
2775}
2776
2777void Builtins::Generate_BaselineOnStackReplacement(MacroAssembler* masm) {
2778  __ movq(kContextRegister,
2779          MemOperand(rbp, BaselineFrameConstants::kContextOffset));
2780  OnStackReplacement(masm, OsrSourceTier::kBaseline);
2781}
2782
2783#if V8_ENABLE_WEBASSEMBLY
2784void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
2785  // The function index was pushed to the stack by the caller as int32.
2786  __ Pop(r15);
2787  // Convert to Smi for the runtime call.
2788  __ SmiTag(r15);
2789
2790  {
2791    HardAbortScope hard_abort(masm);  // Avoid calls to Abort.
2792    FrameScope scope(masm, StackFrame::WASM_COMPILE_LAZY);
2793
2794    // Save all parameter registers (see wasm-linkage.h). They might be
2795    // overwritten in the runtime call below. We don't have any callee-saved
2796    // registers in wasm, so no need to store anything else.
2797    static_assert(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs ==
2798                      arraysize(wasm::kGpParamRegisters),
2799                  "frame size mismatch");
2800    for (Register reg : wasm::kGpParamRegisters) {
2801      __ Push(reg);
2802    }
2803    static_assert(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs ==
2804                      arraysize(wasm::kFpParamRegisters),
2805                  "frame size mismatch");
2806    __ AllocateStackSpace(kSimd128Size * arraysize(wasm::kFpParamRegisters));
2807    int offset = 0;
2808    for (DoubleRegister reg : wasm::kFpParamRegisters) {
2809      __ movdqu(Operand(rsp, offset), reg);
2810      offset += kSimd128Size;
2811    }
2812
2813    // Push the Wasm instance for loading the jump table address after the
2814    // runtime call.
2815    __ Push(kWasmInstanceRegister);
2816
2817    // Push the Wasm instance again as an explicit argument to the runtime
2818    // function.
2819    __ Push(kWasmInstanceRegister);
2820    // Push the function index as second argument.
2821    __ Push(r15);
2822    // Initialize the JavaScript context with 0. CEntry will use it to
2823    // set the current context on the isolate.
2824    __ Move(kContextRegister, Smi::zero());
2825    __ CallRuntime(Runtime::kWasmCompileLazy, 2);
2826    // The runtime function returns the jump table slot offset as a Smi. Use
2827    // that to compute the jump target in r15.
2828    __ Pop(kWasmInstanceRegister);
2829    __ movq(r15, MemOperand(kWasmInstanceRegister,
2830                            wasm::ObjectAccess::ToTagged(
2831                                WasmInstanceObject::kJumpTableStartOffset)));
2832    __ SmiUntag(kReturnRegister0);
2833    __ addq(r15, kReturnRegister0);
2834    // r15 now holds the jump table slot where we want to jump to in the end.
2835
2836    // Restore registers.
2837    for (DoubleRegister reg : base::Reversed(wasm::kFpParamRegisters)) {
2838      offset -= kSimd128Size;
2839      __ movdqu(reg, Operand(rsp, offset));
2840    }
2841    DCHECK_EQ(0, offset);
2842    __ addq(rsp, Immediate(kSimd128Size * arraysize(wasm::kFpParamRegisters)));
2843    for (Register reg : base::Reversed(wasm::kGpParamRegisters)) {
2844      __ Pop(reg);
2845    }
2846  }
2847
2848  // Finally, jump to the jump table slot for the function.
2849  __ jmp(r15);
2850}
2851
2852void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
2853  HardAbortScope hard_abort(masm);  // Avoid calls to Abort.
2854  {
2855    FrameScope scope(masm, StackFrame::WASM_DEBUG_BREAK);
2856
2857    // Save all parameter registers. They might hold live values, we restore
2858    // them after the runtime call.
2859    for (Register reg :
2860         base::Reversed(WasmDebugBreakFrameConstants::kPushedGpRegs)) {
2861      __ Push(reg);
2862    }
2863
2864    constexpr int kFpStackSize =
2865        kSimd128Size * WasmDebugBreakFrameConstants::kNumPushedFpRegisters;
2866    __ AllocateStackSpace(kFpStackSize);
2867    int offset = kFpStackSize;
2868    for (DoubleRegister reg :
2869         base::Reversed(WasmDebugBreakFrameConstants::kPushedFpRegs)) {
2870      offset -= kSimd128Size;
2871      __ movdqu(Operand(rsp, offset), reg);
2872    }
2873
2874    // Initialize the JavaScript context with 0. CEntry will use it to
2875    // set the current context on the isolate.
2876    __ Move(kContextRegister, Smi::zero());
2877    __ CallRuntime(Runtime::kWasmDebugBreak, 0);
2878
2879    // Restore registers.
2880    for (DoubleRegister reg : WasmDebugBreakFrameConstants::kPushedFpRegs) {
2881      __ movdqu(reg, Operand(rsp, offset));
2882      offset += kSimd128Size;
2883    }
2884    __ addq(rsp, Immediate(kFpStackSize));
2885    for (Register reg : WasmDebugBreakFrameConstants::kPushedGpRegs) {
2886      __ Pop(reg);
2887    }
2888  }
2889
2890  __ ret(0);
2891}
2892
2893namespace {
2894// Helper functions for the GenericJSToWasmWrapper.
2895void PrepareForBuiltinCall(MacroAssembler* masm, MemOperand GCScanSlotPlace,
2896                           const int GCScanSlotCount, Register current_param,
2897                           Register param_limit,
2898                           Register current_int_param_slot,
2899                           Register current_float_param_slot,
2900                           Register valuetypes_array_ptr,
2901                           Register wasm_instance, Register function_data) {
2902  // Pushes and puts the values in order onto the stack before builtin calls for
2903  // the GenericJSToWasmWrapper.
2904  __ Move(GCScanSlotPlace, GCScanSlotCount);
2905  __ pushq(current_param);
2906  __ pushq(param_limit);
2907  __ pushq(current_int_param_slot);
2908  __ pushq(current_float_param_slot);
2909  __ pushq(valuetypes_array_ptr);
2910  __ pushq(wasm_instance);
2911  __ pushq(function_data);
2912  // We had to prepare the parameters for the Call: we have to put the context
2913  // into rsi.
2914  __ LoadAnyTaggedField(
2915      rsi,
2916      MemOperand(wasm_instance, wasm::ObjectAccess::ToTagged(
2917                                    WasmInstanceObject::kNativeContextOffset)));
2918}
2919
2920void RestoreAfterBuiltinCall(MacroAssembler* masm, Register function_data,
2921                             Register wasm_instance,
2922                             Register valuetypes_array_ptr,
2923                             Register current_float_param_slot,
2924                             Register current_int_param_slot,
2925                             Register param_limit, Register current_param) {
2926  // Pop and load values from the stack in order into the registers after
2927  // builtin calls for the GenericJSToWasmWrapper.
2928  __ popq(function_data);
2929  __ popq(wasm_instance);
2930  __ popq(valuetypes_array_ptr);
2931  __ popq(current_float_param_slot);
2932  __ popq(current_int_param_slot);
2933  __ popq(param_limit);
2934  __ popq(current_param);
2935}
2936
2937void FillJumpBuffer(MacroAssembler* masm, Register jmpbuf, Label* pc) {
2938  __ movq(MemOperand(jmpbuf, wasm::kJmpBufSpOffset), rsp);
2939  __ movq(MemOperand(jmpbuf, wasm::kJmpBufFpOffset), rbp);
2940  __ movq(kScratchRegister,
2941          __ StackLimitAsOperand(StackLimitKind::kRealStackLimit));
2942  __ movq(MemOperand(jmpbuf, wasm::kJmpBufStackLimitOffset), kScratchRegister);
2943  __ leaq(kScratchRegister, MemOperand(pc, 0));
2944  __ movq(MemOperand(jmpbuf, wasm::kJmpBufPcOffset), kScratchRegister);
2945}
2946
2947void LoadJumpBuffer(MacroAssembler* masm, Register jmpbuf, bool load_pc) {
2948  __ movq(rsp, MemOperand(jmpbuf, wasm::kJmpBufSpOffset));
2949  __ movq(rbp, MemOperand(jmpbuf, wasm::kJmpBufFpOffset));
2950  if (load_pc) {
2951    __ jmp(MemOperand(jmpbuf, wasm::kJmpBufPcOffset));
2952  }
2953  // The stack limit is set separately under the ExecutionAccess lock.
2954}
2955
2956void SaveState(MacroAssembler* masm, Register active_continuation, Register tmp,
2957               Label* suspend) {
2958  Register foreign_jmpbuf = tmp;
2959  __ LoadAnyTaggedField(
2960      foreign_jmpbuf,
2961      FieldOperand(active_continuation, WasmContinuationObject::kJmpbufOffset));
2962  Register jmpbuf = foreign_jmpbuf;
2963  __ LoadExternalPointerField(
2964      jmpbuf, FieldOperand(foreign_jmpbuf, Foreign::kForeignAddressOffset),
2965      kForeignForeignAddressTag, kScratchRegister);
2966  FillJumpBuffer(masm, jmpbuf, suspend);
2967}
2968
2969// Returns the new continuation in rax.
2970void AllocateContinuation(MacroAssembler* masm, Register function_data,
2971                          Register wasm_instance) {
2972  Register suspender = kScratchRegister;
2973  __ LoadAnyTaggedField(
2974      suspender,
2975      FieldOperand(function_data, WasmExportedFunctionData::kSuspenderOffset));
2976  MemOperand GCScanSlotPlace =
2977      MemOperand(rbp, BuiltinWasmWrapperConstants::kGCScanSlotCountOffset);
2978  __ Move(GCScanSlotPlace, 3);
2979  __ Push(wasm_instance);
2980  __ Push(function_data);
2981  __ Push(suspender);  // Argument.
2982  __ Move(kContextRegister, Smi::zero());
2983  __ CallRuntime(Runtime::kWasmAllocateContinuation);
2984  __ Pop(function_data);
2985  __ Pop(wasm_instance);
2986  STATIC_ASSERT(kReturnRegister0 == rax);
2987  suspender = no_reg;
2988}
2989
2990void LoadTargetJumpBuffer(MacroAssembler* masm, Register target_continuation) {
2991  Register foreign_jmpbuf = target_continuation;
2992  __ LoadAnyTaggedField(
2993      foreign_jmpbuf,
2994      FieldOperand(target_continuation, WasmContinuationObject::kJmpbufOffset));
2995  Register target_jmpbuf = foreign_jmpbuf;
2996  __ LoadExternalPointerField(
2997      target_jmpbuf,
2998      FieldOperand(foreign_jmpbuf, Foreign::kForeignAddressOffset),
2999      kForeignForeignAddressTag, kScratchRegister);
3000  MemOperand GCScanSlotPlace =
3001      MemOperand(rbp, BuiltinWasmWrapperConstants::kGCScanSlotCountOffset);
3002  __ Move(GCScanSlotPlace, 0);
3003  // Switch stack!
3004  LoadJumpBuffer(masm, target_jmpbuf, false);
3005}
3006
3007void ReloadParentContinuation(MacroAssembler* masm, Register wasm_instance,
3008                              Register return_reg, Register tmp1,
3009                              Register tmp2) {
3010  Register active_continuation = tmp1;
3011  __ LoadRoot(active_continuation, RootIndex::kActiveContinuation);
3012
3013  // Set a null pointer in the jump buffer's SP slot to indicate to the stack
3014  // frame iterator that this stack is empty.
3015  Register foreign_jmpbuf = kScratchRegister;
3016  __ LoadAnyTaggedField(
3017      foreign_jmpbuf,
3018      FieldOperand(active_continuation, WasmContinuationObject::kJmpbufOffset));
3019  Register jmpbuf = foreign_jmpbuf;
3020  __ LoadExternalPointerField(
3021      jmpbuf, FieldOperand(foreign_jmpbuf, Foreign::kForeignAddressOffset),
3022      kForeignForeignAddressTag, tmp2);
3023  __ movq(Operand(jmpbuf, wasm::kJmpBufSpOffset), Immediate(kNullAddress));
3024
3025  Register parent = tmp2;
3026  __ LoadAnyTaggedField(
3027      parent,
3028      FieldOperand(active_continuation, WasmContinuationObject::kParentOffset));
3029
3030  // Update active continuation root.
3031  __ movq(masm->RootAsOperand(RootIndex::kActiveContinuation), parent);
3032  foreign_jmpbuf = tmp1;
3033  __ LoadAnyTaggedField(
3034      foreign_jmpbuf,
3035      FieldOperand(parent, WasmContinuationObject::kJmpbufOffset));
3036  jmpbuf = foreign_jmpbuf;
3037  __ LoadExternalPointerField(
3038      jmpbuf, FieldOperand(foreign_jmpbuf, Foreign::kForeignAddressOffset),
3039      kForeignForeignAddressTag, tmp2);
3040
3041  // Switch stack!
3042  LoadJumpBuffer(masm, jmpbuf, false);
3043  MemOperand GCScanSlotPlace =
3044      MemOperand(rbp, BuiltinWasmWrapperConstants::kGCScanSlotCountOffset);
3045  __ Move(GCScanSlotPlace, 1);
3046  __ Push(return_reg);
3047  __ Push(wasm_instance);  // Spill.
3048  __ Move(kContextRegister, Smi::zero());
3049  __ CallRuntime(Runtime::kWasmSyncStackLimit);
3050  __ Pop(wasm_instance);
3051  __ Pop(return_reg);
3052}
3053
3054void RestoreParentSuspender(MacroAssembler* masm) {
3055  Register suspender = kScratchRegister;
3056  __ LoadRoot(suspender, RootIndex::kActiveSuspender);
3057  __ LoadAnyTaggedField(
3058      suspender, FieldOperand(suspender, WasmSuspenderObject::kParentOffset));
3059  __ CompareRoot(suspender, RootIndex::kUndefinedValue);
3060  Label undefined;
3061  __ j(equal, &undefined, Label::kNear);
3062#ifdef DEBUG
3063  // Check that the parent suspender is inactive.
3064  Label parent_inactive;
3065  Register state = rbx;
3066  __ LoadTaggedSignedField(
3067      state, FieldOperand(suspender, WasmSuspenderObject::kStateOffset));
3068  __ SmiCompare(state, Smi::FromInt(WasmSuspenderObject::Inactive));
3069  __ j(equal, &parent_inactive, Label::kNear);
3070  __ Trap();
3071  __ bind(&parent_inactive);
3072#endif
3073  __ StoreTaggedSignedField(
3074      FieldOperand(suspender, WasmSuspenderObject::kStateOffset),
3075      Smi::FromInt(WasmSuspenderObject::State::Active));
3076  __ bind(&undefined);
3077  __ movq(masm->RootAsOperand(RootIndex::kActiveSuspender), suspender);
3078}
3079
3080void LoadFunctionDataAndWasmInstance(MacroAssembler* masm,
3081                                     Register function_data,
3082                                     Register wasm_instance) {
3083  Register closure = function_data;
3084  Register shared_function_info = closure;
3085  __ LoadAnyTaggedField(
3086      shared_function_info,
3087      MemOperand(
3088          closure,
3089          wasm::ObjectAccess::SharedFunctionInfoOffsetInTaggedJSFunction()));
3090  closure = no_reg;
3091  __ LoadAnyTaggedField(
3092      function_data,
3093      MemOperand(shared_function_info,
3094                 SharedFunctionInfo::kFunctionDataOffset - kHeapObjectTag));
3095  shared_function_info = no_reg;
3096
3097  __ LoadAnyTaggedField(
3098      wasm_instance,
3099      MemOperand(function_data,
3100                 WasmExportedFunctionData::kInstanceOffset - kHeapObjectTag));
3101}
3102
3103void LoadValueTypesArray(MacroAssembler* masm, Register function_data,
3104                         Register valuetypes_array_ptr, Register return_count,
3105                         Register param_count) {
3106  Register foreign_signature = valuetypes_array_ptr;
3107  __ LoadAnyTaggedField(
3108      foreign_signature,
3109      MemOperand(function_data,
3110                 WasmExportedFunctionData::kSignatureOffset - kHeapObjectTag));
3111  Register signature = foreign_signature;
3112  __ LoadExternalPointerField(
3113      signature,
3114      FieldOperand(foreign_signature, Foreign::kForeignAddressOffset),
3115      kForeignForeignAddressTag, kScratchRegister);
3116  foreign_signature = no_reg;
3117  __ movq(return_count,
3118          MemOperand(signature, wasm::FunctionSig::kReturnCountOffset));
3119  __ movq(param_count,
3120          MemOperand(signature, wasm::FunctionSig::kParameterCountOffset));
3121  valuetypes_array_ptr = signature;
3122  __ movq(valuetypes_array_ptr,
3123          MemOperand(signature, wasm::FunctionSig::kRepsOffset));
3124}
3125
3126void GenericJSToWasmWrapperHelper(MacroAssembler* masm, bool stack_switch) {
3127  // Set up the stackframe.
3128  __ EnterFrame(stack_switch ? StackFrame::STACK_SWITCH
3129                             : StackFrame::JS_TO_WASM);
3130
3131  // -------------------------------------------
3132  // Compute offsets and prepare for GC.
3133  // -------------------------------------------
3134  constexpr int kGCScanSlotCountOffset =
3135      BuiltinWasmWrapperConstants::kGCScanSlotCountOffset;
3136  // The number of parameters passed to this function.
3137  constexpr int kInParamCountOffset =
3138      BuiltinWasmWrapperConstants::kInParamCountOffset;
3139  // The number of parameters according to the signature.
3140  constexpr int kParamCountOffset =
3141      BuiltinWasmWrapperConstants::kParamCountOffset;
3142  constexpr int kReturnCountOffset = kParamCountOffset - kSystemPointerSize;
3143  constexpr int kValueTypesArrayStartOffset =
3144      kReturnCountOffset - kSystemPointerSize;
3145  // A boolean flag to check if one of the parameters is a reference. If so, we
3146  // iterate over the parameters two times, first for all value types, and then
3147  // for all references.
3148  constexpr int kHasRefTypesOffset =
3149      kValueTypesArrayStartOffset - kSystemPointerSize;
3150  // We set and use this slot only when moving parameters into the parameter
3151  // registers (so no GC scan is needed).
3152  constexpr int kFunctionDataOffset = kHasRefTypesOffset - kSystemPointerSize;
3153  constexpr int kLastSpillOffset = kFunctionDataOffset;
3154  constexpr int kNumSpillSlots = 7;
3155  __ subq(rsp, Immediate(kNumSpillSlots * kSystemPointerSize));
3156  // Put the in_parameter count on the stack, we only  need it at the very end
3157  // when we pop the parameters off the stack.
3158  Register in_param_count = rax;
3159  __ decq(in_param_count);  // Exclude receiver.
3160  __ movq(MemOperand(rbp, kInParamCountOffset), in_param_count);
3161  in_param_count = no_reg;
3162
3163  Register function_data = rdi;
3164  Register wasm_instance = rsi;
3165  LoadFunctionDataAndWasmInstance(masm, function_data, wasm_instance);
3166
3167  Label compile_wrapper, compile_wrapper_done;
3168  if (!stack_switch) {
3169    // -------------------------------------------
3170    // Decrement the budget of the generic wrapper in function data.
3171    // -------------------------------------------
3172    __ SmiAddConstant(
3173        MemOperand(
3174            function_data,
3175            WasmExportedFunctionData::kWrapperBudgetOffset - kHeapObjectTag),
3176        Smi::FromInt(-1));
3177
3178    // -------------------------------------------
3179    // Check if the budget of the generic wrapper reached 0 (zero).
3180    // -------------------------------------------
3181    // Instead of a specific comparison, we can directly use the flags set
3182    // from the previous addition.
3183    __ j(less_equal, &compile_wrapper);
3184    __ bind(&compile_wrapper_done);
3185  }
3186
3187  Label suspend;
3188  if (stack_switch) {
3189    Register active_continuation = rbx;
3190    __ LoadRoot(active_continuation, RootIndex::kActiveContinuation);
3191    SaveState(masm, active_continuation, rcx, &suspend);
3192    AllocateContinuation(masm, function_data, wasm_instance);
3193    Register target_continuation = rax; /* fixed */
3194    // Save the old stack's rbp in r9, and use it to access the parameters in
3195    // the parent frame.
3196    // We also distribute the spill slots across the two stacks as needed by
3197    // creating a "shadow frame":
3198    //
3199    //      old stack:                    new stack:
3200    //      +-----------------+
3201    //      | <parent frame>  |
3202    // r9-> +-----------------+           +-----------------+
3203    //      | <fixed>         |           | 0 (jmpbuf rbp)  |
3204    //      +-----------------+     rbp-> +-----------------+
3205    //      |kGCScanSlotCount |           |kGCScanSlotCount |
3206    //      +-----------------+           +-----------------+
3207    //      | kParamCount     |           |      /          |
3208    //      +-----------------+           +-----------------+
3209    //      | kInParamCount   |           |      /          |
3210    //      +-----------------+           +-----------------+
3211    //      |      /          |           | kReturnCount    |
3212    //      +-----------------+           +-----------------+
3213    //      |      /          |           |kValueTypesArray |
3214    //      +-----------------+           +-----------------+
3215    //      |      /          |           | kHasRefTypes    |
3216    //      +-----------------+           +-----------------+
3217    //      |      /          |           | kFunctionData   |
3218    //      +-----------------+    rsp->  +-----------------+
3219    //          seal stack                         |
3220    //                                             V
3221    //
3222    // - When we first enter the prompt, we have access to both frames, so it
3223    // does not matter where the values are spilled.
3224    // - When we suspend for the first time, we longjmp to the original frame
3225    // (left).  So the frame needs to contain the necessary information to
3226    // properly deconstruct itself (actual param count and signature param
3227    // count).
3228    // - When we suspend for the second time, we longjmp to the frame that was
3229    // set up by the WasmResume builtin, which has the same layout as the
3230    // original frame (left).
3231    // - When the closure finally resolves, we use the value types pointer
3232    // stored in the shadow frame to get the return type and convert the return
3233    // value accordingly.
3234    __ movq(r9, rbp);
3235    LoadTargetJumpBuffer(masm, target_continuation);
3236    // Push the loaded rbp. We know it is null, because there is no frame yet,
3237    // so we could also push 0 directly. In any case we need to push it, because
3238    // this marks the base of the stack segment for the stack frame iterator.
3239    __ pushq(rbp);
3240    __ movq(rbp, rsp);
3241    __ addq(rsp, Immediate(kLastSpillOffset));
3242  }
3243  Register original_fp = stack_switch ? r9 : rbp;
3244
3245  // -------------------------------------------
3246  // Load values from the signature.
3247  // -------------------------------------------
3248  Register valuetypes_array_ptr = r11;
3249  Register return_count = r8;
3250  Register param_count = rcx;
3251  LoadValueTypesArray(masm, function_data, valuetypes_array_ptr, return_count,
3252                      param_count);
3253
3254  // Initialize the {HasRefTypes} slot.
3255  __ movq(MemOperand(rbp, kHasRefTypesOffset), Immediate(0));
3256
3257  // -------------------------------------------
3258  // Store signature-related values to the stack.
3259  // -------------------------------------------
3260  // We store values on the stack to restore them after function calls.
3261  // We cannot push values onto the stack right before the wasm call. The wasm
3262  // function expects the parameters, that didn't fit into the registers, on the
3263  // top of the stack.
3264  __ movq(MemOperand(original_fp, kParamCountOffset), param_count);
3265  __ movq(MemOperand(rbp, kReturnCountOffset), return_count);
3266  __ movq(MemOperand(rbp, kValueTypesArrayStartOffset), valuetypes_array_ptr);
3267
3268  // -------------------------------------------
3269  // Parameter handling.
3270  // -------------------------------------------
3271  Label prepare_for_wasm_call;
3272  __ Cmp(param_count, 0);
3273
3274  // IF we have 0 params: jump through parameter handling.
3275  __ j(equal, &prepare_for_wasm_call);
3276
3277  // -------------------------------------------
3278  // Create 2 sections for integer and float params.
3279  // -------------------------------------------
3280  // We will create 2 sections on the stack for the evaluated parameters:
3281  // Integer and Float section, both with parameter count size. We will place
3282  // the parameters into these sections depending on their valuetype. This way
3283  // we can easily fill the general purpose and floating point parameter
3284  // registers and place the remaining parameters onto the stack in proper order
3285  // for the Wasm function. These remaining params are the final stack
3286  // parameters for the call to WebAssembly. Example of the stack layout after
3287  // processing 2 int and 1 float parameters when param_count is 4.
3288  //   +-----------------+
3289  //   |      rbp        |
3290  //   |-----------------|-------------------------------
3291  //   |                 |   Slots we defined
3292  //   |   Saved values  |    when setting up
3293  //   |                 |     the stack
3294  //   |                 |
3295  //   +-Integer section-+--- <--- start_int_section ----
3296  //   |  1st int param  |
3297  //   |- - - - - - - - -|
3298  //   |  2nd int param  |
3299  //   |- - - - - - - - -|  <----- current_int_param_slot
3300  //   |                 |       (points to the stackslot
3301  //   |- - - - - - - - -|  where the next int param should be placed)
3302  //   |                 |
3303  //   +--Float section--+--- <--- start_float_section --
3304  //   | 1st float param |
3305  //   |- - - - - - - - -|  <----  current_float_param_slot
3306  //   |                 |       (points to the stackslot
3307  //   |- - - - - - - - -|  where the next float param should be placed)
3308  //   |                 |
3309  //   |- - - - - - - - -|
3310  //   |                 |
3311  //   +---Final stack---+------------------------------
3312  //   +-parameters for--+------------------------------
3313  //   +-the Wasm call---+------------------------------
3314  //   |      . . .      |
3315
3316  constexpr int kIntegerSectionStartOffset =
3317      kLastSpillOffset - kSystemPointerSize;
3318  // For Integer section.
3319  // Set the current_int_param_slot to point to the start of the section.
3320  Register current_int_param_slot = r10;
3321  __ leaq(current_int_param_slot, MemOperand(rsp, -kSystemPointerSize));
3322  Register params_size = param_count;
3323  param_count = no_reg;
3324  __ shlq(params_size, Immediate(kSystemPointerSizeLog2));
3325  __ subq(rsp, params_size);
3326
3327  // For Float section.
3328  // Set the current_float_param_slot to point to the start of the section.
3329  Register current_float_param_slot = r15;
3330  __ leaq(current_float_param_slot, MemOperand(rsp, -kSystemPointerSize));
3331  __ subq(rsp, params_size);
3332  params_size = no_reg;
3333  param_count = rcx;
3334  __ movq(param_count, MemOperand(original_fp, kParamCountOffset));
3335
3336  // -------------------------------------------
3337  // Set up for the param evaluation loop.
3338  // -------------------------------------------
3339  // We will loop through the params starting with the 1st param.
3340  // The order of processing the params is important. We have to evaluate them
3341  // in an increasing order.
3342  //       +-----------------+---------------
3343  //       |     param n     |
3344  //       |- - - - - - - - -|
3345  //       |    param n-1    |   Caller
3346  //       |       ...       | frame slots
3347  //       |     param 1     |
3348  //       |- - - - - - - - -|
3349  //       |    receiver     |
3350  //       +-----------------+---------------
3351  //       |  return addr    |
3352  //   FP->|- - - - - - - - -|
3353  //       |      rbp        |   Spill slots
3354  //       |- - - - - - - - -|
3355  //
3356  // [rbp + current_param] gives us the parameter we are processing.
3357  // We iterate through half-open interval <1st param, [rbp + param_limit]).
3358
3359  Register current_param = rbx;
3360  Register param_limit = rdx;
3361  constexpr int kReceiverOnStackSize = kSystemPointerSize;
3362  __ Move(current_param,
3363          kFPOnStackSize + kPCOnStackSize + kReceiverOnStackSize);
3364  __ movq(param_limit, param_count);
3365  __ shlq(param_limit, Immediate(kSystemPointerSizeLog2));
3366  __ addq(param_limit,
3367          Immediate(kFPOnStackSize + kPCOnStackSize + kReceiverOnStackSize));
3368  const int increment = kSystemPointerSize;
3369  Register param = rax;
3370  // We have to check the types of the params. The ValueType array contains
3371  // first the return then the param types.
3372  constexpr int kValueTypeSize = sizeof(wasm::ValueType);
3373  STATIC_ASSERT(kValueTypeSize == 4);
3374  const int32_t kValueTypeSizeLog2 = log2(kValueTypeSize);
3375  // Set the ValueType array pointer to point to the first parameter.
3376  Register returns_size = return_count;
3377  return_count = no_reg;
3378  __ shlq(returns_size, Immediate(kValueTypeSizeLog2));
3379  __ addq(valuetypes_array_ptr, returns_size);
3380  returns_size = no_reg;
3381  Register valuetype = r12;
3382
3383  // -------------------------------------------
3384  // Param evaluation loop.
3385  // -------------------------------------------
3386  Label loop_through_params;
3387  __ bind(&loop_through_params);
3388
3389  __ movq(param, MemOperand(original_fp, current_param, times_1, 0));
3390  __ movl(valuetype,
3391          Operand(valuetypes_array_ptr, wasm::ValueType::bit_field_offset()));
3392
3393  // -------------------------------------------
3394  // Param conversion.
3395  // -------------------------------------------
3396  // If param is a Smi we can easily convert it. Otherwise we'll call a builtin
3397  // for conversion.
3398  Label convert_param;
3399  __ cmpq(valuetype, Immediate(wasm::kWasmI32.raw_bit_field()));
3400  __ j(not_equal, &convert_param);
3401  __ JumpIfNotSmi(param, &convert_param);
3402  // Change the paramfrom Smi to int32.
3403  __ SmiUntag(param);
3404  // Zero extend.
3405  __ movl(param, param);
3406  // Place the param into the proper slot in Integer section.
3407  __ movq(MemOperand(current_int_param_slot, 0), param);
3408  __ subq(current_int_param_slot, Immediate(kSystemPointerSize));
3409
3410  // -------------------------------------------
3411  // Param conversion done.
3412  // -------------------------------------------
3413  Label param_conversion_done;
3414  __ bind(&param_conversion_done);
3415
3416  __ addq(current_param, Immediate(increment));
3417  __ addq(valuetypes_array_ptr, Immediate(kValueTypeSize));
3418
3419  __ cmpq(current_param, param_limit);
3420  __ j(not_equal, &loop_through_params);
3421
3422  // -------------------------------------------
3423  // Second loop to handle references.
3424  // -------------------------------------------
3425  // In this loop we iterate over all parameters for a second time and copy all
3426  // reference parameters at the end of the integer parameters section.
3427  Label ref_params_done;
3428  // We check if we have seen a reference in the first parameter loop.
3429  Register ref_param_count = param_count;
3430  __ movq(ref_param_count, Immediate(0));
3431  __ cmpq(MemOperand(rbp, kHasRefTypesOffset), Immediate(0));
3432  __ j(equal, &ref_params_done);
3433  // We re-calculate the beginning of the value-types array and the beginning of
3434  // the parameters ({valuetypes_array_ptr} and {current_param}).
3435  __ movq(valuetypes_array_ptr, MemOperand(rbp, kValueTypesArrayStartOffset));
3436  return_count = current_param;
3437  current_param = no_reg;
3438  __ movq(return_count, MemOperand(rbp, kReturnCountOffset));
3439  returns_size = return_count;
3440  return_count = no_reg;
3441  __ shlq(returns_size, Immediate(kValueTypeSizeLog2));
3442  __ addq(valuetypes_array_ptr, returns_size);
3443
3444  current_param = returns_size;
3445  returns_size = no_reg;
3446  __ Move(current_param,
3447          kFPOnStackSize + kPCOnStackSize + kReceiverOnStackSize);
3448
3449  Label ref_loop_through_params;
3450  Label ref_loop_end;
3451  // Start of the loop.
3452  __ bind(&ref_loop_through_params);
3453
3454  // Load the current parameter with type.
3455  __ movq(param, MemOperand(original_fp, current_param, times_1, 0));
3456  __ movl(valuetype,
3457          Operand(valuetypes_array_ptr, wasm::ValueType::bit_field_offset()));
3458  // Extract the ValueKind of the type, to check for kRef and kOptRef.
3459  __ andl(valuetype, Immediate(wasm::kWasmValueKindBitsMask));
3460  Label move_ref_to_slot;
3461  __ cmpq(valuetype, Immediate(wasm::ValueKind::kOptRef));
3462  __ j(equal, &move_ref_to_slot);
3463  __ cmpq(valuetype, Immediate(wasm::ValueKind::kRef));
3464  __ j(equal, &move_ref_to_slot);
3465  __ jmp(&ref_loop_end);
3466
3467  // Place the param into the proper slot in Integer section.
3468  __ bind(&move_ref_to_slot);
3469  __ addq(ref_param_count, Immediate(1));
3470  __ movq(MemOperand(current_int_param_slot, 0), param);
3471  __ subq(current_int_param_slot, Immediate(kSystemPointerSize));
3472
3473  // Move to the next parameter.
3474  __ bind(&ref_loop_end);
3475  __ addq(current_param, Immediate(increment));
3476  __ addq(valuetypes_array_ptr, Immediate(kValueTypeSize));
3477
3478  // Check if we finished all parameters.
3479  __ cmpq(current_param, param_limit);
3480  __ j(not_equal, &ref_loop_through_params);
3481
3482  __ bind(&ref_params_done);
3483  __ movq(valuetype, ref_param_count);
3484  ref_param_count = valuetype;
3485  valuetype = no_reg;
3486  // -------------------------------------------
3487  // Move the parameters into the proper param registers.
3488  // -------------------------------------------
3489  // The Wasm function expects that the params can be popped from the top of the
3490  // stack in an increasing order.
3491  // We can always move the values on the beginning of the sections into the GP
3492  // or FP parameter registers. If the parameter count is less than the number
3493  // of parameter registers, we may move values into the registers that are not
3494  // in the section.
3495  // ----------- S t a t e -------------
3496  //  -- r8  : start_int_section
3497  //  -- rdi : start_float_section
3498  //  -- r10 : current_int_param_slot
3499  //  -- r15 : current_float_param_slot
3500  //  -- r11 : valuetypes_array_ptr
3501  //  -- r12 : valuetype
3502  //  -- rsi : wasm_instance
3503  //  -- GpParamRegisters = rax, rdx, rcx, rbx, r9
3504  // -----------------------------------
3505
3506  Register temp_params_size = rax;
3507  __ movq(temp_params_size, MemOperand(original_fp, kParamCountOffset));
3508  __ shlq(temp_params_size, Immediate(kSystemPointerSizeLog2));
3509  // We want to use the register of the function_data = rdi.
3510  __ movq(MemOperand(rbp, kFunctionDataOffset), function_data);
3511  Register start_float_section = function_data;
3512  function_data = no_reg;
3513  __ movq(start_float_section, rbp);
3514  __ addq(start_float_section, Immediate(kIntegerSectionStartOffset));
3515  __ subq(start_float_section, temp_params_size);
3516  temp_params_size = no_reg;
3517  // Fill the FP param registers.
3518  __ Movsd(xmm1, MemOperand(start_float_section, 0));
3519  __ Movsd(xmm2, MemOperand(start_float_section, -kSystemPointerSize));
3520  __ Movsd(xmm3, MemOperand(start_float_section, -2 * kSystemPointerSize));
3521  __ Movsd(xmm4, MemOperand(start_float_section, -3 * kSystemPointerSize));
3522  __ Movsd(xmm5, MemOperand(start_float_section, -4 * kSystemPointerSize));
3523  __ Movsd(xmm6, MemOperand(start_float_section, -5 * kSystemPointerSize));
3524  // We want the start to point to the last properly placed param.
3525  __ subq(start_float_section, Immediate(5 * kSystemPointerSize));
3526
3527  Register start_int_section = r8;
3528  __ movq(start_int_section, rbp);
3529  __ addq(start_int_section, Immediate(kIntegerSectionStartOffset));
3530  // Fill the GP param registers.
3531  __ movq(rax, MemOperand(start_int_section, 0));
3532  __ movq(rdx, MemOperand(start_int_section, -kSystemPointerSize));
3533  __ movq(rcx, MemOperand(start_int_section, -2 * kSystemPointerSize));
3534  __ movq(rbx, MemOperand(start_int_section, -3 * kSystemPointerSize));
3535  __ movq(r9, MemOperand(start_int_section, -4 * kSystemPointerSize));
3536  // We want the start to point to the last properly placed param.
3537  __ subq(start_int_section, Immediate(4 * kSystemPointerSize));
3538
3539  // -------------------------------------------
3540  // Place the final stack parameters to the proper place.
3541  // -------------------------------------------
3542  // We want the current_param_slot (insertion) pointers to point at the last
3543  // param of the section instead of the next free slot.
3544  __ addq(current_int_param_slot, Immediate(kSystemPointerSize));
3545  __ addq(current_float_param_slot, Immediate(kSystemPointerSize));
3546
3547  // -------------------------------------------
3548  // Final stack parameters loop.
3549  // -------------------------------------------
3550  // The parameters that didn't fit into the registers should be placed on the
3551  // top of the stack contiguously. The interval of parameters between the
3552  // start_section and the current_param_slot pointers define the remaining
3553  // parameters of the section.
3554  // We can iterate through the valuetypes array to decide from which section we
3555  // need to push the parameter onto the top of the stack. By iterating in a
3556  // reversed order we can easily pick the last parameter of the proper section.
3557  // The parameter of the section is pushed on the top of the stack only if the
3558  // interval of remaining params is not empty. This way we ensure that only
3559  // params that didn't fit into param registers are pushed again.
3560
3561  Label loop_through_valuetypes;
3562  Label loop_place_ref_params;
3563  __ bind(&loop_place_ref_params);
3564  __ testq(ref_param_count, ref_param_count);
3565  __ j(zero, &loop_through_valuetypes);
3566
3567  __ cmpq(start_int_section, current_int_param_slot);
3568  // if no int or ref param remains, directly iterate valuetypes
3569  __ j(less_equal, &loop_through_valuetypes);
3570
3571  __ pushq(MemOperand(current_int_param_slot, 0));
3572  __ addq(current_int_param_slot, Immediate(kSystemPointerSize));
3573  __ subq(ref_param_count, Immediate(1));
3574  __ jmp(&loop_place_ref_params);
3575
3576  valuetype = ref_param_count;
3577  ref_param_count = no_reg;
3578  __ bind(&loop_through_valuetypes);
3579
3580  // We iterated through the valuetypes array, we are one field over the end in
3581  // the beginning. Also, we have to decrement it in each iteration.
3582  __ subq(valuetypes_array_ptr, Immediate(kValueTypeSize));
3583
3584  // Check if there are still remaining integer params.
3585  Label continue_loop;
3586  __ cmpq(start_int_section, current_int_param_slot);
3587  // If there are remaining integer params.
3588  __ j(greater, &continue_loop);
3589
3590  // Check if there are still remaining float params.
3591  __ cmpq(start_float_section, current_float_param_slot);
3592  // If there aren't any params remaining.
3593  Label params_done;
3594  __ j(less_equal, &params_done);
3595
3596  __ bind(&continue_loop);
3597  __ movl(valuetype,
3598          Operand(valuetypes_array_ptr, wasm::ValueType::bit_field_offset()));
3599  Label place_integer_param;
3600  Label place_float_param;
3601  __ cmpq(valuetype, Immediate(wasm::kWasmI32.raw_bit_field()));
3602  __ j(equal, &place_integer_param);
3603
3604  __ cmpq(valuetype, Immediate(wasm::kWasmI64.raw_bit_field()));
3605  __ j(equal, &place_integer_param);
3606
3607  __ cmpq(valuetype, Immediate(wasm::kWasmF32.raw_bit_field()));
3608  __ j(equal, &place_float_param);
3609
3610  __ cmpq(valuetype, Immediate(wasm::kWasmF64.raw_bit_field()));
3611  __ j(equal, &place_float_param);
3612
3613  // ref params have already been pushed, so go through directly
3614  __ jmp(&loop_through_valuetypes);
3615
3616  // All other types are reference types. We can just fall through to place them
3617  // in the integer section.
3618
3619  __ bind(&place_integer_param);
3620  __ cmpq(start_int_section, current_int_param_slot);
3621  // If there aren't any integer params remaining, just floats, then go to the
3622  // next valuetype.
3623  __ j(less_equal, &loop_through_valuetypes);
3624
3625  // Copy the param from the integer section to the actual parameter area.
3626  __ pushq(MemOperand(current_int_param_slot, 0));
3627  __ addq(current_int_param_slot, Immediate(kSystemPointerSize));
3628  __ jmp(&loop_through_valuetypes);
3629
3630  __ bind(&place_float_param);
3631  __ cmpq(start_float_section, current_float_param_slot);
3632  // If there aren't any float params remaining, just integers, then go to the
3633  // next valuetype.
3634  __ j(less_equal, &loop_through_valuetypes);
3635
3636  // Copy the param from the float section to the actual parameter area.
3637  __ pushq(MemOperand(current_float_param_slot, 0));
3638  __ addq(current_float_param_slot, Immediate(kSystemPointerSize));
3639  __ jmp(&loop_through_valuetypes);
3640
3641  __ bind(&params_done);
3642  // Restore function_data after we are done with parameter placement.
3643  function_data = rdi;
3644  __ movq(function_data, MemOperand(rbp, kFunctionDataOffset));
3645
3646  __ bind(&prepare_for_wasm_call);
3647  // -------------------------------------------
3648  // Prepare for the Wasm call.
3649  // -------------------------------------------
3650  // Set thread_in_wasm_flag.
3651  Register thread_in_wasm_flag_addr = r12;
3652  __ movq(
3653      thread_in_wasm_flag_addr,
3654      MemOperand(kRootRegister, Isolate::thread_in_wasm_flag_address_offset()));
3655  __ movl(MemOperand(thread_in_wasm_flag_addr, 0), Immediate(1));
3656  thread_in_wasm_flag_addr = no_reg;
3657
3658  Register function_entry = function_data;
3659  Register scratch = r12;
3660  __ LoadAnyTaggedField(
3661      function_entry,
3662      FieldOperand(function_data, WasmExportedFunctionData::kInternalOffset));
3663  __ LoadExternalPointerField(
3664      function_entry,
3665      FieldOperand(function_entry, WasmInternalFunction::kForeignAddressOffset),
3666      kForeignForeignAddressTag, scratch);
3667  function_data = no_reg;
3668  scratch = no_reg;
3669
3670  // We set the indicating value for the GC to the proper one for Wasm call.
3671  constexpr int kWasmCallGCScanSlotCount = 0;
3672  __ Move(MemOperand(rbp, kGCScanSlotCountOffset), kWasmCallGCScanSlotCount);
3673
3674  // -------------------------------------------
3675  // Call the Wasm function.
3676  // -------------------------------------------
3677  __ call(function_entry);
3678  // Note: we might be returning to a different frame if the stack was suspended
3679  // and resumed during the call. The new frame is set up by WasmResume and has
3680  // a compatible layout.
3681  function_entry = no_reg;
3682
3683  // -------------------------------------------
3684  // Resetting after the Wasm call.
3685  // -------------------------------------------
3686  // Restore rsp to free the reserved stack slots for the sections.
3687  __ leaq(rsp, MemOperand(rbp, kLastSpillOffset));
3688
3689  // Unset thread_in_wasm_flag.
3690  thread_in_wasm_flag_addr = r8;
3691  __ movq(
3692      thread_in_wasm_flag_addr,
3693      MemOperand(kRootRegister, Isolate::thread_in_wasm_flag_address_offset()));
3694  __ movl(MemOperand(thread_in_wasm_flag_addr, 0), Immediate(0));
3695  thread_in_wasm_flag_addr = no_reg;
3696
3697  // -------------------------------------------
3698  // Return handling.
3699  // -------------------------------------------
3700  return_count = r8;
3701  __ movq(return_count, MemOperand(rbp, kReturnCountOffset));
3702  Register return_reg = rax;
3703
3704  // If we have 1 return value, then jump to conversion.
3705  __ cmpl(return_count, Immediate(1));
3706  Label convert_return;
3707  __ j(equal, &convert_return);
3708
3709  // Otherwise load undefined.
3710  __ LoadRoot(return_reg, RootIndex::kUndefinedValue);
3711
3712  Label return_done;
3713  __ bind(&return_done);
3714  if (stack_switch) {
3715    ReloadParentContinuation(masm, wasm_instance, return_reg, rbx, rcx);
3716    RestoreParentSuspender(masm);
3717  }
3718  __ bind(&suspend);
3719  // No need to process the return value if the stack is suspended, there is a
3720  // single 'externref' value (the promise) which doesn't require conversion.
3721
3722  __ movq(param_count, MemOperand(rbp, kParamCountOffset));
3723
3724  // Calculate the number of parameters we have to pop off the stack. This
3725  // number is max(in_param_count, param_count).
3726  in_param_count = rdx;
3727  __ movq(in_param_count, MemOperand(rbp, kInParamCountOffset));
3728  __ cmpq(param_count, in_param_count);
3729  __ cmovq(less, param_count, in_param_count);
3730
3731  // -------------------------------------------
3732  // Deconstrunct the stack frame.
3733  // -------------------------------------------
3734  __ LeaveFrame(stack_switch ? StackFrame::STACK_SWITCH
3735                             : StackFrame::JS_TO_WASM);
3736
3737  // We have to remove the caller frame slots:
3738  //  - JS arguments
3739  //  - the receiver
3740  // and transfer the control to the return address (the return address is
3741  // expected to be on the top of the stack).
3742  // We cannot use just the ret instruction for this, because we cannot pass the
3743  // number of slots to remove in a Register as an argument.
3744  __ DropArguments(param_count, rbx, TurboAssembler::kCountIsInteger,
3745                   TurboAssembler::kCountExcludesReceiver);
3746  __ ret(0);
3747
3748  // --------------------------------------------------------------------------
3749  //                          Deferred code.
3750  // --------------------------------------------------------------------------
3751
3752  // -------------------------------------------
3753  // Param conversion builtins.
3754  // -------------------------------------------
3755  __ bind(&convert_param);
3756  // Restore function_data register (which was clobbered by the code above,
3757  // but was valid when jumping here earlier).
3758  function_data = rdi;
3759  // The order of pushes is important. We want the heap objects, that should be
3760  // scanned by GC, to be on the top of the stack.
3761  // We have to set the indicating value for the GC to the number of values on
3762  // the top of the stack that have to be scanned before calling the builtin
3763  // function.
3764  // The builtin expects the parameter to be in register param = rax.
3765
3766  constexpr int kBuiltinCallGCScanSlotCount = 2;
3767  PrepareForBuiltinCall(masm, MemOperand(rbp, kGCScanSlotCountOffset),
3768                        kBuiltinCallGCScanSlotCount, current_param, param_limit,
3769                        current_int_param_slot, current_float_param_slot,
3770                        valuetypes_array_ptr, wasm_instance, function_data);
3771
3772  Label param_kWasmI32_not_smi;
3773  Label param_kWasmI64;
3774  Label param_kWasmF32;
3775  Label param_kWasmF64;
3776
3777  __ cmpq(valuetype, Immediate(wasm::kWasmI32.raw_bit_field()));
3778  __ j(equal, &param_kWasmI32_not_smi);
3779
3780  __ cmpq(valuetype, Immediate(wasm::kWasmI64.raw_bit_field()));
3781  __ j(equal, &param_kWasmI64);
3782
3783  __ cmpq(valuetype, Immediate(wasm::kWasmF32.raw_bit_field()));
3784  __ j(equal, &param_kWasmF32);
3785
3786  __ cmpq(valuetype, Immediate(wasm::kWasmF64.raw_bit_field()));
3787  __ j(equal, &param_kWasmF64);
3788
3789  // The parameter is a reference. We do not convert the parameter immediately.
3790  // Instead we will later loop over all parameters again to handle reference
3791  // parameters. The reason is that later value type parameters may trigger a
3792  // GC, and we cannot keep reference parameters alive then. Instead we leave
3793  // reference parameters at their initial place on the stack and only copy them
3794  // once no GC can happen anymore.
3795  // As an optimization we set a flag here that indicates that we have seen a
3796  // reference so far. If there was no reference parameter, we would not iterate
3797  // over the parameters for a second time.
3798  __ movq(MemOperand(rbp, kHasRefTypesOffset), Immediate(1));
3799  RestoreAfterBuiltinCall(masm, function_data, wasm_instance,
3800                          valuetypes_array_ptr, current_float_param_slot,
3801                          current_int_param_slot, param_limit, current_param);
3802  __ jmp(&param_conversion_done);
3803
3804  __ int3();
3805
3806  __ bind(&param_kWasmI32_not_smi);
3807  __ Call(BUILTIN_CODE(masm->isolate(), WasmTaggedNonSmiToInt32),
3808          RelocInfo::CODE_TARGET);
3809  // Param is the result of the builtin.
3810  __ AssertZeroExtended(param);
3811  RestoreAfterBuiltinCall(masm, function_data, wasm_instance,
3812                          valuetypes_array_ptr, current_float_param_slot,
3813                          current_int_param_slot, param_limit, current_param);
3814  __ movq(MemOperand(current_int_param_slot, 0), param);
3815  __ subq(current_int_param_slot, Immediate(kSystemPointerSize));
3816  __ jmp(&param_conversion_done);
3817
3818  __ bind(&param_kWasmI64);
3819  __ Call(BUILTIN_CODE(masm->isolate(), BigIntToI64), RelocInfo::CODE_TARGET);
3820  RestoreAfterBuiltinCall(masm, function_data, wasm_instance,
3821                          valuetypes_array_ptr, current_float_param_slot,
3822                          current_int_param_slot, param_limit, current_param);
3823  __ movq(MemOperand(current_int_param_slot, 0), param);
3824  __ subq(current_int_param_slot, Immediate(kSystemPointerSize));
3825  __ jmp(&param_conversion_done);
3826
3827  __ bind(&param_kWasmF32);
3828  __ Call(BUILTIN_CODE(masm->isolate(), WasmTaggedToFloat64),
3829          RelocInfo::CODE_TARGET);
3830  RestoreAfterBuiltinCall(masm, function_data, wasm_instance,
3831                          valuetypes_array_ptr, current_float_param_slot,
3832                          current_int_param_slot, param_limit, current_param);
3833  // Clear higher bits.
3834  __ Xorpd(xmm1, xmm1);
3835  // Truncate float64 to float32.
3836  __ Cvtsd2ss(xmm1, xmm0);
3837  __ Movsd(MemOperand(current_float_param_slot, 0), xmm1);
3838  __ subq(current_float_param_slot, Immediate(kSystemPointerSize));
3839  __ jmp(&param_conversion_done);
3840
3841  __ bind(&param_kWasmF64);
3842  __ Call(BUILTIN_CODE(masm->isolate(), WasmTaggedToFloat64),
3843          RelocInfo::CODE_TARGET);
3844  RestoreAfterBuiltinCall(masm, function_data, wasm_instance,
3845                          valuetypes_array_ptr, current_float_param_slot,
3846                          current_int_param_slot, param_limit, current_param);
3847  __ Movsd(MemOperand(current_float_param_slot, 0), xmm0);
3848  __ subq(current_float_param_slot, Immediate(kSystemPointerSize));
3849  __ jmp(&param_conversion_done);
3850
3851  // -------------------------------------------
3852  // Return conversions.
3853  // -------------------------------------------
3854  __ bind(&convert_return);
3855  // We have to make sure that the kGCScanSlotCount is set correctly when we
3856  // call the builtins for conversion. For these builtins it's the same as for
3857  // the Wasm call, that is, kGCScanSlotCount = 0, so we don't have to reset it.
3858  // We don't need the JS context for these builtin calls.
3859
3860  __ movq(valuetypes_array_ptr, MemOperand(rbp, kValueTypesArrayStartOffset));
3861  // The first valuetype of the array is the return's valuetype.
3862  __ movl(valuetype,
3863          Operand(valuetypes_array_ptr, wasm::ValueType::bit_field_offset()));
3864
3865  Label return_kWasmI32;
3866  Label return_kWasmI64;
3867  Label return_kWasmF32;
3868  Label return_kWasmF64;
3869  Label return_kWasmFuncRef;
3870
3871  __ cmpq(valuetype, Immediate(wasm::kWasmI32.raw_bit_field()));
3872  __ j(equal, &return_kWasmI32);
3873
3874  __ cmpq(valuetype, Immediate(wasm::kWasmI64.raw_bit_field()));
3875  __ j(equal, &return_kWasmI64);
3876
3877  __ cmpq(valuetype, Immediate(wasm::kWasmF32.raw_bit_field()));
3878  __ j(equal, &return_kWasmF32);
3879
3880  __ cmpq(valuetype, Immediate(wasm::kWasmF64.raw_bit_field()));
3881  __ j(equal, &return_kWasmF64);
3882
3883  __ cmpq(valuetype, Immediate(wasm::kWasmFuncRef.raw_bit_field()));
3884  __ j(equal, &return_kWasmFuncRef);
3885
3886  // All types that are not SIMD are reference types.
3887  __ cmpq(valuetype, Immediate(wasm::kWasmS128.raw_bit_field()));
3888  // References can be passed to JavaScript as is.
3889  __ j(not_equal, &return_done);
3890
3891  __ int3();
3892
3893  __ bind(&return_kWasmI32);
3894  Label to_heapnumber;
3895  // If pointer compression is disabled, we can convert the return to a smi.
3896  if (SmiValuesAre32Bits()) {
3897    __ SmiTag(return_reg);
3898  } else {
3899    Register temp = rbx;
3900    __ movq(temp, return_reg);
3901    // Double the return value to test if it can be a Smi.
3902    __ addl(temp, return_reg);
3903    temp = no_reg;
3904    // If there was overflow, convert the return value to a HeapNumber.
3905    __ j(overflow, &to_heapnumber);
3906    // If there was no overflow, we can convert to Smi.
3907    __ SmiTag(return_reg);
3908  }
3909  __ jmp(&return_done);
3910
3911  // Handle the conversion of the I32 return value to HeapNumber when it cannot
3912  // be a smi.
3913  __ bind(&to_heapnumber);
3914  __ Call(BUILTIN_CODE(masm->isolate(), WasmInt32ToHeapNumber),
3915          RelocInfo::CODE_TARGET);
3916  __ jmp(&return_done);
3917
3918  __ bind(&return_kWasmI64);
3919  __ Call(BUILTIN_CODE(masm->isolate(), I64ToBigInt), RelocInfo::CODE_TARGET);
3920  __ jmp(&return_done);
3921
3922  __ bind(&return_kWasmF32);
3923  // The builtin expects the value to be in xmm0.
3924  __ Movss(xmm0, xmm1);
3925  __ Call(BUILTIN_CODE(masm->isolate(), WasmFloat32ToNumber),
3926          RelocInfo::CODE_TARGET);
3927  __ jmp(&return_done);
3928
3929  __ bind(&return_kWasmF64);
3930  // The builtin expects the value to be in xmm0.
3931  __ Movsd(xmm0, xmm1);
3932  __ Call(BUILTIN_CODE(masm->isolate(), WasmFloat64ToNumber),
3933          RelocInfo::CODE_TARGET);
3934  __ jmp(&return_done);
3935
3936  __ bind(&return_kWasmFuncRef);
3937  __ Call(BUILTIN_CODE(masm->isolate(), WasmFuncRefToJS),
3938          RelocInfo::CODE_TARGET);
3939  __ jmp(&return_done);
3940
3941  if (!stack_switch) {
3942    // -------------------------------------------
3943    // Kick off compilation.
3944    // -------------------------------------------
3945    __ bind(&compile_wrapper);
3946    // Enable GC.
3947    MemOperand GCScanSlotPlace = MemOperand(rbp, kGCScanSlotCountOffset);
3948    __ Move(GCScanSlotPlace, 4);
3949    // Save registers to the stack.
3950    __ pushq(wasm_instance);
3951    __ pushq(function_data);
3952    // Push the arguments for the runtime call.
3953    __ Push(wasm_instance);  // first argument
3954    __ Push(function_data);  // second argument
3955                             // Set up context.
3956    __ Move(kContextRegister, Smi::zero());
3957    // Call the runtime function that kicks off compilation.
3958    __ CallRuntime(Runtime::kWasmCompileWrapper, 2);
3959    // Pop the result.
3960    __ movq(r9, kReturnRegister0);
3961    // Restore registers from the stack.
3962    __ popq(function_data);
3963    __ popq(wasm_instance);
3964    __ jmp(&compile_wrapper_done);
3965  }
3966}
3967}  // namespace
3968
3969void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) {
3970  GenericJSToWasmWrapperHelper(masm, false);
3971}
3972
3973void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) {
3974  GenericJSToWasmWrapperHelper(masm, true);
3975}
3976
3977void Builtins::Generate_WasmSuspend(MacroAssembler* masm) {
3978  // Set up the stackframe.
3979  __ EnterFrame(StackFrame::STACK_SWITCH);
3980
3981  Register promise = rax;
3982  Register suspender = rbx;
3983
3984  __ subq(rsp, Immediate(-(BuiltinWasmWrapperConstants::kGCScanSlotCountOffset -
3985                           TypedFrameConstants::kFixedFrameSizeFromFp)));
3986
3987  // TODO(thibaudm): Throw if any of the following holds:
3988  // - caller is null
3989  // - ActiveSuspender is undefined
3990  // - 'suspender' is not the active suspender
3991
3992  // -------------------------------------------
3993  // Save current state in active jump buffer.
3994  // -------------------------------------------
3995  Label resume;
3996  Register continuation = rcx;
3997  __ LoadRoot(continuation, RootIndex::kActiveContinuation);
3998  Register jmpbuf = rdx;
3999  __ LoadAnyTaggedField(
4000      jmpbuf,
4001      FieldOperand(continuation, WasmContinuationObject::kJmpbufOffset));
4002  __ LoadExternalPointerField(
4003      jmpbuf, FieldOperand(jmpbuf, Foreign::kForeignAddressOffset),
4004      kForeignForeignAddressTag, r8);
4005  FillJumpBuffer(masm, jmpbuf, &resume);
4006  __ StoreTaggedSignedField(
4007      FieldOperand(suspender, WasmSuspenderObject::kStateOffset),
4008      Smi::FromInt(WasmSuspenderObject::Suspended));
4009  jmpbuf = no_reg;
4010  // live: [rax, rbx, rcx]
4011
4012#ifdef DEBUG
4013  // -------------------------------------------
4014  // Check that the suspender's continuation is the active continuation.
4015  // -------------------------------------------
4016  // TODO(thibaudm): Once we add core stack-switching instructions, this check
4017  // will not hold anymore: it's possible that the active continuation changed
4018  // (due to an internal switch), so we have to update the suspender.
4019  Register suspender_continuation = rdx;
4020  __ LoadAnyTaggedField(
4021      suspender_continuation,
4022      FieldOperand(suspender, WasmSuspenderObject::kContinuationOffset));
4023  __ cmpq(suspender_continuation, continuation);
4024  Label ok;
4025  __ j(equal, &ok);
4026  __ Trap();
4027  __ bind(&ok);
4028#endif
4029
4030  // -------------------------------------------
4031  // Update roots.
4032  // -------------------------------------------
4033  Register caller = rcx;
4034  __ LoadAnyTaggedField(
4035      caller,
4036      FieldOperand(suspender, WasmSuspenderObject::kContinuationOffset));
4037  __ LoadAnyTaggedField(
4038      caller, FieldOperand(caller, WasmContinuationObject::kParentOffset));
4039  __ movq(masm->RootAsOperand(RootIndex::kActiveContinuation), caller);
4040  Register parent = rdx;
4041  __ LoadAnyTaggedField(
4042      parent, FieldOperand(suspender, WasmSuspenderObject::kParentOffset));
4043  __ movq(masm->RootAsOperand(RootIndex::kActiveSuspender), parent);
4044  parent = no_reg;
4045  // live: [rax, rcx]
4046
4047  // -------------------------------------------
4048  // Load jump buffer.
4049  // -------------------------------------------
4050  MemOperand GCScanSlotPlace =
4051      MemOperand(rbp, BuiltinWasmWrapperConstants::kGCScanSlotCountOffset);
4052  __ Move(GCScanSlotPlace, 2);
4053  __ Push(promise);
4054  __ Push(caller);
4055  __ Move(kContextRegister, Smi::zero());
4056  __ CallRuntime(Runtime::kWasmSyncStackLimit);
4057  __ Pop(caller);
4058  __ Pop(promise);
4059  jmpbuf = caller;
4060  __ LoadAnyTaggedField(
4061      jmpbuf, FieldOperand(caller, WasmContinuationObject::kJmpbufOffset));
4062  caller = no_reg;
4063  __ LoadExternalPointerField(
4064      jmpbuf, FieldOperand(jmpbuf, Foreign::kForeignAddressOffset),
4065      kForeignForeignAddressTag, r8);
4066  __ movq(kReturnRegister0, promise);
4067  __ Move(GCScanSlotPlace, 0);
4068  LoadJumpBuffer(masm, jmpbuf, true);
4069  __ Trap();
4070  __ bind(&resume);
4071  __ LeaveFrame(StackFrame::STACK_SWITCH);
4072  __ ret(0);
4073}
4074
4075// Resume the suspender stored in the closure.
4076void Builtins::Generate_WasmResume(MacroAssembler* masm) {
4077  __ EnterFrame(StackFrame::STACK_SWITCH);
4078
4079  Register param_count = rax;
4080  __ decq(param_count);                    // Exclude receiver.
4081  Register closure = kJSFunctionRegister;  // rdi
4082
4083  // These slots are not used in this builtin. But when we return from the
4084  // resumed continuation, we return to the GenericJSToWasmWrapper code, which
4085  // expects these slots to be set.
4086  constexpr int kInParamCountOffset =
4087      BuiltinWasmWrapperConstants::kInParamCountOffset;
4088  constexpr int kParamCountOffset =
4089      BuiltinWasmWrapperConstants::kParamCountOffset;
4090  __ subq(rsp, Immediate(3 * kSystemPointerSize));
4091  __ movq(MemOperand(rbp, kParamCountOffset), param_count);
4092  __ movq(MemOperand(rbp, kInParamCountOffset), param_count);
4093
4094  param_count = no_reg;
4095
4096  // -------------------------------------------
4097  // Load suspender from closure.
4098  // -------------------------------------------
4099  Register sfi = closure;
4100  __ LoadAnyTaggedField(
4101      sfi,
4102      MemOperand(
4103          closure,
4104          wasm::ObjectAccess::SharedFunctionInfoOffsetInTaggedJSFunction()));
4105  Register function_data = sfi;
4106  __ LoadAnyTaggedField(
4107      function_data,
4108      FieldOperand(sfi, SharedFunctionInfo::kFunctionDataOffset));
4109  Register suspender = rax;
4110  __ LoadAnyTaggedField(
4111      suspender,
4112      FieldOperand(function_data, WasmOnFulfilledData::kSuspenderOffset));
4113  // Check the suspender state.
4114  Label suspender_is_suspended;
4115  Register state = rdx;
4116  __ LoadTaggedSignedField(
4117      state, FieldOperand(suspender, WasmSuspenderObject::kStateOffset));
4118  __ SmiCompare(state, Smi::FromInt(WasmSuspenderObject::Suspended));
4119  __ j(equal, &suspender_is_suspended);
4120  __ Trap();  // TODO(thibaudm): Throw a wasm trap.
4121  closure = no_reg;
4122  sfi = no_reg;
4123
4124  __ bind(&suspender_is_suspended);
4125  // -------------------------------------------
4126  // Save current state.
4127  // -------------------------------------------
4128  Label suspend;
4129  Register active_continuation = r9;
4130  __ LoadRoot(active_continuation, RootIndex::kActiveContinuation);
4131  Register current_jmpbuf = rdi;
4132  __ LoadAnyTaggedField(
4133      current_jmpbuf,
4134      FieldOperand(active_continuation, WasmContinuationObject::kJmpbufOffset));
4135  __ LoadExternalPointerField(
4136      current_jmpbuf,
4137      FieldOperand(current_jmpbuf, Foreign::kForeignAddressOffset),
4138      kForeignForeignAddressTag, rdx);
4139  FillJumpBuffer(masm, current_jmpbuf, &suspend);
4140  current_jmpbuf = no_reg;
4141
4142  // -------------------------------------------
4143  // Set suspender's parent to active continuation.
4144  // -------------------------------------------
4145  __ StoreTaggedSignedField(
4146      FieldOperand(suspender, WasmSuspenderObject::kStateOffset),
4147      Smi::FromInt(WasmSuspenderObject::Active));
4148  Register target_continuation = rdi;
4149  __ LoadAnyTaggedField(
4150      target_continuation,
4151      FieldOperand(suspender, WasmSuspenderObject::kContinuationOffset));
4152  Register slot_address = WriteBarrierDescriptor::SlotAddressRegister();
4153  __ StoreTaggedField(
4154      FieldOperand(target_continuation, WasmContinuationObject::kParentOffset),
4155      active_continuation);
4156  __ RecordWriteField(
4157      target_continuation, WasmContinuationObject::kParentOffset,
4158      active_continuation, slot_address, SaveFPRegsMode::kIgnore);
4159  active_continuation = no_reg;
4160
4161  // -------------------------------------------
4162  // Update roots.
4163  // -------------------------------------------
4164  __ movq(masm->RootAsOperand(RootIndex::kActiveContinuation),
4165          target_continuation);
4166  __ movq(masm->RootAsOperand(RootIndex::kActiveSuspender), suspender);
4167  suspender = no_reg;
4168
4169  MemOperand GCScanSlotPlace =
4170      MemOperand(rbp, BuiltinWasmWrapperConstants::kGCScanSlotCountOffset);
4171  __ Move(GCScanSlotPlace, 1);
4172  __ Push(target_continuation);
4173  __ Move(kContextRegister, Smi::zero());
4174  __ CallRuntime(Runtime::kWasmSyncStackLimit);
4175  __ Pop(target_continuation);
4176
4177  // -------------------------------------------
4178  // Load state from target jmpbuf (longjmp).
4179  // -------------------------------------------
4180  Register target_jmpbuf = target_continuation;
4181  __ LoadAnyTaggedField(
4182      target_jmpbuf,
4183      FieldOperand(target_continuation, WasmContinuationObject::kJmpbufOffset));
4184  __ LoadExternalPointerField(
4185      target_jmpbuf,
4186      FieldOperand(target_jmpbuf, Foreign::kForeignAddressOffset),
4187      kForeignForeignAddressTag, rax);
4188  // Move resolved value to return register.
4189  __ movq(kReturnRegister0, Operand(rbp, 3 * kSystemPointerSize));
4190  __ Move(GCScanSlotPlace, 0);
4191  LoadJumpBuffer(masm, target_jmpbuf, true);
4192  __ Trap();
4193  __ bind(&suspend);
4194  __ LeaveFrame(StackFrame::STACK_SWITCH);
4195  __ ret(3);
4196}
4197
4198void Builtins::Generate_WasmOnStackReplace(MacroAssembler* masm) {
4199  MemOperand OSRTargetSlot(rbp, -wasm::kOSRTargetOffset);
4200  __ movq(kScratchRegister, OSRTargetSlot);
4201  __ Move(OSRTargetSlot, 0);
4202  __ jmp(kScratchRegister);
4203}
4204
4205#endif  // V8_ENABLE_WEBASSEMBLY
4206
4207void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
4208                               SaveFPRegsMode save_doubles, ArgvMode argv_mode,
4209                               bool builtin_exit_frame) {
4210  // rax: number of arguments including receiver
4211  // rbx: pointer to C function  (C callee-saved)
4212  // rbp: frame pointer of calling JS frame (restored after C call)
4213  // rsp: stack pointer  (restored after C call)
4214  // rsi: current context (restored)
4215  //
4216  // If argv_mode == ArgvMode::kRegister:
4217  // r15: pointer to the first argument
4218
4219#ifdef V8_TARGET_OS_WIN
4220  // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9. It requires the
4221  // stack to be aligned to 16 bytes. It only allows a single-word to be
4222  // returned in register rax. Larger return sizes must be written to an address
4223  // passed as a hidden first argument.
4224  const Register kCCallArg0 = rcx;
4225  const Register kCCallArg1 = rdx;
4226  const Register kCCallArg2 = r8;
4227  const Register kCCallArg3 = r9;
4228  const int kArgExtraStackSpace = 2;
4229  const int kMaxRegisterResultSize = 1;
4230#else
4231  // GCC / Clang passes arguments in rdi, rsi, rdx, rcx, r8, r9. Simple results
4232  // are returned in rax, and a struct of two pointers are returned in rax+rdx.
4233  // Larger return sizes must be written to an address passed as a hidden first
4234  // argument.
4235  const Register kCCallArg0 = rdi;
4236  const Register kCCallArg1 = rsi;
4237  const Register kCCallArg2 = rdx;
4238  const Register kCCallArg3 = rcx;
4239  const int kArgExtraStackSpace = 0;
4240  const int kMaxRegisterResultSize = 2;
4241#endif  // V8_TARGET_OS_WIN
4242
4243  // Enter the exit frame that transitions from JavaScript to C++.
4244  int arg_stack_space =
4245      kArgExtraStackSpace +
4246      (result_size <= kMaxRegisterResultSize ? 0 : result_size);
4247  if (argv_mode == ArgvMode::kRegister) {
4248    DCHECK(save_doubles == SaveFPRegsMode::kIgnore);
4249    DCHECK(!builtin_exit_frame);
4250    __ EnterApiExitFrame(arg_stack_space);
4251    // Move argc into r12 (argv is already in r15).
4252    __ movq(r12, rax);
4253  } else {
4254    __ EnterExitFrame(
4255        arg_stack_space, save_doubles == SaveFPRegsMode::kSave,
4256        builtin_exit_frame ? StackFrame::BUILTIN_EXIT : StackFrame::EXIT);
4257  }
4258
4259  // rbx: pointer to builtin function  (C callee-saved).
4260  // rbp: frame pointer of exit frame  (restored after C call).
4261  // rsp: stack pointer (restored after C call).
4262  // r12: number of arguments including receiver (C callee-saved).
4263  // r15: argv pointer (C callee-saved).
4264
4265  // Check stack alignment.
4266  if (FLAG_debug_code) {
4267    __ CheckStackAlignment();
4268  }
4269
4270  // Call C function. The arguments object will be created by stubs declared by
4271  // DECLARE_RUNTIME_FUNCTION().
4272  if (result_size <= kMaxRegisterResultSize) {
4273    // Pass a pointer to the Arguments object as the first argument.
4274    // Return result in single register (rax), or a register pair (rax, rdx).
4275    __ movq(kCCallArg0, r12);  // argc.
4276    __ movq(kCCallArg1, r15);  // argv.
4277    __ Move(kCCallArg2, ExternalReference::isolate_address(masm->isolate()));
4278  } else {
4279    DCHECK_LE(result_size, 2);
4280    // Pass a pointer to the result location as the first argument.
4281    __ leaq(kCCallArg0, StackSpaceOperand(kArgExtraStackSpace));
4282    // Pass a pointer to the Arguments object as the second argument.
4283    __ movq(kCCallArg1, r12);  // argc.
4284    __ movq(kCCallArg2, r15);  // argv.
4285    __ Move(kCCallArg3, ExternalReference::isolate_address(masm->isolate()));
4286  }
4287  __ call(rbx);
4288
4289  if (result_size > kMaxRegisterResultSize) {
4290    // Read result values stored on stack. Result is stored
4291    // above the the two Arguments object slots on Win64.
4292    DCHECK_LE(result_size, 2);
4293    __ movq(kReturnRegister0, StackSpaceOperand(kArgExtraStackSpace + 0));
4294    __ movq(kReturnRegister1, StackSpaceOperand(kArgExtraStackSpace + 1));
4295  }
4296  // Result is in rax or rdx:rax - do not destroy these registers!
4297
4298  // Check result for exception sentinel.
4299  Label exception_returned;
4300  __ CompareRoot(rax, RootIndex::kException);
4301  __ j(equal, &exception_returned);
4302
4303  // Check that there is no pending exception, otherwise we
4304  // should have returned the exception sentinel.
4305  if (FLAG_debug_code) {
4306    Label okay;
4307    __ LoadRoot(kScratchRegister, RootIndex::kTheHoleValue);
4308    ExternalReference pending_exception_address = ExternalReference::Create(
4309        IsolateAddressId::kPendingExceptionAddress, masm->isolate());
4310    Operand pending_exception_operand =
4311        masm->ExternalReferenceAsOperand(pending_exception_address);
4312    __ cmp_tagged(kScratchRegister, pending_exception_operand);
4313    __ j(equal, &okay, Label::kNear);
4314    __ int3();
4315    __ bind(&okay);
4316  }
4317
4318  // Exit the JavaScript to C++ exit frame.
4319  __ LeaveExitFrame(save_doubles == SaveFPRegsMode::kSave,
4320                    argv_mode == ArgvMode::kStack);
4321  __ ret(0);
4322
4323  // Handling of exception.
4324  __ bind(&exception_returned);
4325
4326  ExternalReference pending_handler_context_address = ExternalReference::Create(
4327      IsolateAddressId::kPendingHandlerContextAddress, masm->isolate());
4328  ExternalReference pending_handler_entrypoint_address =
4329      ExternalReference::Create(
4330          IsolateAddressId::kPendingHandlerEntrypointAddress, masm->isolate());
4331  ExternalReference pending_handler_fp_address = ExternalReference::Create(
4332      IsolateAddressId::kPendingHandlerFPAddress, masm->isolate());
4333  ExternalReference pending_handler_sp_address = ExternalReference::Create(
4334      IsolateAddressId::kPendingHandlerSPAddress, masm->isolate());
4335
4336  // Ask the runtime for help to determine the handler. This will set rax to
4337  // contain the current pending exception, don't clobber it.
4338  ExternalReference find_handler =
4339      ExternalReference::Create(Runtime::kUnwindAndFindExceptionHandler);
4340  {
4341    FrameScope scope(masm, StackFrame::MANUAL);
4342    __ Move(arg_reg_1, 0);  // argc.
4343    __ Move(arg_reg_2, 0);  // argv.
4344    __ Move(arg_reg_3, ExternalReference::isolate_address(masm->isolate()));
4345    __ PrepareCallCFunction(3);
4346    __ CallCFunction(find_handler, 3);
4347  }
4348
4349#ifdef V8_ENABLE_CET_SHADOW_STACK
4350  // Drop frames from the shadow stack.
4351  ExternalReference num_frames_above_pending_handler_address =
4352      ExternalReference::Create(
4353          IsolateAddressId::kNumFramesAbovePendingHandlerAddress,
4354          masm->isolate());
4355  __ movq(rcx, masm->ExternalReferenceAsOperand(
4356                   num_frames_above_pending_handler_address));
4357  __ IncsspqIfSupported(rcx, kScratchRegister);
4358#endif  // V8_ENABLE_CET_SHADOW_STACK
4359
4360  // Retrieve the handler context, SP and FP.
4361  __ movq(rsi,
4362          masm->ExternalReferenceAsOperand(pending_handler_context_address));
4363  __ movq(rsp, masm->ExternalReferenceAsOperand(pending_handler_sp_address));
4364  __ movq(rbp, masm->ExternalReferenceAsOperand(pending_handler_fp_address));
4365
4366  // If the handler is a JS frame, restore the context to the frame. Note that
4367  // the context will be set to (rsi == 0) for non-JS frames.
4368  Label skip;
4369  __ testq(rsi, rsi);
4370  __ j(zero, &skip, Label::kNear);
4371  __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
4372  __ bind(&skip);
4373
4374  // Clear c_entry_fp, like we do in `LeaveExitFrame`.
4375  ExternalReference c_entry_fp_address = ExternalReference::Create(
4376      IsolateAddressId::kCEntryFPAddress, masm->isolate());
4377  Operand c_entry_fp_operand =
4378      masm->ExternalReferenceAsOperand(c_entry_fp_address);
4379  __ movq(c_entry_fp_operand, Immediate(0));
4380
4381  // Compute the handler entry address and jump to it.
4382  __ movq(rdi,
4383          masm->ExternalReferenceAsOperand(pending_handler_entrypoint_address));
4384  __ jmp(rdi);
4385}
4386
4387void Builtins::Generate_DoubleToI(MacroAssembler* masm) {
4388  Label check_negative, process_64_bits, done;
4389
4390  // Account for return address and saved regs.
4391  const int kArgumentOffset = 4 * kSystemPointerSize;
4392
4393  MemOperand mantissa_operand(MemOperand(rsp, kArgumentOffset));
4394  MemOperand exponent_operand(
4395      MemOperand(rsp, kArgumentOffset + kDoubleSize / 2));
4396
4397  // The result is returned on the stack.
4398  MemOperand return_operand = mantissa_operand;
4399
4400  Register scratch1 = rbx;
4401
4402  // Since we must use rcx for shifts below, use some other register (rax)
4403  // to calculate the result if ecx is the requested return register.
4404  Register result_reg = rax;
4405  // Save ecx if it isn't the return register and therefore volatile, or if it
4406  // is the return register, then save the temp register we use in its stead
4407  // for the result.
4408  Register save_reg = rax;
4409  __ pushq(rcx);
4410  __ pushq(scratch1);
4411  __ pushq(save_reg);
4412
4413  __ movl(scratch1, mantissa_operand);
4414  __ Movsd(kScratchDoubleReg, mantissa_operand);
4415  __ movl(rcx, exponent_operand);
4416
4417  __ andl(rcx, Immediate(HeapNumber::kExponentMask));
4418  __ shrl(rcx, Immediate(HeapNumber::kExponentShift));
4419  __ leal(result_reg, MemOperand(rcx, -HeapNumber::kExponentBias));
4420  __ cmpl(result_reg, Immediate(HeapNumber::kMantissaBits));
4421  __ j(below, &process_64_bits, Label::kNear);
4422
4423  // Result is entirely in lower 32-bits of mantissa
4424  int delta =
4425      HeapNumber::kExponentBias + base::Double::kPhysicalSignificandSize;
4426  __ subl(rcx, Immediate(delta));
4427  __ xorl(result_reg, result_reg);
4428  __ cmpl(rcx, Immediate(31));
4429  __ j(above, &done, Label::kNear);
4430  __ shll_cl(scratch1);
4431  __ jmp(&check_negative, Label::kNear);
4432
4433  __ bind(&process_64_bits);
4434  __ Cvttsd2siq(result_reg, kScratchDoubleReg);
4435  __ jmp(&done, Label::kNear);
4436
4437  // If the double was negative, negate the integer result.
4438  __ bind(&check_negative);
4439  __ movl(result_reg, scratch1);
4440  __ negl(result_reg);
4441  __ cmpl(exponent_operand, Immediate(0));
4442  __ cmovl(greater, result_reg, scratch1);
4443
4444  // Restore registers
4445  __ bind(&done);
4446  __ movl(return_operand, result_reg);
4447  __ popq(save_reg);
4448  __ popq(scratch1);
4449  __ popq(rcx);
4450  __ ret(0);
4451}
4452
4453namespace {
4454
4455int Offset(ExternalReference ref0, ExternalReference ref1) {
4456  int64_t offset = (ref0.address() - ref1.address());
4457  // Check that fits into int.
4458  DCHECK(static_cast<int>(offset) == offset);
4459  return static_cast<int>(offset);
4460}
4461
4462// Calls an API function.  Allocates HandleScope, extracts returned value
4463// from handle and propagates exceptions.  Clobbers r12, r15, rbx and
4464// caller-save registers.  Restores context.  On return removes
4465// stack_space * kSystemPointerSize (GCed).
4466void CallApiFunctionAndReturn(MacroAssembler* masm, Register function_address,
4467                              ExternalReference thunk_ref,
4468                              Register thunk_last_arg, int stack_space,
4469                              Operand* stack_space_operand,
4470                              Operand return_value_operand) {
4471  Label prologue;
4472  Label promote_scheduled_exception;
4473  Label delete_allocated_handles;
4474  Label leave_exit_frame;
4475
4476  Isolate* isolate = masm->isolate();
4477  Factory* factory = isolate->factory();
4478  ExternalReference next_address =
4479      ExternalReference::handle_scope_next_address(isolate);
4480  const int kNextOffset = 0;
4481  const int kLimitOffset = Offset(
4482      ExternalReference::handle_scope_limit_address(isolate), next_address);
4483  const int kLevelOffset = Offset(
4484      ExternalReference::handle_scope_level_address(isolate), next_address);
4485  ExternalReference scheduled_exception_address =
4486      ExternalReference::scheduled_exception_address(isolate);
4487
4488  DCHECK(rdx == function_address || r8 == function_address);
4489  // Allocate HandleScope in callee-save registers.
4490  Register prev_next_address_reg = r12;
4491  Register prev_limit_reg = rbx;
4492  Register base_reg = r15;
4493  __ Move(base_reg, next_address);
4494  __ movq(prev_next_address_reg, Operand(base_reg, kNextOffset));
4495  __ movq(prev_limit_reg, Operand(base_reg, kLimitOffset));
4496  __ addl(Operand(base_reg, kLevelOffset), Immediate(1));
4497
4498  Label profiler_enabled, end_profiler_check;
4499  __ Move(rax, ExternalReference::is_profiling_address(isolate));
4500  __ cmpb(Operand(rax, 0), Immediate(0));
4501  __ j(not_zero, &profiler_enabled);
4502  __ Move(rax, ExternalReference::address_of_runtime_stats_flag());
4503  __ cmpl(Operand(rax, 0), Immediate(0));
4504  __ j(not_zero, &profiler_enabled);
4505  {
4506    // Call the api function directly.
4507    __ Move(rax, function_address);
4508    __ jmp(&end_profiler_check);
4509  }
4510  __ bind(&profiler_enabled);
4511  {
4512    // Third parameter is the address of the actual getter function.
4513    __ Move(thunk_last_arg, function_address);
4514    __ Move(rax, thunk_ref);
4515  }
4516  __ bind(&end_profiler_check);
4517
4518  // Call the api function!
4519  __ call(rax);
4520
4521  // Load the value from ReturnValue
4522  __ movq(rax, return_value_operand);
4523  __ bind(&prologue);
4524
4525  // No more valid handles (the result handle was the last one). Restore
4526  // previous handle scope.
4527  __ subl(Operand(base_reg, kLevelOffset), Immediate(1));
4528  __ movq(Operand(base_reg, kNextOffset), prev_next_address_reg);
4529  __ cmpq(prev_limit_reg, Operand(base_reg, kLimitOffset));
4530  __ j(not_equal, &delete_allocated_handles);
4531
4532  // Leave the API exit frame.
4533  __ bind(&leave_exit_frame);
4534  if (stack_space_operand != nullptr) {
4535    DCHECK_EQ(stack_space, 0);
4536    __ movq(rbx, *stack_space_operand);
4537  }
4538  __ LeaveApiExitFrame();
4539
4540  // Check if the function scheduled an exception.
4541  __ Move(rdi, scheduled_exception_address);
4542  __ Cmp(Operand(rdi, 0), factory->the_hole_value());
4543  __ j(not_equal, &promote_scheduled_exception);
4544
4545#if DEBUG
4546  // Check if the function returned a valid JavaScript value.
4547  Label ok;
4548  Register return_value = rax;
4549  Register map = rcx;
4550
4551  __ JumpIfSmi(return_value, &ok, Label::kNear);
4552  __ LoadMap(map, return_value);
4553  __ CmpInstanceType(map, LAST_NAME_TYPE);
4554  __ j(below_equal, &ok, Label::kNear);
4555
4556  __ CmpInstanceType(map, FIRST_JS_RECEIVER_TYPE);
4557  __ j(above_equal, &ok, Label::kNear);
4558
4559  __ CompareRoot(map, RootIndex::kHeapNumberMap);
4560  __ j(equal, &ok, Label::kNear);
4561
4562  __ CompareRoot(map, RootIndex::kBigIntMap);
4563  __ j(equal, &ok, Label::kNear);
4564
4565  __ CompareRoot(return_value, RootIndex::kUndefinedValue);
4566  __ j(equal, &ok, Label::kNear);
4567
4568  __ CompareRoot(return_value, RootIndex::kTrueValue);
4569  __ j(equal, &ok, Label::kNear);
4570
4571  __ CompareRoot(return_value, RootIndex::kFalseValue);
4572  __ j(equal, &ok, Label::kNear);
4573
4574  __ CompareRoot(return_value, RootIndex::kNullValue);
4575  __ j(equal, &ok, Label::kNear);
4576
4577  __ Abort(AbortReason::kAPICallReturnedInvalidObject);
4578
4579  __ bind(&ok);
4580#endif
4581
4582  if (stack_space_operand == nullptr) {
4583    DCHECK_NE(stack_space, 0);
4584    __ ret(stack_space * kSystemPointerSize);
4585  } else {
4586    DCHECK_EQ(stack_space, 0);
4587    __ PopReturnAddressTo(rcx);
4588    // {stack_space_operand} was loaded into {rbx} above.
4589    __ addq(rsp, rbx);
4590    // Push and ret (instead of jmp) to keep the RSB and the CET shadow stack
4591    // balanced.
4592    __ PushReturnAddressFrom(rcx);
4593    __ ret(0);
4594  }
4595
4596  // Re-throw by promoting a scheduled exception.
4597  __ bind(&promote_scheduled_exception);
4598  __ TailCallRuntime(Runtime::kPromoteScheduledException);
4599
4600  // HandleScope limit has changed. Delete allocated extensions.
4601  __ bind(&delete_allocated_handles);
4602  __ movq(Operand(base_reg, kLimitOffset), prev_limit_reg);
4603  __ movq(prev_limit_reg, rax);
4604  __ LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate));
4605  __ LoadAddress(rax, ExternalReference::delete_handle_scope_extensions());
4606  __ call(rax);
4607  __ movq(rax, prev_limit_reg);
4608  __ jmp(&leave_exit_frame);
4609}
4610
4611}  // namespace
4612
4613// TODO(jgruber): Instead of explicitly setting up implicit_args_ on the stack
4614// in CallApiCallback, we could use the calling convention to set up the stack
4615// correctly in the first place.
4616//
4617// TODO(jgruber): I suspect that most of CallApiCallback could be implemented
4618// as a C++ trampoline, vastly simplifying the assembly implementation.
4619
4620void Builtins::Generate_CallApiCallback(MacroAssembler* masm) {
4621  // ----------- S t a t e -------------
4622  //  -- rsi                 : context
4623  //  -- rdx                 : api function address
4624  //  -- rcx                 : arguments count (not including the receiver)
4625  //  -- rbx                 : call data
4626  //  -- rdi                 : holder
4627  //  -- rsp[0]              : return address
4628  //  -- rsp[8]              : argument 0 (receiver)
4629  //  -- rsp[16]             : argument 1
4630  //  -- ...
4631  //  -- rsp[argc * 8]       : argument (argc - 1)
4632  //  -- rsp[(argc + 1) * 8] : argument argc
4633  // -----------------------------------
4634
4635  Register api_function_address = rdx;
4636  Register argc = rcx;
4637  Register call_data = rbx;
4638  Register holder = rdi;
4639
4640  DCHECK(!AreAliased(api_function_address, argc, holder, call_data,
4641                     kScratchRegister));
4642
4643  using FCA = FunctionCallbackArguments;
4644
4645  STATIC_ASSERT(FCA::kArgsLength == 6);
4646  STATIC_ASSERT(FCA::kNewTargetIndex == 5);
4647  STATIC_ASSERT(FCA::kDataIndex == 4);
4648  STATIC_ASSERT(FCA::kReturnValueOffset == 3);
4649  STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
4650  STATIC_ASSERT(FCA::kIsolateIndex == 1);
4651  STATIC_ASSERT(FCA::kHolderIndex == 0);
4652
4653  // Set up FunctionCallbackInfo's implicit_args on the stack as follows:
4654  //
4655  // Current state:
4656  //   rsp[0]: return address
4657  //
4658  // Target state:
4659  //   rsp[0 * kSystemPointerSize]: return address
4660  //   rsp[1 * kSystemPointerSize]: kHolder
4661  //   rsp[2 * kSystemPointerSize]: kIsolate
4662  //   rsp[3 * kSystemPointerSize]: undefined (kReturnValueDefaultValue)
4663  //   rsp[4 * kSystemPointerSize]: undefined (kReturnValue)
4664  //   rsp[5 * kSystemPointerSize]: kData
4665  //   rsp[6 * kSystemPointerSize]: undefined (kNewTarget)
4666
4667  __ PopReturnAddressTo(rax);
4668  __ LoadRoot(kScratchRegister, RootIndex::kUndefinedValue);
4669  __ Push(kScratchRegister);
4670  __ Push(call_data);
4671  __ Push(kScratchRegister);
4672  __ Push(kScratchRegister);
4673  __ PushAddress(ExternalReference::isolate_address(masm->isolate()));
4674  __ Push(holder);
4675  __ PushReturnAddressFrom(rax);
4676
4677  // Keep a pointer to kHolder (= implicit_args) in a scratch register.
4678  // We use it below to set up the FunctionCallbackInfo object.
4679  Register scratch = rbx;
4680  __ leaq(scratch, Operand(rsp, 1 * kSystemPointerSize));
4681
4682  // Allocate the v8::Arguments structure in the arguments' space since
4683  // it's not controlled by GC.
4684  static constexpr int kApiStackSpace = 4;
4685  __ EnterApiExitFrame(kApiStackSpace);
4686
4687  // FunctionCallbackInfo::implicit_args_ (points at kHolder as set up above).
4688  __ movq(StackSpaceOperand(0), scratch);
4689
4690  // FunctionCallbackInfo::values_ (points at the first varargs argument passed
4691  // on the stack).
4692  __ leaq(scratch,
4693          Operand(scratch, (FCA::kArgsLength + 1) * kSystemPointerSize));
4694  __ movq(StackSpaceOperand(1), scratch);
4695
4696  // FunctionCallbackInfo::length_.
4697  __ movq(StackSpaceOperand(2), argc);
4698
4699  // We also store the number of bytes to drop from the stack after returning
4700  // from the API function here.
4701  __ leaq(kScratchRegister,
4702          Operand(argc, times_system_pointer_size,
4703                  (FCA::kArgsLength + 1 /* receiver */) * kSystemPointerSize));
4704  __ movq(StackSpaceOperand(3), kScratchRegister);
4705
4706  Register arguments_arg = arg_reg_1;
4707  Register callback_arg = arg_reg_2;
4708
4709  // It's okay if api_function_address == callback_arg
4710  // but not arguments_arg
4711  DCHECK(api_function_address != arguments_arg);
4712
4713  // v8::InvocationCallback's argument.
4714  __ leaq(arguments_arg, StackSpaceOperand(0));
4715
4716  ExternalReference thunk_ref = ExternalReference::invoke_function_callback();
4717
4718  // There are two stack slots above the arguments we constructed on the stack:
4719  // the stored ebp (pushed by EnterApiExitFrame), and the return address.
4720  static constexpr int kStackSlotsAboveFCA = 2;
4721  Operand return_value_operand(
4722      rbp,
4723      (kStackSlotsAboveFCA + FCA::kReturnValueOffset) * kSystemPointerSize);
4724
4725  static constexpr int kUseStackSpaceOperand = 0;
4726  Operand stack_space_operand = StackSpaceOperand(3);
4727  CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, callback_arg,
4728                           kUseStackSpaceOperand, &stack_space_operand,
4729                           return_value_operand);
4730}
4731
4732void Builtins::Generate_CallApiGetter(MacroAssembler* masm) {
4733  Register name_arg = arg_reg_1;
4734  Register accessor_info_arg = arg_reg_2;
4735  Register getter_arg = arg_reg_3;
4736  Register api_function_address = r8;
4737  Register receiver = ApiGetterDescriptor::ReceiverRegister();
4738  Register holder = ApiGetterDescriptor::HolderRegister();
4739  Register callback = ApiGetterDescriptor::CallbackRegister();
4740  Register scratch = rax;
4741  Register decompr_scratch1 = COMPRESS_POINTERS_BOOL ? r15 : no_reg;
4742
4743  DCHECK(!AreAliased(receiver, holder, callback, scratch, decompr_scratch1));
4744
4745  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
4746  // name below the exit frame to make GC aware of them.
4747  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
4748  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
4749  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
4750  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
4751  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
4752  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
4753  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
4754  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
4755
4756  // Insert additional parameters into the stack frame above return address.
4757  __ PopReturnAddressTo(scratch);
4758  __ Push(receiver);
4759  __ PushTaggedAnyField(FieldOperand(callback, AccessorInfo::kDataOffset),
4760                        decompr_scratch1);
4761  __ LoadRoot(kScratchRegister, RootIndex::kUndefinedValue);
4762  __ Push(kScratchRegister);  // return value
4763  __ Push(kScratchRegister);  // return value default
4764  __ PushAddress(ExternalReference::isolate_address(masm->isolate()));
4765  __ Push(holder);
4766  __ Push(Smi::zero());  // should_throw_on_error -> false
4767  __ PushTaggedPointerField(FieldOperand(callback, AccessorInfo::kNameOffset),
4768                            decompr_scratch1);
4769  __ PushReturnAddressFrom(scratch);
4770
4771  // v8::PropertyCallbackInfo::args_ array and name handle.
4772  const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
4773
4774  // Allocate v8::PropertyCallbackInfo in non-GCed stack space.
4775  const int kArgStackSpace = 1;
4776
4777  // Load address of v8::PropertyAccessorInfo::args_ array.
4778  __ leaq(scratch, Operand(rsp, 2 * kSystemPointerSize));
4779
4780  __ EnterApiExitFrame(kArgStackSpace);
4781
4782  // Create v8::PropertyCallbackInfo object on the stack and initialize
4783  // it's args_ field.
4784  Operand info_object = StackSpaceOperand(0);
4785  __ movq(info_object, scratch);
4786
4787  __ leaq(name_arg, Operand(scratch, -kSystemPointerSize));
4788  // The context register (rsi) has been saved in EnterApiExitFrame and
4789  // could be used to pass arguments.
4790  __ leaq(accessor_info_arg, info_object);
4791
4792  ExternalReference thunk_ref =
4793      ExternalReference::invoke_accessor_getter_callback();
4794
4795  // It's okay if api_function_address == getter_arg
4796  // but not accessor_info_arg or name_arg
4797  DCHECK(api_function_address != accessor_info_arg);
4798  DCHECK(api_function_address != name_arg);
4799  __ LoadTaggedPointerField(
4800      scratch, FieldOperand(callback, AccessorInfo::kJsGetterOffset));
4801  __ LoadExternalPointerField(
4802      api_function_address,
4803      FieldOperand(scratch, Foreign::kForeignAddressOffset),
4804      kForeignForeignAddressTag, kScratchRegister);
4805
4806  // +3 is to skip prolog, return address and name handle.
4807  Operand return_value_operand(
4808      rbp,
4809      (PropertyCallbackArguments::kReturnValueOffset + 3) * kSystemPointerSize);
4810  Operand* const kUseStackSpaceConstant = nullptr;
4811  CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, getter_arg,
4812                           kStackUnwindSpace, kUseStackSpaceConstant,
4813                           return_value_operand);
4814}
4815
4816void Builtins::Generate_DirectCEntry(MacroAssembler* masm) {
4817  __ int3();  // Unused on this architecture.
4818}
4819
4820namespace {
4821
4822void Generate_DeoptimizationEntry(MacroAssembler* masm,
4823                                  DeoptimizeKind deopt_kind) {
4824  Isolate* isolate = masm->isolate();
4825
4826  // Save all double registers, they will later be copied to the deoptimizer's
4827  // FrameDescription.
4828  static constexpr int kDoubleRegsSize =
4829      kDoubleSize * XMMRegister::kNumRegisters;
4830  __ AllocateStackSpace(kDoubleRegsSize);
4831
4832  const RegisterConfiguration* config = RegisterConfiguration::Default();
4833  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
4834    int code = config->GetAllocatableDoubleCode(i);
4835    XMMRegister xmm_reg = XMMRegister::from_code(code);
4836    int offset = code * kDoubleSize;
4837    __ Movsd(Operand(rsp, offset), xmm_reg);
4838  }
4839
4840  // Save all general purpose registers, they will later be copied to the
4841  // deoptimizer's FrameDescription.
4842  static constexpr int kNumberOfRegisters = Register::kNumRegisters;
4843  for (int i = 0; i < kNumberOfRegisters; i++) {
4844    __ pushq(Register::from_code(i));
4845  }
4846
4847  static constexpr int kSavedRegistersAreaSize =
4848      kNumberOfRegisters * kSystemPointerSize + kDoubleRegsSize;
4849  static constexpr int kCurrentOffsetToReturnAddress = kSavedRegistersAreaSize;
4850  static constexpr int kCurrentOffsetToParentSP =
4851      kCurrentOffsetToReturnAddress + kPCOnStackSize;
4852
4853  __ Store(
4854      ExternalReference::Create(IsolateAddressId::kCEntryFPAddress, isolate),
4855      rbp);
4856
4857  // Get the address of the location in the code object
4858  // and compute the fp-to-sp delta in register arg5.
4859  __ movq(arg_reg_3, Operand(rsp, kCurrentOffsetToReturnAddress));
4860  // Load the fp-to-sp-delta.
4861  __ leaq(arg_reg_4, Operand(rsp, kCurrentOffsetToParentSP));
4862  __ subq(arg_reg_4, rbp);
4863  __ negq(arg_reg_4);
4864
4865  // Allocate a new deoptimizer object.
4866  __ PrepareCallCFunction(5);
4867  __ Move(rax, 0);
4868  Label context_check;
4869  __ movq(rdi, Operand(rbp, CommonFrameConstants::kContextOrFrameTypeOffset));
4870  __ JumpIfSmi(rdi, &context_check);
4871  __ movq(rax, Operand(rbp, StandardFrameConstants::kFunctionOffset));
4872  __ bind(&context_check);
4873  __ movq(arg_reg_1, rax);
4874  __ Move(arg_reg_2, static_cast<int>(deopt_kind));
4875  // Args 3 and 4 are already in the right registers.
4876
4877  // On windows put the arguments on the stack (PrepareCallCFunction
4878  // has created space for this). On linux pass the arguments in r8.
4879#ifdef V8_TARGET_OS_WIN
4880  Register arg5 = r15;
4881  __ LoadAddress(arg5, ExternalReference::isolate_address(isolate));
4882  __ movq(Operand(rsp, 4 * kSystemPointerSize), arg5);
4883#else
4884  // r8 is arg_reg_5 on Linux
4885  __ LoadAddress(r8, ExternalReference::isolate_address(isolate));
4886#endif
4887
4888  {
4889    AllowExternalCallThatCantCauseGC scope(masm);
4890    __ CallCFunction(ExternalReference::new_deoptimizer_function(), 5);
4891  }
4892  // Preserve deoptimizer object in register rax and get the input
4893  // frame descriptor pointer.
4894  __ movq(rbx, Operand(rax, Deoptimizer::input_offset()));
4895
4896  // Fill in the input registers.
4897  for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
4898    int offset =
4899        (i * kSystemPointerSize) + FrameDescription::registers_offset();
4900    __ PopQuad(Operand(rbx, offset));
4901  }
4902
4903  // Fill in the double input registers.
4904  int double_regs_offset = FrameDescription::double_registers_offset();
4905  for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
4906    int dst_offset = i * kDoubleSize + double_regs_offset;
4907    __ popq(Operand(rbx, dst_offset));
4908  }
4909
4910  // Mark the stack as not iterable for the CPU profiler which won't be able to
4911  // walk the stack without the return address.
4912  __ movb(__ ExternalReferenceAsOperand(
4913              ExternalReference::stack_is_iterable_address(isolate)),
4914          Immediate(0));
4915
4916  // Remove the return address from the stack.
4917  __ addq(rsp, Immediate(kPCOnStackSize));
4918
4919  // Compute a pointer to the unwinding limit in register rcx; that is
4920  // the first stack slot not part of the input frame.
4921  __ movq(rcx, Operand(rbx, FrameDescription::frame_size_offset()));
4922  __ addq(rcx, rsp);
4923
4924  // Unwind the stack down to - but not including - the unwinding
4925  // limit and copy the contents of the activation frame to the input
4926  // frame description.
4927  __ leaq(rdx, Operand(rbx, FrameDescription::frame_content_offset()));
4928  Label pop_loop_header;
4929  __ jmp(&pop_loop_header);
4930  Label pop_loop;
4931  __ bind(&pop_loop);
4932  __ Pop(Operand(rdx, 0));
4933  __ addq(rdx, Immediate(sizeof(intptr_t)));
4934  __ bind(&pop_loop_header);
4935  __ cmpq(rcx, rsp);
4936  __ j(not_equal, &pop_loop);
4937
4938  // Compute the output frame in the deoptimizer.
4939  __ pushq(rax);
4940  __ PrepareCallCFunction(2);
4941  __ movq(arg_reg_1, rax);
4942  __ LoadAddress(arg_reg_2, ExternalReference::isolate_address(isolate));
4943  {
4944    AllowExternalCallThatCantCauseGC scope(masm);
4945    __ CallCFunction(ExternalReference::compute_output_frames_function(), 2);
4946  }
4947  __ popq(rax);
4948
4949  __ movq(rsp, Operand(rax, Deoptimizer::caller_frame_top_offset()));
4950
4951  // Replace the current (input) frame with the output frames.
4952  Label outer_push_loop, inner_push_loop, outer_loop_header, inner_loop_header;
4953  // Outer loop state: rax = current FrameDescription**, rdx = one past the
4954  // last FrameDescription**.
4955  __ movl(rdx, Operand(rax, Deoptimizer::output_count_offset()));
4956  __ movq(rax, Operand(rax, Deoptimizer::output_offset()));
4957  __ leaq(rdx, Operand(rax, rdx, times_system_pointer_size, 0));
4958  __ jmp(&outer_loop_header);
4959  __ bind(&outer_push_loop);
4960  // Inner loop state: rbx = current FrameDescription*, rcx = loop index.
4961  __ movq(rbx, Operand(rax, 0));
4962  __ movq(rcx, Operand(rbx, FrameDescription::frame_size_offset()));
4963  __ jmp(&inner_loop_header);
4964  __ bind(&inner_push_loop);
4965  __ subq(rcx, Immediate(sizeof(intptr_t)));
4966  __ Push(Operand(rbx, rcx, times_1, FrameDescription::frame_content_offset()));
4967  __ bind(&inner_loop_header);
4968  __ testq(rcx, rcx);
4969  __ j(not_zero, &inner_push_loop);
4970  __ addq(rax, Immediate(kSystemPointerSize));
4971  __ bind(&outer_loop_header);
4972  __ cmpq(rax, rdx);
4973  __ j(below, &outer_push_loop);
4974
4975  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
4976    int code = config->GetAllocatableDoubleCode(i);
4977    XMMRegister xmm_reg = XMMRegister::from_code(code);
4978    int src_offset = code * kDoubleSize + double_regs_offset;
4979    __ Movsd(xmm_reg, Operand(rbx, src_offset));
4980  }
4981
4982  // Push pc and continuation from the last output frame.
4983  __ PushQuad(Operand(rbx, FrameDescription::pc_offset()));
4984  __ PushQuad(Operand(rbx, FrameDescription::continuation_offset()));
4985
4986  // Push the registers from the last output frame.
4987  for (int i = 0; i < kNumberOfRegisters; i++) {
4988    int offset =
4989        (i * kSystemPointerSize) + FrameDescription::registers_offset();
4990    __ PushQuad(Operand(rbx, offset));
4991  }
4992
4993  // Restore the registers from the stack.
4994  for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
4995    Register r = Register::from_code(i);
4996    // Do not restore rsp, simply pop the value into the next register
4997    // and overwrite this afterwards.
4998    if (r == rsp) {
4999      DCHECK_GT(i, 0);
5000      r = Register::from_code(i - 1);
5001    }
5002    __ popq(r);
5003  }
5004
5005  __ movb(__ ExternalReferenceAsOperand(
5006              ExternalReference::stack_is_iterable_address(isolate)),
5007          Immediate(1));
5008
5009  // Return to the continuation point.
5010  __ ret(0);
5011}
5012
5013}  // namespace
5014
5015void Builtins::Generate_DeoptimizationEntry_Eager(MacroAssembler* masm) {
5016  Generate_DeoptimizationEntry(masm, DeoptimizeKind::kEager);
5017}
5018
5019void Builtins::Generate_DeoptimizationEntry_Lazy(MacroAssembler* masm) {
5020  Generate_DeoptimizationEntry(masm, DeoptimizeKind::kLazy);
5021}
5022
5023void Builtins::Generate_DeoptimizationEntry_Unused(MacroAssembler* masm) {
5024  Generate_DeoptimizationEntry(masm, DeoptimizeKind::kUnused);
5025}
5026
5027namespace {
5028
5029// Restarts execution either at the current or next (in execution order)
5030// bytecode. If there is baseline code on the shared function info, converts an
5031// interpreter frame into a baseline frame and continues execution in baseline
5032// code. Otherwise execution continues with bytecode.
5033void Generate_BaselineOrInterpreterEntry(MacroAssembler* masm,
5034                                         bool next_bytecode,
5035                                         bool is_osr = false) {
5036  Label start;
5037  __ bind(&start);
5038
5039  // Get function from the frame.
5040  Register closure = rdi;
5041  __ movq(closure, MemOperand(rbp, StandardFrameConstants::kFunctionOffset));
5042
5043  // Get the Code object from the shared function info.
5044  Register code_obj = rbx;
5045  __ LoadTaggedPointerField(
5046      code_obj, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset));
5047  __ LoadTaggedPointerField(
5048      code_obj,
5049      FieldOperand(code_obj, SharedFunctionInfo::kFunctionDataOffset));
5050
5051  // Check if we have baseline code. For OSR entry it is safe to assume we
5052  // always have baseline code.
5053  if (!is_osr) {
5054    Label start_with_baseline;
5055    __ CmpObjectType(code_obj, CODET_TYPE, kScratchRegister);
5056    __ j(equal, &start_with_baseline);
5057
5058    // Start with bytecode as there is no baseline code.
5059    Builtin builtin_id = next_bytecode
5060                             ? Builtin::kInterpreterEnterAtNextBytecode
5061                             : Builtin::kInterpreterEnterAtBytecode;
5062    __ Jump(masm->isolate()->builtins()->code_handle(builtin_id),
5063            RelocInfo::CODE_TARGET);
5064
5065    // Start with baseline code.
5066    __ bind(&start_with_baseline);
5067  } else if (FLAG_debug_code) {
5068    __ CmpObjectType(code_obj, CODET_TYPE, kScratchRegister);
5069    __ Assert(equal, AbortReason::kExpectedBaselineData);
5070  }
5071
5072  if (FLAG_debug_code) {
5073    AssertCodeTIsBaseline(masm, code_obj, r11);
5074  }
5075  if (V8_EXTERNAL_CODE_SPACE_BOOL) {
5076    __ LoadCodeDataContainerCodeNonBuiltin(code_obj, code_obj);
5077  }
5078
5079  // Load the feedback vector.
5080  Register feedback_vector = r11;
5081  __ LoadTaggedPointerField(
5082      feedback_vector, FieldOperand(closure, JSFunction::kFeedbackCellOffset));
5083  __ LoadTaggedPointerField(feedback_vector,
5084                            FieldOperand(feedback_vector, Cell::kValueOffset));
5085
5086  Label install_baseline_code;
5087  // Check if feedback vector is valid. If not, call prepare for baseline to
5088  // allocate it.
5089  __ CmpObjectType(feedback_vector, FEEDBACK_VECTOR_TYPE, kScratchRegister);
5090  __ j(not_equal, &install_baseline_code);
5091
5092  // Save BytecodeOffset from the stack frame.
5093  __ SmiUntag(
5094      kInterpreterBytecodeOffsetRegister,
5095      MemOperand(rbp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
5096  // Replace BytecodeOffset with the feedback vector.
5097  __ movq(MemOperand(rbp, InterpreterFrameConstants::kBytecodeOffsetFromFp),
5098          feedback_vector);
5099  feedback_vector = no_reg;
5100
5101  // Compute baseline pc for bytecode offset.
5102  ExternalReference get_baseline_pc_extref;
5103  if (next_bytecode || is_osr) {
5104    get_baseline_pc_extref =
5105        ExternalReference::baseline_pc_for_next_executed_bytecode();
5106  } else {
5107    get_baseline_pc_extref =
5108        ExternalReference::baseline_pc_for_bytecode_offset();
5109  }
5110  Register get_baseline_pc = r11;
5111  __ LoadAddress(get_baseline_pc, get_baseline_pc_extref);
5112
5113  // If the code deoptimizes during the implicit function entry stack interrupt
5114  // check, it will have a bailout ID of kFunctionEntryBytecodeOffset, which is
5115  // not a valid bytecode offset.
5116  // TODO(pthier): Investigate if it is feasible to handle this special case
5117  // in TurboFan instead of here.
5118  Label valid_bytecode_offset, function_entry_bytecode;
5119  if (!is_osr) {
5120    __ cmpq(kInterpreterBytecodeOffsetRegister,
5121            Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag +
5122                      kFunctionEntryBytecodeOffset));
5123    __ j(equal, &function_entry_bytecode);
5124  }
5125
5126  __ subq(kInterpreterBytecodeOffsetRegister,
5127          Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
5128
5129  __ bind(&valid_bytecode_offset);
5130  // Get bytecode array from the stack frame.
5131  __ movq(kInterpreterBytecodeArrayRegister,
5132          MemOperand(rbp, InterpreterFrameConstants::kBytecodeArrayFromFp));
5133  __ pushq(kInterpreterAccumulatorRegister);
5134  {
5135    FrameScope scope(masm, StackFrame::INTERNAL);
5136    __ PrepareCallCFunction(3);
5137    __ movq(arg_reg_1, code_obj);
5138    __ movq(arg_reg_2, kInterpreterBytecodeOffsetRegister);
5139    __ movq(arg_reg_3, kInterpreterBytecodeArrayRegister);
5140    __ CallCFunction(get_baseline_pc, 3);
5141  }
5142  __ leaq(code_obj,
5143          FieldOperand(code_obj, kReturnRegister0, times_1, Code::kHeaderSize));
5144  __ popq(kInterpreterAccumulatorRegister);
5145
5146  if (is_osr) {
5147    // TODO(pthier): Separate Sparkplug and Turbofan OSR states.
5148    ResetBytecodeAgeAndOsrState(masm, kInterpreterBytecodeArrayRegister);
5149    Generate_OSREntry(masm, code_obj);
5150  } else {
5151    __ jmp(code_obj);
5152  }
5153  __ Trap();  // Unreachable.
5154
5155  if (!is_osr) {
5156    __ bind(&function_entry_bytecode);
5157    // If the bytecode offset is kFunctionEntryOffset, get the start address of
5158    // the first bytecode.
5159    __ Move(kInterpreterBytecodeOffsetRegister, 0);
5160    if (next_bytecode) {
5161      __ LoadAddress(get_baseline_pc,
5162                     ExternalReference::baseline_pc_for_bytecode_offset());
5163    }
5164    __ jmp(&valid_bytecode_offset);
5165  }
5166
5167  __ bind(&install_baseline_code);
5168  {
5169    FrameScope scope(masm, StackFrame::INTERNAL);
5170    __ pushq(kInterpreterAccumulatorRegister);
5171    __ Push(closure);
5172    __ CallRuntime(Runtime::kInstallBaselineCode, 1);
5173    __ popq(kInterpreterAccumulatorRegister);
5174  }
5175  // Retry from the start after installing baseline code.
5176  __ jmp(&start);
5177}
5178
5179}  // namespace
5180
5181void Builtins::Generate_BaselineOrInterpreterEnterAtBytecode(
5182    MacroAssembler* masm) {
5183  Generate_BaselineOrInterpreterEntry(masm, false);
5184}
5185
5186void Builtins::Generate_BaselineOrInterpreterEnterAtNextBytecode(
5187    MacroAssembler* masm) {
5188  Generate_BaselineOrInterpreterEntry(masm, true);
5189}
5190
5191void Builtins::Generate_InterpreterOnStackReplacement_ToBaseline(
5192    MacroAssembler* masm) {
5193  Generate_BaselineOrInterpreterEntry(masm, false, true);
5194}
5195
5196#undef __
5197
5198}  // namespace internal
5199}  // namespace v8
5200
5201#endif  // V8_TARGET_ARCH_X64
5202