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#include "src/codegen/register.h"
6#if V8_TARGET_ARCH_IA32
7
8#include "src/api/api-arguments.h"
9#include "src/base/bits-iterator.h"
10#include "src/base/iterator.h"
11#include "src/codegen/code-factory.h"
12#include "src/codegen/interface-descriptors-inl.h"
13// For interpreter_entry_return_pc_offset. TODO(jkummerow): Drop.
14#include "src/codegen/macro-assembler-inl.h"
15#include "src/codegen/register-configuration.h"
16#include "src/debug/debug.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/foreign.h"
24#include "src/objects/heap-number.h"
25#include "src/objects/js-generator.h"
26#include "src/objects/objects-inl.h"
27#include "src/objects/smi.h"
28
29#if V8_ENABLE_WEBASSEMBLY
30#include "src/wasm/wasm-linkage.h"
31#include "src/wasm/wasm-objects.h"
32#endif  // V8_ENABLE_WEBASSEMBLY
33
34namespace v8 {
35namespace internal {
36
37#define __ ACCESS_MASM(masm)
38
39void Builtins::Generate_Adaptor(MacroAssembler* masm, Address address) {
40  __ Move(kJavaScriptCallExtraArg1Register,
41          Immediate(ExternalReference::Create(address)));
42  __ Jump(BUILTIN_CODE(masm->isolate(), AdaptorWithBuiltinExitFrame),
43          RelocInfo::CODE_TARGET);
44}
45
46static void GenerateTailCallToReturnedCode(MacroAssembler* masm,
47                                           Runtime::FunctionId function_id) {
48  // ----------- S t a t e -------------
49  //  -- eax : actual argument count
50  //  -- edx : new target (preserved for callee)
51  //  -- edi : target function (preserved for callee)
52  // -----------------------------------
53  ASM_CODE_COMMENT(masm);
54  {
55    FrameScope scope(masm, StackFrame::INTERNAL);
56    // Push a copy of the target function, the new target and the actual
57    // argument count.
58    __ push(kJavaScriptCallTargetRegister);
59    __ push(kJavaScriptCallNewTargetRegister);
60    __ SmiTag(kJavaScriptCallArgCountRegister);
61    __ push(kJavaScriptCallArgCountRegister);
62    // Function is also the parameter to the runtime call.
63    __ push(kJavaScriptCallTargetRegister);
64
65    __ CallRuntime(function_id, 1);
66    __ mov(ecx, eax);
67
68    // Restore target function, new target and actual argument count.
69    __ pop(kJavaScriptCallArgCountRegister);
70    __ SmiUntag(kJavaScriptCallArgCountRegister);
71    __ pop(kJavaScriptCallNewTargetRegister);
72    __ pop(kJavaScriptCallTargetRegister);
73  }
74
75  static_assert(kJavaScriptCallCodeStartRegister == ecx, "ABI mismatch");
76  __ JumpCodeObject(ecx);
77}
78
79namespace {
80
81enum class ArgumentsElementType {
82  kRaw,    // Push arguments as they are.
83  kHandle  // Dereference arguments before pushing.
84};
85
86void Generate_PushArguments(MacroAssembler* masm, Register array, Register argc,
87                            Register scratch1, Register scratch2,
88                            ArgumentsElementType element_type) {
89  DCHECK(!AreAliased(array, argc, scratch1, scratch2));
90  Register counter = scratch1;
91  Label loop, entry;
92  __ lea(counter, Operand(argc, -kJSArgcReceiverSlots));
93  __ jmp(&entry);
94  __ bind(&loop);
95  Operand value(array, counter, times_system_pointer_size, 0);
96  if (element_type == ArgumentsElementType::kHandle) {
97    DCHECK(scratch2 != no_reg);
98    __ mov(scratch2, value);
99    value = Operand(scratch2, 0);
100  }
101  __ Push(value);
102  __ bind(&entry);
103  __ dec(counter);
104  __ j(greater_equal, &loop, Label::kNear);
105}
106
107void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
108  // ----------- S t a t e -------------
109  //  -- eax: number of arguments
110  //  -- edi: constructor function
111  //  -- edx: new target
112  //  -- esi: context
113  // -----------------------------------
114
115  Label stack_overflow;
116
117  __ StackOverflowCheck(eax, ecx, &stack_overflow);
118
119  // Enter a construct frame.
120  {
121    FrameScope scope(masm, StackFrame::CONSTRUCT);
122
123    // Preserve the incoming parameters on the stack.
124    __ SmiTag(eax);
125    __ push(esi);
126    __ push(eax);
127    __ SmiUntag(eax);
128
129    // TODO(victorgomes): When the arguments adaptor is completely removed, we
130    // should get the formal parameter count and copy the arguments in its
131    // correct position (including any undefined), instead of delaying this to
132    // InvokeFunction.
133
134    // Set up pointer to first argument (skip receiver).
135    __ lea(esi, Operand(ebp, StandardFrameConstants::kCallerSPOffset +
136                                 kSystemPointerSize));
137    // Copy arguments to the expression stack.
138    // esi: Pointer to start of arguments.
139    // eax: Number of arguments.
140    Generate_PushArguments(masm, esi, eax, ecx, no_reg,
141                           ArgumentsElementType::kRaw);
142    // The receiver for the builtin/api call.
143    __ PushRoot(RootIndex::kTheHoleValue);
144
145    // Call the function.
146    // eax: number of arguments (untagged)
147    // edi: constructor function
148    // edx: new target
149    // Reload context from the frame.
150    __ mov(esi, Operand(ebp, ConstructFrameConstants::kContextOffset));
151    __ InvokeFunction(edi, edx, eax, InvokeType::kCall);
152
153    // Restore context from the frame.
154    __ mov(esi, Operand(ebp, ConstructFrameConstants::kContextOffset));
155    // Restore smi-tagged arguments count from the frame.
156    __ mov(edx, Operand(ebp, ConstructFrameConstants::kLengthOffset));
157    // Leave construct frame.
158  }
159
160  // Remove caller arguments from the stack and return.
161  __ DropArguments(edx, ecx, TurboAssembler::kCountIsSmi,
162                   TurboAssembler::kCountIncludesReceiver);
163  __ ret(0);
164
165  __ bind(&stack_overflow);
166  {
167    FrameScope scope(masm, StackFrame::INTERNAL);
168    __ CallRuntime(Runtime::kThrowStackOverflow);
169    __ int3();  // This should be unreachable.
170  }
171}
172
173}  // namespace
174
175// The construct stub for ES5 constructor functions and ES6 class constructors.
176void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
177  // ----------- S t a t e -------------
178  //  -- eax: number of arguments (untagged)
179  //  -- edi: constructor function
180  //  -- edx: new target
181  //  -- esi: context
182  //  -- sp[...]: constructor arguments
183  // -----------------------------------
184
185  FrameScope scope(masm, StackFrame::MANUAL);
186  // Enter a construct frame.
187  __ EnterFrame(StackFrame::CONSTRUCT);
188
189  Label post_instantiation_deopt_entry, not_create_implicit_receiver;
190
191  // Preserve the incoming parameters on the stack.
192  __ mov(ecx, eax);
193  __ SmiTag(ecx);
194  __ Push(esi);
195  __ Push(ecx);
196  __ Push(edi);
197  __ PushRoot(RootIndex::kTheHoleValue);
198  __ Push(edx);
199
200  // ----------- S t a t e -------------
201  //  --         sp[0*kSystemPointerSize]: new target
202  //  --         sp[1*kSystemPointerSize]: padding
203  //  -- edi and sp[2*kSystemPointerSize]: constructor function
204  //  --         sp[3*kSystemPointerSize]: argument count
205  //  --         sp[4*kSystemPointerSize]: context
206  // -----------------------------------
207
208  __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
209  __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kFlagsOffset));
210  __ DecodeField<SharedFunctionInfo::FunctionKindBits>(eax);
211  __ JumpIfIsInRange(
212      eax, static_cast<uint32_t>(FunctionKind::kDefaultDerivedConstructor),
213      static_cast<uint32_t>(FunctionKind::kDerivedConstructor), ecx,
214      &not_create_implicit_receiver, Label::kNear);
215
216  // If not derived class constructor: Allocate the new receiver object.
217  __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1,
218                      eax);
219  __ Call(BUILTIN_CODE(masm->isolate(), FastNewObject), RelocInfo::CODE_TARGET);
220  __ jmp(&post_instantiation_deopt_entry, Label::kNear);
221
222  // Else: use TheHoleValue as receiver for constructor call
223  __ bind(&not_create_implicit_receiver);
224  __ LoadRoot(eax, RootIndex::kTheHoleValue);
225
226  // ----------- S t a t e -------------
227  //  --                         eax: implicit receiver
228  //  -- Slot 4 / sp[0*kSystemPointerSize]: new target
229  //  -- Slot 3 / sp[1*kSystemPointerSize]: padding
230  //  -- Slot 2 / sp[2*kSystemPointerSize]: constructor function
231  //  -- Slot 1 / sp[3*kSystemPointerSize]: number of arguments (tagged)
232  //  -- Slot 0 / sp[4*kSystemPointerSize]: context
233  // -----------------------------------
234  // Deoptimizer enters here.
235  masm->isolate()->heap()->SetConstructStubCreateDeoptPCOffset(
236      masm->pc_offset());
237  __ bind(&post_instantiation_deopt_entry);
238
239  // Restore new target.
240  __ Pop(edx);
241
242  // Push the allocated receiver to the stack.
243  __ Push(eax);
244
245  // We need two copies because we may have to return the original one
246  // and the calling conventions dictate that the called function pops the
247  // receiver. The second copy is pushed after the arguments, we saved in r8
248  // since rax needs to store the number of arguments before
249  // InvokingFunction.
250  __ movd(xmm0, eax);
251
252  // Set up pointer to first argument (skip receiver).
253  __ lea(edi, Operand(ebp, StandardFrameConstants::kCallerSPOffset +
254                               kSystemPointerSize));
255
256  // Restore argument count.
257  __ mov(eax, Operand(ebp, ConstructFrameConstants::kLengthOffset));
258  __ SmiUntag(eax);
259
260  // Check if we have enough stack space to push all arguments.
261  // Argument count in eax. Clobbers ecx.
262  Label stack_overflow;
263  __ StackOverflowCheck(eax, ecx, &stack_overflow);
264
265  // TODO(victorgomes): When the arguments adaptor is completely removed, we
266  // should get the formal parameter count and copy the arguments in its
267  // correct position (including any undefined), instead of delaying this to
268  // InvokeFunction.
269
270  // Copy arguments to the expression stack.
271  // edi: Pointer to start of arguments.
272  // eax: Number of arguments.
273  Generate_PushArguments(masm, edi, eax, ecx, no_reg,
274                         ArgumentsElementType::kRaw);
275
276  // Push implicit receiver.
277  __ movd(ecx, xmm0);
278  __ Push(ecx);
279
280  // Restore and and call the constructor function.
281  __ mov(edi, Operand(ebp, ConstructFrameConstants::kConstructorOffset));
282  __ InvokeFunction(edi, edx, eax, InvokeType::kCall);
283
284  // ----------- S t a t e -------------
285  //  --                eax: constructor result
286  //  -- sp[0*kSystemPointerSize]: implicit receiver
287  //  -- sp[1*kSystemPointerSize]: padding
288  //  -- sp[2*kSystemPointerSize]: constructor function
289  //  -- sp[3*kSystemPointerSize]: number of arguments
290  //  -- sp[4*kSystemPointerSize]: context
291  // -----------------------------------
292
293  // Store offset of return address for deoptimizer.
294  masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset(
295      masm->pc_offset());
296
297  // If the result is an object (in the ECMA sense), we should get rid
298  // of the receiver and use the result; see ECMA-262 section 13.2.2-7
299  // on page 74.
300
301  Label check_result, use_receiver, do_throw, leave_and_return;
302  // If the result is undefined, we jump out to using the implicit receiver.
303  __ JumpIfNotRoot(eax, RootIndex::kUndefinedValue, &check_result,
304                   Label::kNear);
305
306  // Throw away the result of the constructor invocation and use the
307  // on-stack receiver as the result.
308  __ bind(&use_receiver);
309  __ mov(eax, Operand(esp, 0 * kSystemPointerSize));
310  __ JumpIfRoot(eax, RootIndex::kTheHoleValue, &do_throw);
311
312  __ bind(&leave_and_return);
313  // Restore smi-tagged arguments count from the frame.
314  __ mov(edx, Operand(ebp, ConstructFrameConstants::kLengthOffset));
315  __ LeaveFrame(StackFrame::CONSTRUCT);
316
317  // Remove caller arguments from the stack and return.
318  __ DropArguments(edx, ecx, TurboAssembler::kCountIsSmi,
319                   TurboAssembler::kCountIncludesReceiver);
320  __ ret(0);
321
322  // Otherwise we do a smi check and fall through to check if the return value
323  // is a valid receiver.
324  __ bind(&check_result);
325
326  // If the result is a smi, it is *not* an object in the ECMA sense.
327  __ JumpIfSmi(eax, &use_receiver, Label::kNear);
328
329  // If the type of the result (stored in its map) is less than
330  // FIRST_JS_RECEIVER_TYPE, it is not an object in the ECMA sense.
331  STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
332  __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, ecx);
333  __ j(above_equal, &leave_and_return, Label::kNear);
334  __ jmp(&use_receiver, Label::kNear);
335
336  __ bind(&do_throw);
337  // Restore context from the frame.
338  __ mov(esi, Operand(ebp, ConstructFrameConstants::kContextOffset));
339  __ CallRuntime(Runtime::kThrowConstructorReturnedNonObject);
340  // This should be unreachable.
341  __ int3();
342
343  __ bind(&stack_overflow);
344  // Restore context from the frame.
345  __ mov(esi, Operand(ebp, ConstructFrameConstants::kContextOffset));
346  __ CallRuntime(Runtime::kThrowStackOverflow);
347  // This should be unreachable.
348  __ int3();
349}
350
351void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
352  Generate_JSBuiltinsConstructStubHelper(masm);
353}
354
355void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
356  FrameScope scope(masm, StackFrame::INTERNAL);
357  __ push(edi);
358  __ CallRuntime(Runtime::kThrowConstructedNonConstructable);
359}
360
361namespace {
362
363// Called with the native C calling convention. The corresponding function
364// signature is either:
365//
366//   using JSEntryFunction = GeneratedCode<Address(
367//       Address root_register_value, Address new_target, Address target,
368//       Address receiver, intptr_t argc, Address** argv)>;
369// or
370//   using JSEntryFunction = GeneratedCode<Address(
371//       Address root_register_value, MicrotaskQueue* microtask_queue)>;
372void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
373                             Builtin entry_trampoline) {
374  Label invoke, handler_entry, exit;
375  Label not_outermost_js, not_outermost_js_2;
376
377  {
378    NoRootArrayScope uninitialized_root_register(masm);
379
380    // Set up frame.
381    __ push(ebp);
382    __ mov(ebp, esp);
383
384    // Push marker in two places.
385    __ push(Immediate(StackFrame::TypeToMarker(type)));
386    // Reserve a slot for the context. It is filled after the root register has
387    // been set up.
388    __ AllocateStackSpace(kSystemPointerSize);
389    // Save callee-saved registers (C calling conventions).
390    __ push(edi);
391    __ push(esi);
392    __ push(ebx);
393
394    // Initialize the root register based on the given Isolate* argument.
395    // C calling convention. The first argument is passed on the stack.
396    __ mov(kRootRegister,
397           Operand(ebp, EntryFrameConstants::kRootRegisterValueOffset));
398  }
399
400  // Save copies of the top frame descriptor on the stack.
401  ExternalReference c_entry_fp = ExternalReference::Create(
402      IsolateAddressId::kCEntryFPAddress, masm->isolate());
403  __ push(__ ExternalReferenceAsOperand(c_entry_fp, edi));
404
405  // Clear c_entry_fp, now we've pushed its previous value to the stack.
406  // If the c_entry_fp is not already zero and we don't clear it, the
407  // SafeStackFrameIterator will assume we are executing C++ and miss the JS
408  // frames on top.
409  __ mov(__ ExternalReferenceAsOperand(c_entry_fp, edi), Immediate(0));
410
411  // Store the context address in the previously-reserved slot.
412  ExternalReference context_address = ExternalReference::Create(
413      IsolateAddressId::kContextAddress, masm->isolate());
414  __ mov(edi, __ ExternalReferenceAsOperand(context_address, edi));
415  static constexpr int kOffsetToContextSlot = -2 * kSystemPointerSize;
416  __ mov(Operand(ebp, kOffsetToContextSlot), edi);
417
418  // If this is the outermost JS call, set js_entry_sp value.
419  ExternalReference js_entry_sp = ExternalReference::Create(
420      IsolateAddressId::kJSEntrySPAddress, masm->isolate());
421  __ cmp(__ ExternalReferenceAsOperand(js_entry_sp, edi), Immediate(0));
422  __ j(not_equal, &not_outermost_js, Label::kNear);
423  __ mov(__ ExternalReferenceAsOperand(js_entry_sp, edi), ebp);
424  __ push(Immediate(StackFrame::OUTERMOST_JSENTRY_FRAME));
425  __ jmp(&invoke, Label::kNear);
426  __ bind(&not_outermost_js);
427  __ push(Immediate(StackFrame::INNER_JSENTRY_FRAME));
428
429  // Jump to a faked try block that does the invoke, with a faked catch
430  // block that sets the pending exception.
431  __ jmp(&invoke);
432  __ bind(&handler_entry);
433
434  // Store the current pc as the handler offset. It's used later to create the
435  // handler table.
436  masm->isolate()->builtins()->SetJSEntryHandlerOffset(handler_entry.pos());
437
438  // Caught exception: Store result (exception) in the pending exception
439  // field in the JSEnv and return a failure sentinel.
440  ExternalReference pending_exception = ExternalReference::Create(
441      IsolateAddressId::kPendingExceptionAddress, masm->isolate());
442  __ mov(__ ExternalReferenceAsOperand(pending_exception, edi), eax);
443  __ Move(eax, masm->isolate()->factory()->exception());
444  __ jmp(&exit);
445
446  // Invoke: Link this frame into the handler chain.
447  __ bind(&invoke);
448  __ PushStackHandler(edi);
449
450  // Invoke the function by calling through JS entry trampoline builtin and
451  // pop the faked function when we return.
452  Handle<Code> trampoline_code =
453      masm->isolate()->builtins()->code_handle(entry_trampoline);
454  __ Call(trampoline_code, RelocInfo::CODE_TARGET);
455
456  // Unlink this frame from the handler chain.
457  __ PopStackHandler(edi);
458
459  __ bind(&exit);
460
461  // Check if the current stack frame is marked as the outermost JS frame.
462  __ pop(edi);
463  __ cmp(edi, Immediate(StackFrame::OUTERMOST_JSENTRY_FRAME));
464  __ j(not_equal, &not_outermost_js_2);
465  __ mov(__ ExternalReferenceAsOperand(js_entry_sp, edi), Immediate(0));
466  __ bind(&not_outermost_js_2);
467
468  // Restore the top frame descriptor from the stack.
469  __ pop(__ ExternalReferenceAsOperand(c_entry_fp, edi));
470
471  // Restore callee-saved registers (C calling conventions).
472  __ pop(ebx);
473  __ pop(esi);
474  __ pop(edi);
475  __ add(esp, Immediate(2 * kSystemPointerSize));  // remove markers
476
477  // Restore frame pointer and return.
478  __ pop(ebp);
479  __ ret(0);
480}
481
482}  // namespace
483
484void Builtins::Generate_JSEntry(MacroAssembler* masm) {
485  Generate_JSEntryVariant(masm, StackFrame::ENTRY, Builtin::kJSEntryTrampoline);
486}
487
488void Builtins::Generate_JSConstructEntry(MacroAssembler* masm) {
489  Generate_JSEntryVariant(masm, StackFrame::CONSTRUCT_ENTRY,
490                          Builtin::kJSConstructEntryTrampoline);
491}
492
493void Builtins::Generate_JSRunMicrotasksEntry(MacroAssembler* masm) {
494  Generate_JSEntryVariant(masm, StackFrame::ENTRY,
495                          Builtin::kRunMicrotasksTrampoline);
496}
497
498static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
499                                             bool is_construct) {
500  {
501    FrameScope scope(masm, StackFrame::INTERNAL);
502
503    const Register scratch1 = edx;
504    const Register scratch2 = edi;
505
506    // Setup the context (we need to use the caller context from the isolate).
507    ExternalReference context_address = ExternalReference::Create(
508        IsolateAddressId::kContextAddress, masm->isolate());
509    __ mov(esi, __ ExternalReferenceAsOperand(context_address, scratch1));
510
511    // Load the previous frame pointer (edx) to access C arguments
512    __ mov(scratch1, Operand(ebp, 0));
513
514    // Push the function.
515    __ push(Operand(scratch1, EntryFrameConstants::kFunctionArgOffset));
516
517    // Load the number of arguments and setup pointer to the arguments.
518    __ mov(eax, Operand(scratch1, EntryFrameConstants::kArgcOffset));
519    __ mov(scratch1, Operand(scratch1, EntryFrameConstants::kArgvOffset));
520
521    // Check if we have enough stack space to push all arguments.
522    // Argument count in eax. Clobbers ecx.
523    Label enough_stack_space, stack_overflow;
524    __ StackOverflowCheck(eax, ecx, &stack_overflow);
525    __ jmp(&enough_stack_space);
526
527    __ bind(&stack_overflow);
528    __ CallRuntime(Runtime::kThrowStackOverflow);
529    // This should be unreachable.
530    __ int3();
531
532    __ bind(&enough_stack_space);
533
534    // Copy arguments to the stack.
535    // scratch1 (edx): Pointer to start of arguments.
536    // eax: Number of arguments.
537    Generate_PushArguments(masm, scratch1, eax, ecx, scratch2,
538                           ArgumentsElementType::kHandle);
539
540    // Load the previous frame pointer to access C arguments
541    __ mov(scratch2, Operand(ebp, 0));
542
543    // Push the receiver onto the stack.
544    __ push(Operand(scratch2, EntryFrameConstants::kReceiverArgOffset));
545
546    // Get the new.target and function from the frame.
547    __ mov(edx, Operand(scratch2, EntryFrameConstants::kNewTargetArgOffset));
548    __ mov(edi, Operand(scratch2, EntryFrameConstants::kFunctionArgOffset));
549
550    // Invoke the code.
551    Handle<Code> builtin = is_construct
552                               ? BUILTIN_CODE(masm->isolate(), Construct)
553                               : masm->isolate()->builtins()->Call();
554    __ Call(builtin, RelocInfo::CODE_TARGET);
555
556    // Exit the internal frame. Notice that this also removes the empty.
557    // context and the function left on the stack by the code
558    // invocation.
559  }
560  __ ret(0);
561}
562
563void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
564  Generate_JSEntryTrampolineHelper(masm, false);
565}
566
567void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
568  Generate_JSEntryTrampolineHelper(masm, true);
569}
570
571void Builtins::Generate_RunMicrotasksTrampoline(MacroAssembler* masm) {
572  // This expects two C++ function parameters passed by Invoke() in
573  // execution.cc.
574  //   r1: microtask_queue
575  __ mov(RunMicrotasksDescriptor::MicrotaskQueueRegister(),
576         Operand(ebp, EntryFrameConstants::kMicrotaskQueueArgOffset));
577  __ Jump(BUILTIN_CODE(masm->isolate(), RunMicrotasks), RelocInfo::CODE_TARGET);
578}
579
580static void GetSharedFunctionInfoBytecode(MacroAssembler* masm,
581                                          Register sfi_data,
582                                          Register scratch1) {
583  Label done;
584
585  __ CmpObjectType(sfi_data, INTERPRETER_DATA_TYPE, scratch1);
586  __ j(not_equal, &done, Label::kNear);
587  __ mov(sfi_data,
588         FieldOperand(sfi_data, InterpreterData::kBytecodeArrayOffset));
589
590  __ bind(&done);
591}
592
593static void AssertCodeIsBaseline(MacroAssembler* masm, Register code,
594                                 Register scratch) {
595  DCHECK(!AreAliased(code, scratch));
596  // Verify that the code kind is baseline code via the CodeKind.
597  __ mov(scratch, FieldOperand(code, Code::kFlagsOffset));
598  __ DecodeField<Code::KindField>(scratch);
599  __ cmp(scratch, Immediate(static_cast<int>(CodeKind::BASELINE)));
600  __ Assert(equal, AbortReason::kExpectedBaselineData);
601}
602
603static void GetSharedFunctionInfoBytecodeOrBaseline(MacroAssembler* masm,
604                                                    Register sfi_data,
605                                                    Register scratch1,
606                                                    Label* is_baseline) {
607  ASM_CODE_COMMENT(masm);
608  Label done;
609  __ LoadMap(scratch1, sfi_data);
610
611  __ CmpInstanceType(scratch1, CODET_TYPE);
612  if (FLAG_debug_code) {
613    Label not_baseline;
614    __ j(not_equal, &not_baseline);
615    AssertCodeIsBaseline(masm, sfi_data, scratch1);
616    __ j(equal, is_baseline);
617    __ bind(&not_baseline);
618  } else {
619    __ j(equal, is_baseline);
620  }
621
622  __ CmpInstanceType(scratch1, INTERPRETER_DATA_TYPE);
623  __ j(not_equal, &done, Label::kNear);
624
625  __ mov(sfi_data,
626         FieldOperand(sfi_data, InterpreterData::kBytecodeArrayOffset));
627
628  __ bind(&done);
629}
630
631// static
632void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
633  // ----------- S t a t e -------------
634  //  -- eax    : the value to pass to the generator
635  //  -- edx    : the JSGeneratorObject to resume
636  //  -- esp[0] : return address
637  // -----------------------------------
638  // Store input value into generator object.
639  __ mov(FieldOperand(edx, JSGeneratorObject::kInputOrDebugPosOffset), eax);
640  Register object = WriteBarrierDescriptor::ObjectRegister();
641  __ mov(object, edx);
642  __ RecordWriteField(object, JSGeneratorObject::kInputOrDebugPosOffset, eax,
643                      WriteBarrierDescriptor::SlotAddressRegister(),
644                      SaveFPRegsMode::kIgnore);
645  // Check that edx is still valid, RecordWrite might have clobbered it.
646  __ AssertGeneratorObject(edx);
647
648  // Load suspended function and context.
649  __ mov(edi, FieldOperand(edx, JSGeneratorObject::kFunctionOffset));
650  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
651
652  // Flood function if we are stepping.
653  Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator;
654  Label stepping_prepared;
655  ExternalReference debug_hook =
656      ExternalReference::debug_hook_on_function_call_address(masm->isolate());
657  __ cmpb(__ ExternalReferenceAsOperand(debug_hook, ecx), Immediate(0));
658  __ j(not_equal, &prepare_step_in_if_stepping);
659
660  // Flood function if we need to continue stepping in the suspended generator.
661  ExternalReference debug_suspended_generator =
662      ExternalReference::debug_suspended_generator_address(masm->isolate());
663  __ cmp(edx, __ ExternalReferenceAsOperand(debug_suspended_generator, ecx));
664  __ j(equal, &prepare_step_in_suspended_generator);
665  __ bind(&stepping_prepared);
666
667  // Check the stack for overflow. We are not trying to catch interruptions
668  // (i.e. debug break and preemption) here, so check the "real stack limit".
669  Label stack_overflow;
670  __ CompareStackLimit(esp, StackLimitKind::kRealStackLimit);
671  __ j(below, &stack_overflow);
672
673  // Pop return address.
674  __ PopReturnAddressTo(eax);
675
676  // ----------- S t a t e -------------
677  //  -- eax    : return address
678  //  -- edx    : the JSGeneratorObject to resume
679  //  -- edi    : generator function
680  //  -- esi    : generator context
681  // -----------------------------------
682
683  {
684    __ movd(xmm0, ebx);
685
686    // Copy the function arguments from the generator object's register file.
687    __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
688    __ movzx_w(ecx, FieldOperand(
689                        ecx, SharedFunctionInfo::kFormalParameterCountOffset));
690    __ dec(ecx);  // Exclude receiver.
691    __ mov(ebx,
692           FieldOperand(edx, JSGeneratorObject::kParametersAndRegistersOffset));
693    {
694      Label done_loop, loop;
695      __ bind(&loop);
696      __ dec(ecx);
697      __ j(less, &done_loop);
698      __ Push(
699          FieldOperand(ebx, ecx, times_tagged_size, FixedArray::kHeaderSize));
700      __ jmp(&loop);
701      __ bind(&done_loop);
702    }
703
704    // Push receiver.
705    __ Push(FieldOperand(edx, JSGeneratorObject::kReceiverOffset));
706
707    // Restore registers.
708    __ mov(edi, FieldOperand(edx, JSGeneratorObject::kFunctionOffset));
709    __ movd(ebx, xmm0);
710  }
711
712  // Underlying function needs to have bytecode available.
713  if (FLAG_debug_code) {
714    Label is_baseline, ok;
715    __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
716    __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kFunctionDataOffset));
717    __ Push(eax);
718    GetSharedFunctionInfoBytecodeOrBaseline(masm, ecx, eax, &is_baseline);
719    __ Pop(eax);
720
721    __ CmpObjectType(ecx, BYTECODE_ARRAY_TYPE, ecx);
722    __ Assert(equal, AbortReason::kMissingBytecodeArray);
723    __ jmp(&ok);
724
725    __ bind(&is_baseline);
726    __ Pop(eax);
727    __ CmpObjectType(ecx, CODET_TYPE, ecx);
728    __ Assert(equal, AbortReason::kMissingBytecodeArray);
729
730    __ bind(&ok);
731  }
732
733  // Resume (Ignition/TurboFan) generator object.
734  {
735    __ PushReturnAddressFrom(eax);
736    __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
737    __ movzx_w(eax, FieldOperand(
738                        eax, SharedFunctionInfo::kFormalParameterCountOffset));
739    // We abuse new.target both to indicate that this is a resume call and to
740    // pass in the generator object.  In ordinary calls, new.target is always
741    // undefined because generator functions are non-constructable.
742    static_assert(kJavaScriptCallCodeStartRegister == ecx, "ABI mismatch");
743    __ mov(ecx, FieldOperand(edi, JSFunction::kCodeOffset));
744    __ JumpCodeObject(ecx);
745  }
746
747  __ bind(&prepare_step_in_if_stepping);
748  {
749    FrameScope scope(masm, StackFrame::INTERNAL);
750    __ Push(edx);
751    __ Push(edi);
752    // Push hole as receiver since we do not use it for stepping.
753    __ PushRoot(RootIndex::kTheHoleValue);
754    __ CallRuntime(Runtime::kDebugOnFunctionCall);
755    __ Pop(edx);
756    __ mov(edi, FieldOperand(edx, JSGeneratorObject::kFunctionOffset));
757  }
758  __ jmp(&stepping_prepared);
759
760  __ bind(&prepare_step_in_suspended_generator);
761  {
762    FrameScope scope(masm, StackFrame::INTERNAL);
763    __ Push(edx);
764    __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator);
765    __ Pop(edx);
766    __ mov(edi, FieldOperand(edx, JSGeneratorObject::kFunctionOffset));
767  }
768  __ jmp(&stepping_prepared);
769
770  __ bind(&stack_overflow);
771  {
772    FrameScope scope(masm, StackFrame::INTERNAL);
773    __ CallRuntime(Runtime::kThrowStackOverflow);
774    __ int3();  // This should be unreachable.
775  }
776}
777
778static void ReplaceClosureCodeWithOptimizedCode(MacroAssembler* masm,
779                                                Register optimized_code,
780                                                Register closure,
781                                                Register value,
782                                                Register slot_address) {
783  ASM_CODE_COMMENT(masm);
784  // Store the optimized code in the closure.
785  __ mov(FieldOperand(closure, JSFunction::kCodeOffset), optimized_code);
786  __ mov(value, optimized_code);  // Write barrier clobbers slot_address below.
787  __ RecordWriteField(closure, JSFunction::kCodeOffset, value, slot_address,
788                      SaveFPRegsMode::kIgnore, RememberedSetAction::kOmit,
789                      SmiCheck::kOmit);
790}
791
792static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch1,
793                                  Register scratch2) {
794  ASM_CODE_COMMENT(masm);
795  Register params_size = scratch1;
796  // Get the size of the formal parameters (in bytes).
797  __ mov(params_size,
798         Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp));
799  __ mov(params_size,
800         FieldOperand(params_size, BytecodeArray::kParameterSizeOffset));
801
802  Register actual_params_size = scratch2;
803  // Compute the size of the actual parameters (in bytes).
804  __ mov(actual_params_size, Operand(ebp, StandardFrameConstants::kArgCOffset));
805  __ lea(actual_params_size,
806         Operand(actual_params_size, times_system_pointer_size, 0));
807
808  // If actual is bigger than formal, then we should use it to free up the stack
809  // arguments.
810  Label corrected_args_count;
811  __ cmp(params_size, actual_params_size);
812  __ j(greater_equal, &corrected_args_count, Label::kNear);
813  __ mov(params_size, actual_params_size);
814  __ bind(&corrected_args_count);
815
816  // Leave the frame (also dropping the register file).
817  __ leave();
818
819  // Drop receiver + arguments.
820  __ DropArguments(params_size, scratch2, TurboAssembler::kCountIsBytes,
821                   TurboAssembler::kCountIncludesReceiver);
822}
823
824// Tail-call |function_id| if |actual_state| == |expected_state|
825static void TailCallRuntimeIfStateEquals(MacroAssembler* masm,
826                                         Register actual_state,
827                                         TieringState expected_state,
828                                         Runtime::FunctionId function_id) {
829  ASM_CODE_COMMENT(masm);
830  Label no_match;
831  __ cmp(actual_state, static_cast<int>(expected_state));
832  __ j(not_equal, &no_match, Label::kNear);
833  GenerateTailCallToReturnedCode(masm, function_id);
834  __ bind(&no_match);
835}
836
837static void TailCallOptimizedCodeSlot(MacroAssembler* masm,
838                                      Register optimized_code_entry) {
839  // ----------- S t a t e -------------
840  //  -- eax : actual argument count
841  //  -- edx : new target (preserved for callee if needed, and caller)
842  //  -- edi : target function (preserved for callee if needed, and caller)
843  // -----------------------------------
844  ASM_CODE_COMMENT(masm);
845  DCHECK(!AreAliased(edx, edi, optimized_code_entry));
846
847  Register closure = edi;
848  __ Push(eax);
849  __ Push(edx);
850
851  Label heal_optimized_code_slot;
852
853  // If the optimized code is cleared, go to runtime to update the optimization
854  // marker field.
855  __ LoadWeakValue(optimized_code_entry, &heal_optimized_code_slot);
856
857  // Check if the optimized code is marked for deopt. If it is, bailout to a
858  // given label.
859  __ mov(eax,
860         FieldOperand(optimized_code_entry, Code::kCodeDataContainerOffset));
861  __ test(FieldOperand(eax, CodeDataContainer::kKindSpecificFlagsOffset),
862          Immediate(1 << Code::kMarkedForDeoptimizationBit));
863  __ j(not_zero, &heal_optimized_code_slot);
864
865  // Optimized code is good, get it into the closure and link the closure
866  // into the optimized functions list, then tail call the optimized code.
867  __ Push(optimized_code_entry);
868  ReplaceClosureCodeWithOptimizedCode(masm, optimized_code_entry, closure, edx,
869                                      ecx);
870  static_assert(kJavaScriptCallCodeStartRegister == ecx, "ABI mismatch");
871  __ Pop(optimized_code_entry);
872  __ LoadCodeObjectEntry(ecx, optimized_code_entry);
873  __ Pop(edx);
874  __ Pop(eax);
875  __ jmp(ecx);
876
877  // Optimized code slot contains deoptimized code or code is cleared and
878  // optimized code marker isn't updated. Evict the code, update the marker
879  // and re-enter the closure's code.
880  __ bind(&heal_optimized_code_slot);
881  __ Pop(edx);
882  __ Pop(eax);
883  GenerateTailCallToReturnedCode(masm, Runtime::kHealOptimizedCodeSlot);
884}
885
886static void MaybeOptimizeCode(MacroAssembler* masm, Register tiering_state) {
887  // ----------- S t a t e -------------
888  //  -- eax : actual argument count
889  //  -- edx : new target (preserved for callee if needed, and caller)
890  //  -- edi : target function (preserved for callee if needed, and caller)
891  //  -- tiering_state : a Smi containing a non-zero tiering state.
892  // -----------------------------------
893  ASM_CODE_COMMENT(masm);
894  DCHECK(!AreAliased(edx, edi, tiering_state));
895
896  TailCallRuntimeIfStateEquals(masm, tiering_state,
897                               TieringState::kRequestTurbofan_Synchronous,
898                               Runtime::kCompileTurbofan_Synchronous);
899  TailCallRuntimeIfStateEquals(masm, tiering_state,
900                               TieringState::kRequestTurbofan_Concurrent,
901                               Runtime::kCompileTurbofan_Concurrent);
902
903  __ int3();
904}
905
906// Advance the current bytecode offset. This simulates what all bytecode
907// handlers do upon completion of the underlying operation. Will bail out to a
908// label if the bytecode (without prefix) is a return bytecode. Will not advance
909// the bytecode offset if the current bytecode is a JumpLoop, instead just
910// re-executing the JumpLoop to jump to the correct bytecode.
911static void AdvanceBytecodeOffsetOrReturn(MacroAssembler* masm,
912                                          Register bytecode_array,
913                                          Register bytecode_offset,
914                                          Register scratch1, Register scratch2,
915                                          Register scratch3, Label* if_return) {
916  ASM_CODE_COMMENT(masm);
917  Register bytecode_size_table = scratch1;
918  Register bytecode = scratch2;
919
920  // The bytecode offset value will be increased by one in wide and extra wide
921  // cases. In the case of having a wide or extra wide JumpLoop bytecode, we
922  // will restore the original bytecode. In order to simplify the code, we have
923  // a backup of it.
924  Register original_bytecode_offset = scratch3;
925  DCHECK(!AreAliased(bytecode_array, bytecode_offset, bytecode_size_table,
926                     bytecode, original_bytecode_offset));
927  __ Move(bytecode_size_table,
928          Immediate(ExternalReference::bytecode_size_table_address()));
929
930  // Load the current bytecode.
931  __ movzx_b(bytecode, Operand(bytecode_array, bytecode_offset, times_1, 0));
932  __ Move(original_bytecode_offset, bytecode_offset);
933
934  // Check if the bytecode is a Wide or ExtraWide prefix bytecode.
935  Label process_bytecode, extra_wide;
936  STATIC_ASSERT(0 == static_cast<int>(interpreter::Bytecode::kWide));
937  STATIC_ASSERT(1 == static_cast<int>(interpreter::Bytecode::kExtraWide));
938  STATIC_ASSERT(2 == static_cast<int>(interpreter::Bytecode::kDebugBreakWide));
939  STATIC_ASSERT(3 ==
940                static_cast<int>(interpreter::Bytecode::kDebugBreakExtraWide));
941  __ cmp(bytecode, Immediate(0x3));
942  __ j(above, &process_bytecode, Label::kNear);
943  // The code to load the next bytecode is common to both wide and extra wide.
944  // We can hoist them up here. inc has to happen before test since it
945  // modifies the ZF flag.
946  __ inc(bytecode_offset);
947  __ test(bytecode, Immediate(0x1));
948  __ movzx_b(bytecode, Operand(bytecode_array, bytecode_offset, times_1, 0));
949  __ j(not_equal, &extra_wide, Label::kNear);
950
951  // Load the next bytecode and update table to the wide scaled table.
952  __ add(bytecode_size_table,
953         Immediate(kByteSize * interpreter::Bytecodes::kBytecodeCount));
954  __ jmp(&process_bytecode, Label::kNear);
955
956  __ bind(&extra_wide);
957  // Update table to the extra wide scaled table.
958  __ add(bytecode_size_table,
959         Immediate(2 * kByteSize * interpreter::Bytecodes::kBytecodeCount));
960
961  __ bind(&process_bytecode);
962
963// Bailout to the return label if this is a return bytecode.
964#define JUMP_IF_EQUAL(NAME)                                            \
965  __ cmp(bytecode,                                                     \
966         Immediate(static_cast<int>(interpreter::Bytecode::k##NAME))); \
967  __ j(equal, if_return);
968  RETURN_BYTECODE_LIST(JUMP_IF_EQUAL)
969#undef JUMP_IF_EQUAL
970
971  // If this is a JumpLoop, re-execute it to perform the jump to the beginning
972  // of the loop.
973  Label end, not_jump_loop;
974  __ cmp(bytecode,
975         Immediate(static_cast<int>(interpreter::Bytecode::kJumpLoop)));
976  __ j(not_equal, &not_jump_loop, Label::kNear);
977  // If this is a wide or extra wide JumpLoop, we need to restore the original
978  // bytecode_offset since we might have increased it to skip the wide /
979  // extra-wide prefix bytecode.
980  __ Move(bytecode_offset, original_bytecode_offset);
981  __ jmp(&end, Label::kNear);
982
983  __ bind(&not_jump_loop);
984  // Otherwise, load the size of the current bytecode and advance the offset.
985  __ movzx_b(bytecode_size_table,
986             Operand(bytecode_size_table, bytecode, times_1, 0));
987  __ add(bytecode_offset, bytecode_size_table);
988
989  __ bind(&end);
990}
991
992// Read off the optimization state in the feedback vector and check if there
993// is optimized code or a tiering state that needs to be processed.
994// Registers optimization_state and feedback_vector must be aliased.
995static void LoadTieringStateAndJumpIfNeedsProcessing(
996    MacroAssembler* masm, Register optimization_state,
997    XMMRegister saved_feedback_vector, Label* has_optimized_code_or_state) {
998  ASM_CODE_COMMENT(masm);
999  Register feedback_vector = optimization_state;
1000
1001  // Store feedback_vector. We may need it if we need to load the optimize code
1002  // slot entry.
1003  __ movd(saved_feedback_vector, feedback_vector);
1004  __ mov(optimization_state,
1005         FieldOperand(feedback_vector, FeedbackVector::kFlagsOffset));
1006
1007  // Check if there is optimized code or a tiering state that needes to be
1008  // processed.
1009  __ test(optimization_state,
1010          Immediate(
1011              FeedbackVector::kHasOptimizedCodeOrTieringStateIsAnyRequestMask));
1012  __ j(not_zero, has_optimized_code_or_state);
1013}
1014
1015static void MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(
1016    MacroAssembler* masm, Register optimization_state,
1017    XMMRegister saved_feedback_vector) {
1018  ASM_CODE_COMMENT(masm);
1019  Label maybe_has_optimized_code;
1020  // Check if optimized code is available
1021  __ test(optimization_state,
1022          Immediate(FeedbackVector::kTieringStateIsAnyRequestMask));
1023  __ j(zero, &maybe_has_optimized_code);
1024
1025  Register tiering_state = optimization_state;
1026  __ DecodeField<FeedbackVector::TieringStateBits>(tiering_state);
1027  MaybeOptimizeCode(masm, tiering_state);
1028
1029  __ bind(&maybe_has_optimized_code);
1030  Register optimized_code_entry = tiering_state;
1031  Register feedback_vector = tiering_state;
1032  __ movd(feedback_vector, saved_feedback_vector);  // Restore feedback vector.
1033  __ mov(
1034      optimized_code_entry,
1035      FieldOperand(feedback_vector, FeedbackVector::kMaybeOptimizedCodeOffset));
1036  TailCallOptimizedCodeSlot(masm, optimized_code_entry);
1037}
1038
1039namespace {
1040
1041void ResetBytecodeAgeAndOsrState(MacroAssembler* masm,
1042                                 Register bytecode_array) {
1043  // Reset the bytecode age and OSR state (optimized to a single write).
1044  static_assert(BytecodeArray::kOsrStateAndBytecodeAgeAreContiguous32Bits);
1045  STATIC_ASSERT(BytecodeArray::kNoAgeBytecodeAge == 0);
1046  __ mov(FieldOperand(bytecode_array,
1047                      BytecodeArray::kOsrUrgencyAndInstallTargetOffset),
1048         Immediate(0));
1049}
1050
1051}  // namespace
1052
1053// Generate code for entering a JS function with the interpreter.
1054// On entry to the function the receiver and arguments have been pushed on the
1055// stack left to right.
1056//
1057// The live registers are:
1058//   o eax: actual argument count
1059//   o edi: the JS function object being called
1060//   o edx: the incoming new target or generator object
1061//   o esi: our context
1062//   o ebp: the caller's frame pointer
1063//   o esp: stack pointer (pointing to return address)
1064//
1065// The function builds an interpreter frame. See InterpreterFrameConstants in
1066// frame-constants.h for its layout.
1067void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
1068  Register closure = edi;
1069
1070  __ movd(xmm0, eax);  // Spill actual argument count.
1071
1072  // The bytecode array could have been flushed from the shared function info,
1073  // if so, call into CompileLazy.
1074  __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1075  __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kFunctionDataOffset));
1076
1077  Label is_baseline;
1078  GetSharedFunctionInfoBytecodeOrBaseline(masm, ecx, eax, &is_baseline);
1079
1080  Label compile_lazy;
1081  __ CmpObjectType(ecx, BYTECODE_ARRAY_TYPE, eax);
1082  __ j(not_equal, &compile_lazy);
1083
1084  Register feedback_vector = ecx;
1085  Label push_stack_frame;
1086  // Load feedback vector and check if it is valid. If valid, check for
1087  // optimized code and update invocation count. Otherwise, setup the stack
1088  // frame.
1089  __ mov(feedback_vector,
1090         FieldOperand(closure, JSFunction::kFeedbackCellOffset));
1091  __ mov(feedback_vector, FieldOperand(feedback_vector, Cell::kValueOffset));
1092  __ mov(eax, FieldOperand(feedback_vector, HeapObject::kMapOffset));
1093  __ CmpInstanceType(eax, FEEDBACK_VECTOR_TYPE);
1094  __ j(not_equal, &push_stack_frame);
1095
1096  // Load the optimization state from the feedback vector and re-use the
1097  // register.
1098  Label has_optimized_code_or_state;
1099  Register optimization_state = ecx;
1100  LoadTieringStateAndJumpIfNeedsProcessing(masm, optimization_state, xmm1,
1101                                           &has_optimized_code_or_state);
1102
1103  Label not_optimized;
1104  __ bind(&not_optimized);
1105
1106  // Load the feedback vector and increment the invocation count.
1107  __ mov(feedback_vector,
1108         FieldOperand(closure, JSFunction::kFeedbackCellOffset));
1109  __ mov(feedback_vector, FieldOperand(feedback_vector, Cell::kValueOffset));
1110  __ inc(FieldOperand(feedback_vector, FeedbackVector::kInvocationCountOffset));
1111
1112  // Open a frame scope to indicate that there is a frame on the stack.  The
1113  // MANUAL indicates that the scope shouldn't actually generate code to set
1114  // up the frame (that is done below).
1115  __ bind(&push_stack_frame);
1116  FrameScope frame_scope(masm, StackFrame::MANUAL);
1117  __ push(ebp);  // Caller's frame pointer.
1118  __ mov(ebp, esp);
1119  __ push(kContextRegister);               // Callee's context.
1120  __ push(kJavaScriptCallTargetRegister);  // Callee's JS function.
1121  __ movd(kJavaScriptCallArgCountRegister, xmm0);
1122  __ push(kJavaScriptCallArgCountRegister);  // Actual argument count.
1123
1124  // Get the bytecode array from the function object and load it into
1125  // kInterpreterBytecodeArrayRegister.
1126  __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1127  __ mov(kInterpreterBytecodeArrayRegister,
1128         FieldOperand(eax, SharedFunctionInfo::kFunctionDataOffset));
1129  GetSharedFunctionInfoBytecode(masm, kInterpreterBytecodeArrayRegister, eax);
1130
1131  // Check function data field is actually a BytecodeArray object.
1132  if (FLAG_debug_code) {
1133    __ AssertNotSmi(kInterpreterBytecodeArrayRegister);
1134    __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE,
1135                     eax);
1136    __ Assert(
1137        equal,
1138        AbortReason::kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
1139  }
1140
1141  ResetBytecodeAgeAndOsrState(masm, kInterpreterBytecodeArrayRegister);
1142
1143  // Push bytecode array.
1144  __ push(kInterpreterBytecodeArrayRegister);
1145  // Push Smi tagged initial bytecode array offset.
1146  __ push(Immediate(Smi::FromInt(BytecodeArray::kHeaderSize - kHeapObjectTag)));
1147
1148  // Allocate the local and temporary register file on the stack.
1149  Label stack_overflow;
1150  {
1151    // Load frame size from the BytecodeArray object.
1152    Register frame_size = ecx;
1153    __ mov(frame_size, FieldOperand(kInterpreterBytecodeArrayRegister,
1154                                    BytecodeArray::kFrameSizeOffset));
1155
1156    // Do a stack check to ensure we don't go over the limit.
1157    __ mov(eax, esp);
1158    __ sub(eax, frame_size);
1159    __ CompareStackLimit(eax, StackLimitKind::kRealStackLimit);
1160    __ j(below, &stack_overflow);
1161
1162    // If ok, push undefined as the initial value for all register file entries.
1163    Label loop_header;
1164    Label loop_check;
1165    __ LoadRoot(kInterpreterAccumulatorRegister, RootIndex::kUndefinedValue);
1166    __ jmp(&loop_check);
1167    __ bind(&loop_header);
1168    // TODO(rmcilroy): Consider doing more than one push per loop iteration.
1169    __ push(kInterpreterAccumulatorRegister);
1170    // Continue loop if not done.
1171    __ bind(&loop_check);
1172    __ sub(frame_size, Immediate(kSystemPointerSize));
1173    __ j(greater_equal, &loop_header);
1174  }
1175
1176  // If the bytecode array has a valid incoming new target or generator object
1177  // register, initialize it with incoming value which was passed in edx.
1178  Label no_incoming_new_target_or_generator_register;
1179  __ mov(ecx, FieldOperand(
1180                  kInterpreterBytecodeArrayRegister,
1181                  BytecodeArray::kIncomingNewTargetOrGeneratorRegisterOffset));
1182  __ test(ecx, ecx);
1183  __ j(zero, &no_incoming_new_target_or_generator_register);
1184  __ mov(Operand(ebp, ecx, times_system_pointer_size, 0), edx);
1185  __ bind(&no_incoming_new_target_or_generator_register);
1186
1187  // Perform interrupt stack check.
1188  // TODO(solanes): Merge with the real stack limit check above.
1189  Label stack_check_interrupt, after_stack_check_interrupt;
1190  __ CompareStackLimit(esp, StackLimitKind::kInterruptStackLimit);
1191  __ j(below, &stack_check_interrupt);
1192  __ bind(&after_stack_check_interrupt);
1193
1194  // The accumulator is already loaded with undefined.
1195
1196  __ mov(kInterpreterBytecodeOffsetRegister,
1197         Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
1198
1199  // Load the dispatch table into a register and dispatch to the bytecode
1200  // handler at the current bytecode offset.
1201  Label do_dispatch;
1202  __ bind(&do_dispatch);
1203  __ Move(kInterpreterDispatchTableRegister,
1204          Immediate(ExternalReference::interpreter_dispatch_table_address(
1205              masm->isolate())));
1206  __ movzx_b(ecx, Operand(kInterpreterBytecodeArrayRegister,
1207                          kInterpreterBytecodeOffsetRegister, times_1, 0));
1208  __ mov(kJavaScriptCallCodeStartRegister,
1209         Operand(kInterpreterDispatchTableRegister, ecx,
1210                 times_system_pointer_size, 0));
1211  __ call(kJavaScriptCallCodeStartRegister);
1212  masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
1213
1214  // Any returns to the entry trampoline are either due to the return bytecode
1215  // or the interpreter tail calling a builtin and then a dispatch.
1216
1217  // Get bytecode array and bytecode offset from the stack frame.
1218  __ mov(kInterpreterBytecodeArrayRegister,
1219         Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp));
1220  __ mov(kInterpreterBytecodeOffsetRegister,
1221         Operand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
1222  __ SmiUntag(kInterpreterBytecodeOffsetRegister);
1223
1224  // Either return, or advance to the next bytecode and dispatch.
1225  Label do_return;
1226  __ Push(eax);
1227  AdvanceBytecodeOffsetOrReturn(masm, kInterpreterBytecodeArrayRegister,
1228                                kInterpreterBytecodeOffsetRegister, ecx,
1229                                kInterpreterDispatchTableRegister, eax,
1230                                &do_return);
1231  __ Pop(eax);
1232  __ jmp(&do_dispatch);
1233
1234  __ bind(&do_return);
1235  __ Pop(eax);
1236  // The return value is in eax.
1237  LeaveInterpreterFrame(masm, edx, ecx);
1238  __ ret(0);
1239
1240  __ bind(&stack_check_interrupt);
1241  // Modify the bytecode offset in the stack to be kFunctionEntryBytecodeOffset
1242  // for the call to the StackGuard.
1243  __ mov(Operand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp),
1244         Immediate(Smi::FromInt(BytecodeArray::kHeaderSize - kHeapObjectTag +
1245                                kFunctionEntryBytecodeOffset)));
1246  __ CallRuntime(Runtime::kStackGuard);
1247
1248  // After the call, restore the bytecode array, bytecode offset and accumulator
1249  // registers again. Also, restore the bytecode offset in the stack to its
1250  // previous value.
1251  __ mov(kInterpreterBytecodeArrayRegister,
1252         Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp));
1253  __ mov(kInterpreterBytecodeOffsetRegister,
1254         Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
1255  __ LoadRoot(kInterpreterAccumulatorRegister, RootIndex::kUndefinedValue);
1256
1257  // It's ok to clobber kInterpreterBytecodeOffsetRegister since we are setting
1258  // it again after continuing.
1259  __ SmiTag(kInterpreterBytecodeOffsetRegister);
1260  __ mov(Operand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp),
1261         kInterpreterBytecodeOffsetRegister);
1262
1263  __ jmp(&after_stack_check_interrupt);
1264
1265  __ bind(&has_optimized_code_or_state);
1266  {
1267    // Restore actual argument count.
1268    __ movd(eax, xmm0);
1269    MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(masm, optimization_state,
1270                                                 xmm1);
1271  }
1272
1273  __ bind(&compile_lazy);
1274  // Restore actual argument count.
1275  __ movd(eax, xmm0);
1276  GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
1277
1278  __ bind(&is_baseline);
1279  {
1280    __ movd(xmm2, ecx);  // Save baseline data.
1281    // Load the feedback vector from the closure.
1282    __ mov(feedback_vector,
1283           FieldOperand(closure, JSFunction::kFeedbackCellOffset));
1284    __ mov(feedback_vector, FieldOperand(feedback_vector, Cell::kValueOffset));
1285
1286    Label install_baseline_code;
1287    // Check if feedback vector is valid. If not, call prepare for baseline to
1288    // allocate it.
1289    __ LoadMap(eax, feedback_vector);
1290    __ CmpInstanceType(eax, FEEDBACK_VECTOR_TYPE);
1291    __ j(not_equal, &install_baseline_code);
1292
1293    // Check the tiering state.
1294    LoadTieringStateAndJumpIfNeedsProcessing(masm, optimization_state, xmm1,
1295                                             &has_optimized_code_or_state);
1296
1297    // Load the baseline code into the closure.
1298    __ movd(ecx, xmm2);
1299    static_assert(kJavaScriptCallCodeStartRegister == ecx, "ABI mismatch");
1300    __ push(edx);  // Spill.
1301    __ push(ecx);
1302    __ Push(xmm0, eax);  // Save the argument count (currently in xmm0).
1303    ReplaceClosureCodeWithOptimizedCode(masm, ecx, closure, eax, ecx);
1304    __ pop(eax);  // Restore the argument count.
1305    __ pop(ecx);
1306    __ pop(edx);
1307    __ JumpCodeObject(ecx);
1308
1309    __ bind(&install_baseline_code);
1310    __ movd(eax, xmm0);  // Recover argument count.
1311    GenerateTailCallToReturnedCode(masm, Runtime::kInstallBaselineCode);
1312  }
1313
1314  __ bind(&stack_overflow);
1315  __ CallRuntime(Runtime::kThrowStackOverflow);
1316  __ int3();  // Should not return.
1317}
1318
1319static void GenerateInterpreterPushArgs(MacroAssembler* masm,
1320                                        Register array_limit,
1321                                        Register start_address) {
1322  // ----------- S t a t e -------------
1323  //  -- start_address : Pointer to the last argument in the args array.
1324  //  -- array_limit : Pointer to one before the first argument in the
1325  //                   args array.
1326  // -----------------------------------
1327  ASM_CODE_COMMENT(masm);
1328  Label loop_header, loop_check;
1329  __ jmp(&loop_check);
1330  __ bind(&loop_header);
1331  __ Push(Operand(array_limit, 0));
1332  __ bind(&loop_check);
1333  __ add(array_limit, Immediate(kSystemPointerSize));
1334  __ cmp(array_limit, start_address);
1335  __ j(below_equal, &loop_header, Label::kNear);
1336}
1337
1338// static
1339void Builtins::Generate_InterpreterPushArgsThenCallImpl(
1340    MacroAssembler* masm, ConvertReceiverMode receiver_mode,
1341    InterpreterPushArgsMode mode) {
1342  DCHECK(mode != InterpreterPushArgsMode::kArrayFunction);
1343  // ----------- S t a t e -------------
1344  //  -- eax : the number of arguments
1345  //  -- ecx : the address of the first argument to be pushed. Subsequent
1346  //           arguments should be consecutive above this, in the same order as
1347  //           they are to be pushed onto the stack.
1348  //  -- edi : the target to call (can be any Object).
1349  // -----------------------------------
1350
1351  const Register scratch = edx;
1352  const Register argv = ecx;
1353
1354  Label stack_overflow;
1355  if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
1356    // The spread argument should not be pushed.
1357    __ dec(eax);
1358  }
1359
1360  // Add a stack check before pushing the arguments.
1361  __ StackOverflowCheck(eax, scratch, &stack_overflow, true);
1362  __ movd(xmm0, eax);  // Spill number of arguments.
1363
1364  // Compute the expected number of arguments.
1365  __ mov(scratch, eax);
1366  if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
1367    __ dec(scratch);  // Exclude receiver.
1368  }
1369
1370  // Pop return address to allow tail-call after pushing arguments.
1371  __ PopReturnAddressTo(eax);
1372
1373  // Find the address of the last argument.
1374  __ shl(scratch, kSystemPointerSizeLog2);
1375  __ neg(scratch);
1376  __ add(scratch, argv);
1377
1378  if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
1379    __ movd(xmm1, scratch);
1380    GenerateInterpreterPushArgs(masm, scratch, argv);
1381    // Pass the spread in the register ecx.
1382    __ movd(ecx, xmm1);
1383    __ mov(ecx, Operand(ecx, 0));
1384  } else {
1385    GenerateInterpreterPushArgs(masm, scratch, argv);
1386  }
1387
1388  // Push "undefined" as the receiver arg if we need to.
1389  if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
1390    __ PushRoot(RootIndex::kUndefinedValue);
1391  }
1392
1393  __ PushReturnAddressFrom(eax);
1394  __ movd(eax, xmm0);  // Restore number of arguments.
1395
1396  // Call the target.
1397  if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
1398    __ Jump(BUILTIN_CODE(masm->isolate(), CallWithSpread),
1399            RelocInfo::CODE_TARGET);
1400  } else {
1401    __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny),
1402            RelocInfo::CODE_TARGET);
1403  }
1404
1405  __ bind(&stack_overflow);
1406  {
1407    __ TailCallRuntime(Runtime::kThrowStackOverflow);
1408
1409    // This should be unreachable.
1410    __ int3();
1411  }
1412}
1413
1414namespace {
1415
1416// This function modifies start_addr, and only reads the contents of num_args
1417// register. scratch1 and scratch2 are used as temporary registers.
1418void Generate_InterpreterPushZeroAndArgsAndReturnAddress(
1419    MacroAssembler* masm, Register num_args, Register start_addr,
1420    Register scratch1, Register scratch2, int num_slots_to_move,
1421    Label* stack_overflow) {
1422  // We have to move return address and the temporary registers above it
1423  // before we can copy arguments onto the stack. To achieve this:
1424  // Step 1: Increment the stack pointer by num_args + 1 for receiver (if it is
1425  // not included in argc already). Step 2: Move the return address and values
1426  // around it to the top of stack. Step 3: Copy the arguments into the correct
1427  // locations.
1428  //  current stack    =====>    required stack layout
1429  // |             |            | return addr   | (2) <-- esp (1)
1430  // |             |            | addtl. slot   |
1431  // |             |            | arg N         | (3)
1432  // |             |            | ....          |
1433  // |             |            | arg 1         |
1434  // | return addr | <-- esp    | arg 0         |
1435  // | addtl. slot |            | receiver slot |
1436
1437  // Check for stack overflow before we increment the stack pointer.
1438  __ StackOverflowCheck(num_args, scratch1, stack_overflow, true);
1439
1440  // Step 1 - Update the stack pointer.
1441
1442  __ lea(scratch1, Operand(num_args, times_system_pointer_size, 0));
1443  __ AllocateStackSpace(scratch1);
1444
1445  // Step 2 move return_address and slots around it to the correct locations.
1446  // Move from top to bottom, otherwise we may overwrite when num_args = 0 or 1,
1447  // basically when the source and destination overlap. We at least need one
1448  // extra slot for receiver, so no extra checks are required to avoid copy.
1449  for (int i = 0; i < num_slots_to_move + 1; i++) {
1450    __ mov(scratch1, Operand(esp, num_args, times_system_pointer_size,
1451                             i * kSystemPointerSize));
1452    __ mov(Operand(esp, i * kSystemPointerSize), scratch1);
1453  }
1454
1455  // Step 3 copy arguments to correct locations.
1456  // Slot meant for receiver contains return address. Reset it so that
1457  // we will not incorrectly interpret return address as an object.
1458  __ mov(Operand(esp, (num_slots_to_move + 1) * kSystemPointerSize),
1459         Immediate(0));
1460  __ mov(scratch1, Immediate(0));
1461
1462  Label loop_header, loop_check;
1463  __ jmp(&loop_check);
1464  __ bind(&loop_header);
1465  __ mov(scratch2, Operand(start_addr, 0));
1466  __ mov(Operand(esp, scratch1, times_system_pointer_size,
1467                 (num_slots_to_move + 1) * kSystemPointerSize),
1468         scratch2);
1469  __ sub(start_addr, Immediate(kSystemPointerSize));
1470  __ bind(&loop_check);
1471  __ inc(scratch1);
1472  __ cmp(scratch1, eax);
1473  __ j(less, &loop_header, Label::kNear);
1474}
1475
1476}  // anonymous namespace
1477
1478// static
1479void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
1480    MacroAssembler* masm, InterpreterPushArgsMode mode) {
1481  // ----------- S t a t e -------------
1482  //  -- eax     : the number of arguments
1483  //  -- ecx     : the address of the first argument to be pushed. Subsequent
1484  //               arguments should be consecutive above this, in the same order
1485  //               as they are to be pushed onto the stack.
1486  //  -- esp[0]  : return address
1487  //  -- esp[4]  : allocation site feedback (if available or undefined)
1488  //  -- esp[8]  : the new target
1489  //  -- esp[12] : the constructor
1490  // -----------------------------------
1491  Label stack_overflow;
1492
1493  if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
1494    // The spread argument should not be pushed.
1495    __ dec(eax);
1496  }
1497
1498  // Push arguments and move return address and stack spill slots to the top of
1499  // stack. The eax register is readonly. The ecx register will be modified. edx
1500  // and edi are used as scratch registers.
1501  Generate_InterpreterPushZeroAndArgsAndReturnAddress(
1502      masm, eax, ecx, edx, edi,
1503      InterpreterPushArgsThenConstructDescriptor::GetStackParameterCount(),
1504      &stack_overflow);
1505
1506  // Call the appropriate constructor. eax and ecx already contain intended
1507  // values, remaining registers still need to be initialized from the stack.
1508
1509  if (mode == InterpreterPushArgsMode::kArrayFunction) {
1510    // Tail call to the array construct stub (still in the caller context at
1511    // this point).
1512
1513    __ movd(xmm0, eax);  // Spill number of arguments.
1514    __ PopReturnAddressTo(eax);
1515    __ Pop(kJavaScriptCallExtraArg1Register);
1516    __ Pop(kJavaScriptCallNewTargetRegister);
1517    __ Pop(kJavaScriptCallTargetRegister);
1518    __ PushReturnAddressFrom(eax);
1519
1520    __ AssertFunction(kJavaScriptCallTargetRegister, eax);
1521    __ AssertUndefinedOrAllocationSite(kJavaScriptCallExtraArg1Register, eax);
1522
1523    __ movd(eax, xmm0);  // Reload number of arguments.
1524    __ Jump(BUILTIN_CODE(masm->isolate(), ArrayConstructorImpl),
1525            RelocInfo::CODE_TARGET);
1526  } else if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
1527    __ movd(xmm0, eax);  // Spill number of arguments.
1528    __ PopReturnAddressTo(eax);
1529    __ Drop(1);  // The allocation site is unused.
1530    __ Pop(kJavaScriptCallNewTargetRegister);
1531    __ Pop(kJavaScriptCallTargetRegister);
1532    // Pass the spread in the register ecx, overwriting ecx.
1533    __ mov(ecx, Operand(ecx, 0));
1534    __ PushReturnAddressFrom(eax);
1535    __ movd(eax, xmm0);  // Reload number of arguments.
1536    __ Jump(BUILTIN_CODE(masm->isolate(), ConstructWithSpread),
1537            RelocInfo::CODE_TARGET);
1538  } else {
1539    DCHECK_EQ(InterpreterPushArgsMode::kOther, mode);
1540    __ PopReturnAddressTo(ecx);
1541    __ Drop(1);  // The allocation site is unused.
1542    __ Pop(kJavaScriptCallNewTargetRegister);
1543    __ Pop(kJavaScriptCallTargetRegister);
1544    __ PushReturnAddressFrom(ecx);
1545
1546    __ Jump(BUILTIN_CODE(masm->isolate(), Construct), RelocInfo::CODE_TARGET);
1547  }
1548
1549  __ bind(&stack_overflow);
1550  __ TailCallRuntime(Runtime::kThrowStackOverflow);
1551  __ int3();
1552}
1553
1554static void Generate_InterpreterEnterBytecode(MacroAssembler* masm) {
1555  // Set the return address to the correct point in the interpreter entry
1556  // trampoline.
1557  Label builtin_trampoline, trampoline_loaded;
1558  Smi interpreter_entry_return_pc_offset(
1559      masm->isolate()->heap()->interpreter_entry_return_pc_offset());
1560  DCHECK_NE(interpreter_entry_return_pc_offset, Smi::zero());
1561
1562  static constexpr Register scratch = ecx;
1563
1564  // If the SFI function_data is an InterpreterData, the function will have a
1565  // custom copy of the interpreter entry trampoline for profiling. If so,
1566  // get the custom trampoline, otherwise grab the entry address of the global
1567  // trampoline.
1568  __ mov(scratch, Operand(ebp, StandardFrameConstants::kFunctionOffset));
1569  __ mov(scratch, FieldOperand(scratch, JSFunction::kSharedFunctionInfoOffset));
1570  __ mov(scratch,
1571         FieldOperand(scratch, SharedFunctionInfo::kFunctionDataOffset));
1572  __ Push(eax);
1573  __ CmpObjectType(scratch, INTERPRETER_DATA_TYPE, eax);
1574  __ j(not_equal, &builtin_trampoline, Label::kNear);
1575
1576  __ mov(scratch,
1577         FieldOperand(scratch, InterpreterData::kInterpreterTrampolineOffset));
1578  __ add(scratch, Immediate(Code::kHeaderSize - kHeapObjectTag));
1579  __ jmp(&trampoline_loaded, Label::kNear);
1580
1581  __ bind(&builtin_trampoline);
1582  __ mov(scratch,
1583         __ ExternalReferenceAsOperand(
1584             ExternalReference::
1585                 address_of_interpreter_entry_trampoline_instruction_start(
1586                     masm->isolate()),
1587             scratch));
1588
1589  __ bind(&trampoline_loaded);
1590  __ Pop(eax);
1591  __ add(scratch, Immediate(interpreter_entry_return_pc_offset.value()));
1592  __ push(scratch);
1593
1594  // Initialize the dispatch table register.
1595  __ Move(kInterpreterDispatchTableRegister,
1596          Immediate(ExternalReference::interpreter_dispatch_table_address(
1597              masm->isolate())));
1598
1599  // Get the bytecode array pointer from the frame.
1600  __ mov(kInterpreterBytecodeArrayRegister,
1601         Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp));
1602
1603  if (FLAG_debug_code) {
1604    // Check function data field is actually a BytecodeArray object.
1605    __ AssertNotSmi(kInterpreterBytecodeArrayRegister);
1606    __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE,
1607                     scratch);
1608    __ Assert(
1609        equal,
1610        AbortReason::kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
1611  }
1612
1613  // Get the target bytecode offset from the frame.
1614  __ mov(kInterpreterBytecodeOffsetRegister,
1615         Operand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
1616  __ SmiUntag(kInterpreterBytecodeOffsetRegister);
1617
1618  if (FLAG_debug_code) {
1619    Label okay;
1620    __ cmp(kInterpreterBytecodeOffsetRegister,
1621           Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
1622    __ j(greater_equal, &okay, Label::kNear);
1623    __ int3();
1624    __ bind(&okay);
1625  }
1626
1627  // Dispatch to the target bytecode.
1628  __ movzx_b(scratch, Operand(kInterpreterBytecodeArrayRegister,
1629                              kInterpreterBytecodeOffsetRegister, times_1, 0));
1630  __ mov(kJavaScriptCallCodeStartRegister,
1631         Operand(kInterpreterDispatchTableRegister, scratch,
1632                 times_system_pointer_size, 0));
1633  __ jmp(kJavaScriptCallCodeStartRegister);
1634}
1635
1636void Builtins::Generate_InterpreterEnterAtNextBytecode(MacroAssembler* masm) {
1637  // Get bytecode array and bytecode offset from the stack frame.
1638  __ mov(kInterpreterBytecodeArrayRegister,
1639         Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp));
1640  __ mov(kInterpreterBytecodeOffsetRegister,
1641         Operand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
1642  __ SmiUntag(kInterpreterBytecodeOffsetRegister);
1643
1644  Label enter_bytecode, function_entry_bytecode;
1645  __ cmp(kInterpreterBytecodeOffsetRegister,
1646         Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag +
1647                   kFunctionEntryBytecodeOffset));
1648  __ j(equal, &function_entry_bytecode);
1649
1650  // Advance to the next bytecode.
1651  Label if_return;
1652  __ Push(eax);
1653  AdvanceBytecodeOffsetOrReturn(masm, kInterpreterBytecodeArrayRegister,
1654                                kInterpreterBytecodeOffsetRegister, ecx, esi,
1655                                eax, &if_return);
1656  __ Pop(eax);
1657
1658  __ bind(&enter_bytecode);
1659  // Convert new bytecode offset to a Smi and save in the stackframe.
1660  __ mov(ecx, kInterpreterBytecodeOffsetRegister);
1661  __ SmiTag(ecx);
1662  __ mov(Operand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp), ecx);
1663
1664  Generate_InterpreterEnterBytecode(masm);
1665
1666  __ bind(&function_entry_bytecode);
1667  // If the code deoptimizes during the implicit function entry stack interrupt
1668  // check, it will have a bailout ID of kFunctionEntryBytecodeOffset, which is
1669  // not a valid bytecode offset. Detect this case and advance to the first
1670  // actual bytecode.
1671  __ mov(kInterpreterBytecodeOffsetRegister,
1672         Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
1673  __ jmp(&enter_bytecode);
1674
1675  // We should never take the if_return path.
1676  __ bind(&if_return);
1677  // No need to pop eax here since we will be aborting anyway.
1678  __ Abort(AbortReason::kInvalidBytecodeAdvance);
1679}
1680
1681void Builtins::Generate_InterpreterEnterAtBytecode(MacroAssembler* masm) {
1682  Generate_InterpreterEnterBytecode(masm);
1683}
1684// static
1685void Builtins::Generate_BaselineOutOfLinePrologue(MacroAssembler* masm) {
1686  auto descriptor =
1687      Builtins::CallInterfaceDescriptorFor(Builtin::kBaselineOutOfLinePrologue);
1688  Register arg_count = descriptor.GetRegisterParameter(
1689      BaselineOutOfLinePrologueDescriptor::kJavaScriptCallArgCount);
1690  Register frame_size = descriptor.GetRegisterParameter(
1691      BaselineOutOfLinePrologueDescriptor::kStackFrameSize);
1692
1693  // Save argument count and bytecode array.
1694  XMMRegister saved_arg_count = xmm0;
1695  XMMRegister saved_bytecode_array = xmm1;
1696  XMMRegister saved_frame_size = xmm2;
1697  XMMRegister saved_feedback_vector = xmm3;
1698  __ movd(saved_arg_count, arg_count);
1699  __ movd(saved_frame_size, frame_size);
1700
1701  // Use the arg count (eax) as the scratch register.
1702  Register scratch = arg_count;
1703
1704  // Load the feedback vector from the closure.
1705  Register feedback_vector = ecx;
1706  Register closure = descriptor.GetRegisterParameter(
1707      BaselineOutOfLinePrologueDescriptor::kClosure);
1708  __ mov(feedback_vector,
1709         FieldOperand(closure, JSFunction::kFeedbackCellOffset));
1710  __ mov(feedback_vector, FieldOperand(feedback_vector, Cell::kValueOffset));
1711  if (FLAG_debug_code) {
1712    __ CmpObjectType(feedback_vector, FEEDBACK_VECTOR_TYPE, scratch);
1713    __ Assert(equal, AbortReason::kExpectedFeedbackVector);
1714  }
1715
1716  // Load the optimization state from the feedback vector and re-use the
1717  // register.
1718  Label has_optimized_code_or_state;
1719  Register optimization_state = ecx;
1720  LoadTieringStateAndJumpIfNeedsProcessing(masm, optimization_state,
1721                                           saved_feedback_vector,
1722                                           &has_optimized_code_or_state);
1723
1724  // Load the feedback vector and increment the invocation count.
1725  __ movd(feedback_vector, saved_feedback_vector);
1726  __ inc(FieldOperand(feedback_vector, FeedbackVector::kInvocationCountOffset));
1727
1728  XMMRegister return_address = xmm4;
1729  // Save the return address, so that we can push it to the end of the newly
1730  // set-up frame once we're done setting it up.
1731  __ PopReturnAddressTo(return_address, scratch);
1732  // The bytecode array was pushed to the stack by the caller.
1733  __ Pop(saved_bytecode_array, scratch);
1734  FrameScope frame_scope(masm, StackFrame::MANUAL);
1735  {
1736    ASM_CODE_COMMENT_STRING(masm, "Frame Setup");
1737    __ EnterFrame(StackFrame::BASELINE);
1738
1739    __ Push(descriptor.GetRegisterParameter(
1740        BaselineOutOfLinePrologueDescriptor::kCalleeContext));  // Callee's
1741                                                                // context.
1742    Register callee_js_function = descriptor.GetRegisterParameter(
1743        BaselineOutOfLinePrologueDescriptor::kClosure);
1744    DCHECK_EQ(callee_js_function, kJavaScriptCallTargetRegister);
1745    DCHECK_EQ(callee_js_function, kJSFunctionRegister);
1746    __ Push(callee_js_function);        // Callee's JS function.
1747    __ Push(saved_arg_count, scratch);  // Push actual argument count.
1748
1749    // We'll use the bytecode for both code age/OSR resetting, and pushing onto
1750    // the frame, so load it into a register.
1751    Register bytecode_array = scratch;
1752    __ movd(bytecode_array, saved_bytecode_array);
1753    ResetBytecodeAgeAndOsrState(masm, bytecode_array);
1754    __ Push(bytecode_array);
1755
1756    // Baseline code frames store the feedback vector where interpreter would
1757    // store the bytecode offset.
1758    __ Push(saved_feedback_vector, scratch);
1759  }
1760
1761  Label call_stack_guard;
1762  {
1763    ASM_CODE_COMMENT_STRING(masm, "Stack/interrupt check");
1764    // Stack check. This folds the checks for both the interrupt stack limit
1765    // check and the real stack limit into one by just checking for the
1766    // interrupt limit. The interrupt limit is either equal to the real stack
1767    // limit or tighter. By ensuring we have space until that limit after
1768    // building the frame we can quickly precheck both at once.
1769    //
1770    // TODO(v8:11429): Backport this folded check to the
1771    // InterpreterEntryTrampoline.
1772    __ movd(frame_size, saved_frame_size);
1773    __ Move(scratch, esp);
1774    DCHECK_NE(frame_size, kJavaScriptCallNewTargetRegister);
1775    __ sub(scratch, frame_size);
1776    __ CompareStackLimit(scratch, StackLimitKind::kInterruptStackLimit);
1777    __ j(below, &call_stack_guard);
1778  }
1779
1780  // Push the return address back onto the stack for return.
1781  __ PushReturnAddressFrom(return_address, scratch);
1782  // Return to caller pushed pc, without any frame teardown.
1783  __ LoadRoot(kInterpreterAccumulatorRegister, RootIndex::kUndefinedValue);
1784  __ Ret();
1785
1786  __ bind(&has_optimized_code_or_state);
1787  {
1788    ASM_CODE_COMMENT_STRING(masm, "Optimized marker check");
1789    // Drop the return address and bytecode array, rebalancing the return stack
1790    // buffer by using JumpMode::kPushAndReturn. We can't leave the slot and
1791    // overwrite it on return since we may do a runtime call along the way that
1792    // requires the stack to only contain valid frames.
1793    __ Drop(2);
1794    __ movd(arg_count, saved_arg_count);  // Restore actual argument count.
1795    MaybeOptimizeCodeOrTailCallOptimizedCodeSlot(masm, optimization_state,
1796                                                 saved_feedback_vector);
1797    __ Trap();
1798  }
1799
1800  __ bind(&call_stack_guard);
1801  {
1802    ASM_CODE_COMMENT_STRING(masm, "Stack/interrupt call");
1803    {
1804      // Push the baseline code return address now, as if it had been pushed by
1805      // the call to this builtin.
1806      __ PushReturnAddressFrom(return_address, scratch);
1807      FrameScope frame_scope(masm, StackFrame::INTERNAL);
1808      // Save incoming new target or generator
1809      __ Push(kJavaScriptCallNewTargetRegister);
1810      __ SmiTag(frame_size);
1811      __ Push(frame_size);
1812      __ CallRuntime(Runtime::kStackGuardWithGap, 1);
1813      __ Pop(kJavaScriptCallNewTargetRegister);
1814    }
1815
1816    // Return to caller pushed pc, without any frame teardown.
1817    __ LoadRoot(kInterpreterAccumulatorRegister, RootIndex::kUndefinedValue);
1818    __ Ret();
1819  }
1820}
1821
1822namespace {
1823void Generate_ContinueToBuiltinHelper(MacroAssembler* masm,
1824                                      bool java_script_builtin,
1825                                      bool with_result) {
1826  const RegisterConfiguration* config(RegisterConfiguration::Default());
1827  int allocatable_register_count = config->num_allocatable_general_registers();
1828  if (with_result) {
1829    if (java_script_builtin) {
1830      // xmm0 is not included in the allocateable registers.
1831      __ movd(xmm0, eax);
1832    } else {
1833      // Overwrite the hole inserted by the deoptimizer with the return value
1834      // from the LAZY deopt point.
1835      __ mov(
1836          Operand(esp, config->num_allocatable_general_registers() *
1837                               kSystemPointerSize +
1838                           BuiltinContinuationFrameConstants::kFixedFrameSize),
1839          eax);
1840    }
1841  }
1842
1843  // Replace the builtin index Smi on the stack with the start address of the
1844  // builtin loaded from the builtins table. The ret below will return to this
1845  // address.
1846  int offset_to_builtin_index = allocatable_register_count * kSystemPointerSize;
1847  __ mov(eax, Operand(esp, offset_to_builtin_index));
1848  __ LoadEntryFromBuiltinIndex(eax);
1849  __ mov(Operand(esp, offset_to_builtin_index), eax);
1850
1851  for (int i = allocatable_register_count - 1; i >= 0; --i) {
1852    int code = config->GetAllocatableGeneralCode(i);
1853    __ pop(Register::from_code(code));
1854    if (java_script_builtin && code == kJavaScriptCallArgCountRegister.code()) {
1855      __ SmiUntag(Register::from_code(code));
1856    }
1857  }
1858  if (with_result && java_script_builtin) {
1859    // Overwrite the hole inserted by the deoptimizer with the return value from
1860    // the LAZY deopt point. eax contains the arguments count, the return value
1861    // from LAZY is always the last argument.
1862    __ movd(Operand(esp, eax, times_system_pointer_size,
1863                    BuiltinContinuationFrameConstants::kFixedFrameSize -
1864                        kJSArgcReceiverSlots * kSystemPointerSize),
1865            xmm0);
1866  }
1867  __ mov(
1868      ebp,
1869      Operand(esp, BuiltinContinuationFrameConstants::kFixedFrameSizeFromFp));
1870  const int offsetToPC =
1871      BuiltinContinuationFrameConstants::kFixedFrameSizeFromFp -
1872      kSystemPointerSize;
1873  __ pop(Operand(esp, offsetToPC));
1874  __ Drop(offsetToPC / kSystemPointerSize);
1875  __ ret(0);
1876}
1877}  // namespace
1878
1879void Builtins::Generate_ContinueToCodeStubBuiltin(MacroAssembler* masm) {
1880  Generate_ContinueToBuiltinHelper(masm, false, false);
1881}
1882
1883void Builtins::Generate_ContinueToCodeStubBuiltinWithResult(
1884    MacroAssembler* masm) {
1885  Generate_ContinueToBuiltinHelper(masm, false, true);
1886}
1887
1888void Builtins::Generate_ContinueToJavaScriptBuiltin(MacroAssembler* masm) {
1889  Generate_ContinueToBuiltinHelper(masm, true, false);
1890}
1891
1892void Builtins::Generate_ContinueToJavaScriptBuiltinWithResult(
1893    MacroAssembler* masm) {
1894  Generate_ContinueToBuiltinHelper(masm, true, true);
1895}
1896
1897void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
1898  {
1899    FrameScope scope(masm, StackFrame::INTERNAL);
1900    __ CallRuntime(Runtime::kNotifyDeoptimized);
1901    // Tear down internal frame.
1902  }
1903
1904  DCHECK_EQ(kInterpreterAccumulatorRegister.code(), eax.code());
1905  __ mov(eax, Operand(esp, 1 * kSystemPointerSize));
1906  __ ret(1 * kSystemPointerSize);  // Remove eax.
1907}
1908
1909// static
1910void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
1911  // ----------- S t a t e -------------
1912  //  -- eax     : argc
1913  //  -- esp[0]  : return address
1914  //  -- esp[1]  : receiver
1915  //  -- esp[2]  : thisArg
1916  //  -- esp[3]  : argArray
1917  // -----------------------------------
1918
1919  // 1. Load receiver into xmm0, argArray into edx (if present), remove all
1920  // arguments from the stack (including the receiver), and push thisArg (if
1921  // present) instead.
1922  {
1923    Label no_arg_array, no_this_arg;
1924    StackArgumentsAccessor args(eax);
1925    // Spill receiver to allow the usage of edi as a scratch register.
1926    __ movd(xmm0, args.GetReceiverOperand());
1927
1928    __ LoadRoot(edx, RootIndex::kUndefinedValue);
1929    __ mov(edi, edx);
1930    __ cmp(eax, Immediate(JSParameterCount(0)));
1931    __ j(equal, &no_this_arg, Label::kNear);
1932    {
1933      __ mov(edi, args[1]);
1934      __ cmp(eax, Immediate(JSParameterCount(1)));
1935      __ j(equal, &no_arg_array, Label::kNear);
1936      __ mov(edx, args[2]);
1937      __ bind(&no_arg_array);
1938    }
1939    __ bind(&no_this_arg);
1940    __ DropArgumentsAndPushNewReceiver(eax, edi, ecx,
1941                                       TurboAssembler::kCountIsInteger,
1942                                       TurboAssembler::kCountIncludesReceiver);
1943
1944    // Restore receiver to edi.
1945    __ movd(edi, xmm0);
1946  }
1947
1948  // ----------- S t a t e -------------
1949  //  -- edx    : argArray
1950  //  -- edi    : receiver
1951  //  -- esp[0] : return address
1952  //  -- esp[4] : thisArg
1953  // -----------------------------------
1954
1955  // 2. We don't need to check explicitly for callable receiver here,
1956  // since that's the first thing the Call/CallWithArrayLike builtins
1957  // will do.
1958
1959  // 3. Tail call with no arguments if argArray is null or undefined.
1960  Label no_arguments;
1961  __ JumpIfRoot(edx, RootIndex::kNullValue, &no_arguments, Label::kNear);
1962  __ JumpIfRoot(edx, RootIndex::kUndefinedValue, &no_arguments, Label::kNear);
1963
1964  // 4a. Apply the receiver to the given argArray.
1965  __ Jump(BUILTIN_CODE(masm->isolate(), CallWithArrayLike),
1966          RelocInfo::CODE_TARGET);
1967
1968  // 4b. The argArray is either null or undefined, so we tail call without any
1969  // arguments to the receiver.
1970  __ bind(&no_arguments);
1971  {
1972    __ Move(eax, JSParameterCount(0));
1973    __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1974  }
1975}
1976
1977// static
1978void Builtins::Generate_FunctionPrototypeCall(MacroAssembler* masm) {
1979  // Stack Layout:
1980  // esp[0]           : Return address
1981  // esp[8]           : Argument 0 (receiver: callable to call)
1982  // esp[16]          : Argument 1
1983  //  ...
1984  // esp[8 * n]       : Argument n-1
1985  // esp[8 * (n + 1)] : Argument n
1986  // eax contains the number of arguments, n.
1987
1988  // 1. Get the callable to call (passed as receiver) from the stack.
1989  {
1990    StackArgumentsAccessor args(eax);
1991    __ mov(edi, args.GetReceiverOperand());
1992  }
1993
1994  // 2. Save the return address and drop the callable.
1995  __ PopReturnAddressTo(edx);
1996  __ Pop(ecx);
1997
1998  // 3. Make sure we have at least one argument.
1999  {
2000    Label done;
2001    __ cmp(eax, Immediate(JSParameterCount(0)));
2002    __ j(greater, &done, Label::kNear);
2003    __ PushRoot(RootIndex::kUndefinedValue);
2004    __ inc(eax);
2005    __ bind(&done);
2006  }
2007
2008  // 4. Push back the return address one slot down on the stack (overwriting the
2009  // original callable), making the original first argument the new receiver.
2010  __ PushReturnAddressFrom(edx);
2011  __ dec(eax);  // One fewer argument (first argument is new receiver).
2012
2013  // 5. Call the callable.
2014  __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
2015}
2016
2017void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
2018  // ----------- S t a t e -------------
2019  //  -- eax     : argc
2020  //  -- esp[0]  : return address
2021  //  -- esp[4]  : receiver
2022  //  -- esp[8]  : target         (if argc >= 1)
2023  //  -- esp[12] : thisArgument   (if argc >= 2)
2024  //  -- esp[16] : argumentsList  (if argc == 3)
2025  // -----------------------------------
2026
2027  // 1. Load target into edi (if present), argumentsList into edx (if present),
2028  // remove all arguments from the stack (including the receiver), and push
2029  // thisArgument (if present) instead.
2030  {
2031    Label done;
2032    StackArgumentsAccessor args(eax);
2033    __ LoadRoot(edi, RootIndex::kUndefinedValue);
2034    __ mov(edx, edi);
2035    __ mov(ecx, edi);
2036    __ cmp(eax, Immediate(JSParameterCount(1)));
2037    __ j(below, &done, Label::kNear);
2038    __ mov(edi, args[1]);  // target
2039    __ j(equal, &done, Label::kNear);
2040    __ mov(ecx, args[2]);  // thisArgument
2041    __ cmp(eax, Immediate(JSParameterCount(3)));
2042    __ j(below, &done, Label::kNear);
2043    __ mov(edx, args[3]);  // argumentsList
2044    __ bind(&done);
2045
2046    // Spill argumentsList to use edx as a scratch register.
2047    __ movd(xmm0, edx);
2048
2049    __ DropArgumentsAndPushNewReceiver(eax, ecx, edx,
2050                                       TurboAssembler::kCountIsInteger,
2051                                       TurboAssembler::kCountIncludesReceiver);
2052
2053    // Restore argumentsList.
2054    __ movd(edx, xmm0);
2055  }
2056
2057  // ----------- S t a t e -------------
2058  //  -- edx    : argumentsList
2059  //  -- edi    : target
2060  //  -- esp[0] : return address
2061  //  -- esp[4] : thisArgument
2062  // -----------------------------------
2063
2064  // 2. We don't need to check explicitly for callable target here,
2065  // since that's the first thing the Call/CallWithArrayLike builtins
2066  // will do.
2067
2068  // 3. Apply the target to the given argumentsList.
2069  __ Jump(BUILTIN_CODE(masm->isolate(), CallWithArrayLike),
2070          RelocInfo::CODE_TARGET);
2071}
2072
2073void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
2074  // ----------- S t a t e -------------
2075  //  -- eax     : argc
2076  //  -- esp[0]  : return address
2077  //  -- esp[4]  : receiver
2078  //  -- esp[8]  : target
2079  //  -- esp[12] : argumentsList
2080  //  -- esp[16] : new.target (optional)
2081  // -----------------------------------
2082
2083  // 1. Load target into edi (if present), argumentsList into ecx (if present),
2084  // new.target into edx (if present, otherwise use target), remove all
2085  // arguments from the stack (including the receiver), and push thisArgument
2086  // (if present) instead.
2087  {
2088    Label done;
2089    StackArgumentsAccessor args(eax);
2090    __ LoadRoot(edi, RootIndex::kUndefinedValue);
2091    __ mov(edx, edi);
2092    __ mov(ecx, edi);
2093    __ cmp(eax, Immediate(JSParameterCount(1)));
2094    __ j(below, &done, Label::kNear);
2095    __ mov(edi, args[1]);  // target
2096    __ mov(edx, edi);
2097    __ j(equal, &done, Label::kNear);
2098    __ mov(ecx, args[2]);  // argumentsList
2099    __ cmp(eax, Immediate(JSParameterCount(3)));
2100    __ j(below, &done, Label::kNear);
2101    __ mov(edx, args[3]);  // new.target
2102    __ bind(&done);
2103
2104    // Spill argumentsList to use ecx as a scratch register.
2105    __ movd(xmm0, ecx);
2106
2107    __ DropArgumentsAndPushNewReceiver(
2108        eax, masm->RootAsOperand(RootIndex::kUndefinedValue), ecx,
2109        TurboAssembler::kCountIsInteger,
2110        TurboAssembler::kCountIncludesReceiver);
2111
2112    // Restore argumentsList.
2113    __ movd(ecx, xmm0);
2114  }
2115
2116  // ----------- S t a t e -------------
2117  //  -- ecx    : argumentsList
2118  //  -- edx    : new.target
2119  //  -- edi    : target
2120  //  -- esp[0] : return address
2121  //  -- esp[4] : receiver (undefined)
2122  // -----------------------------------
2123
2124  // 2. We don't need to check explicitly for constructor target here,
2125  // since that's the first thing the Construct/ConstructWithArrayLike
2126  // builtins will do.
2127
2128  // 3. We don't need to check explicitly for constructor new.target here,
2129  // since that's the second thing the Construct/ConstructWithArrayLike
2130  // builtins will do.
2131
2132  // 4. Construct the target with the given new.target and argumentsList.
2133  __ Jump(BUILTIN_CODE(masm->isolate(), ConstructWithArrayLike),
2134          RelocInfo::CODE_TARGET);
2135}
2136
2137namespace {
2138
2139// Allocate new stack space for |count| arguments and shift all existing
2140// arguments already on the stack. |pointer_to_new_space_out| points to the
2141// first free slot on the stack to copy additional arguments to and
2142// |argc_in_out| is updated to include |count|.
2143void Generate_AllocateSpaceAndShiftExistingArguments(
2144    MacroAssembler* masm, Register count, Register argc_in_out,
2145    Register pointer_to_new_space_out, Register scratch1, Register scratch2) {
2146  DCHECK(!AreAliased(count, argc_in_out, pointer_to_new_space_out, scratch1,
2147                     scratch2));
2148  // Use pointer_to_new_space_out as scratch until we set it to the correct
2149  // value at the end.
2150  Register old_esp = pointer_to_new_space_out;
2151  Register new_space = scratch1;
2152  __ mov(old_esp, esp);
2153
2154  __ lea(new_space, Operand(count, times_system_pointer_size, 0));
2155  __ AllocateStackSpace(new_space);
2156
2157  Register current = scratch1;
2158  Register value = scratch2;
2159
2160  Label loop, entry;
2161  __ mov(current, 0);
2162  __ jmp(&entry);
2163  __ bind(&loop);
2164  __ mov(value, Operand(old_esp, current, times_system_pointer_size, 0));
2165  __ mov(Operand(esp, current, times_system_pointer_size, 0), value);
2166  __ inc(current);
2167  __ bind(&entry);
2168  __ cmp(current, argc_in_out);
2169  __ j(less_equal, &loop, Label::kNear);
2170
2171  // Point to the next free slot above the shifted arguments (argc + 1 slot for
2172  // the return address).
2173  __ lea(
2174      pointer_to_new_space_out,
2175      Operand(esp, argc_in_out, times_system_pointer_size, kSystemPointerSize));
2176  // Update the total number of arguments.
2177  __ add(argc_in_out, count);
2178}
2179
2180}  // namespace
2181
2182// static
2183// TODO(v8:11615): Observe Code::kMaxArguments in CallOrConstructVarargs
2184void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm,
2185                                               Handle<Code> code) {
2186  // ----------- S t a t e -------------
2187  //  -- edi    : target
2188  //  -- esi    : context for the Call / Construct builtin
2189  //  -- eax    : number of parameters on the stack
2190  //  -- ecx    : len (number of elements to from args)
2191  //  -- edx    : new.target (checked to be constructor or undefined)
2192  //  -- esp[4] : arguments list (a FixedArray)
2193  //  -- esp[0] : return address.
2194  // -----------------------------------
2195
2196  __ movd(xmm0, edx);  // Spill new.target.
2197  __ movd(xmm1, edi);  // Spill target.
2198  __ movd(xmm3, esi);  // Spill the context.
2199
2200  const Register kArgumentsList = esi;
2201  const Register kArgumentsLength = ecx;
2202
2203  __ PopReturnAddressTo(edx);
2204  __ pop(kArgumentsList);
2205  __ PushReturnAddressFrom(edx);
2206
2207  if (FLAG_debug_code) {
2208    // Allow kArgumentsList to be a FixedArray, or a FixedDoubleArray if
2209    // kArgumentsLength == 0.
2210    Label ok, fail;
2211    __ AssertNotSmi(kArgumentsList);
2212    __ mov(edx, FieldOperand(kArgumentsList, HeapObject::kMapOffset));
2213    __ CmpInstanceType(edx, FIXED_ARRAY_TYPE);
2214    __ j(equal, &ok);
2215    __ CmpInstanceType(edx, FIXED_DOUBLE_ARRAY_TYPE);
2216    __ j(not_equal, &fail);
2217    __ cmp(kArgumentsLength, 0);
2218    __ j(equal, &ok);
2219    // Fall through.
2220    __ bind(&fail);
2221    __ Abort(AbortReason::kOperandIsNotAFixedArray);
2222
2223    __ bind(&ok);
2224  }
2225
2226  // Check the stack for overflow. We are not trying to catch interruptions
2227  // (i.e. debug break and preemption) here, so check the "real stack limit".
2228  Label stack_overflow;
2229  __ StackOverflowCheck(kArgumentsLength, edx, &stack_overflow);
2230
2231  __ movd(xmm4, kArgumentsList);  // Spill the arguments list.
2232  // Move the arguments already in the stack,
2233  // including the receiver and the return address.
2234  // kArgumentsLength (ecx): Number of arguments to make room for.
2235  // eax: Number of arguments already on the stack.
2236  // edx: Points to first free slot on the stack after arguments were shifted.
2237  Generate_AllocateSpaceAndShiftExistingArguments(masm, kArgumentsLength, eax,
2238                                                  edx, edi, esi);
2239  __ movd(kArgumentsList, xmm4);  // Recover arguments list.
2240  __ movd(xmm2, eax);             // Spill argument count.
2241
2242  // Push additional arguments onto the stack.
2243  {
2244    __ Move(eax, Immediate(0));
2245    Label done, push, loop;
2246    __ bind(&loop);
2247    __ cmp(eax, kArgumentsLength);
2248    __ j(equal, &done, Label::kNear);
2249    // Turn the hole into undefined as we go.
2250    __ mov(edi, FieldOperand(kArgumentsList, eax, times_tagged_size,
2251                             FixedArray::kHeaderSize));
2252    __ CompareRoot(edi, RootIndex::kTheHoleValue);
2253    __ j(not_equal, &push, Label::kNear);
2254    __ LoadRoot(edi, RootIndex::kUndefinedValue);
2255    __ bind(&push);
2256    __ mov(Operand(edx, 0), edi);
2257    __ add(edx, Immediate(kSystemPointerSize));
2258    __ inc(eax);
2259    __ jmp(&loop);
2260    __ bind(&done);
2261  }
2262
2263  // Restore eax, edi and edx.
2264  __ movd(esi, xmm3);  // Restore the context.
2265  __ movd(eax, xmm2);  // Restore argument count.
2266  __ movd(edi, xmm1);  // Restore target.
2267  __ movd(edx, xmm0);  // Restore new.target.
2268
2269  // Tail-call to the actual Call or Construct builtin.
2270  __ Jump(code, RelocInfo::CODE_TARGET);
2271
2272  __ bind(&stack_overflow);
2273  __ movd(esi, xmm3);  // Restore the context.
2274  __ TailCallRuntime(Runtime::kThrowStackOverflow);
2275}
2276
2277// static
2278void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm,
2279                                                      CallOrConstructMode mode,
2280                                                      Handle<Code> code) {
2281  // ----------- S t a t e -------------
2282  //  -- eax : the number of arguments
2283  //  -- edi : the target to call (can be any Object)
2284  //  -- esi : context for the Call / Construct builtin
2285  //  -- edx : the new target (for [[Construct]] calls)
2286  //  -- ecx : start index (to support rest parameters)
2287  // -----------------------------------
2288
2289  __ movd(xmm0, esi);  // Spill the context.
2290
2291  Register scratch = esi;
2292
2293  // Check if new.target has a [[Construct]] internal method.
2294  if (mode == CallOrConstructMode::kConstruct) {
2295    Label new_target_constructor, new_target_not_constructor;
2296    __ JumpIfSmi(edx, &new_target_not_constructor, Label::kNear);
2297    __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset));
2298    __ test_b(FieldOperand(scratch, Map::kBitFieldOffset),
2299              Immediate(Map::Bits1::IsConstructorBit::kMask));
2300    __ j(not_zero, &new_target_constructor, Label::kNear);
2301    __ bind(&new_target_not_constructor);
2302    {
2303      FrameScope scope(masm, StackFrame::MANUAL);
2304      __ EnterFrame(StackFrame::INTERNAL);
2305      __ Push(edx);
2306      __ movd(esi, xmm0);  // Restore the context.
2307      __ CallRuntime(Runtime::kThrowNotConstructor);
2308    }
2309    __ bind(&new_target_constructor);
2310  }
2311
2312  __ movd(xmm1, edx);  // Preserve new.target (in case of [[Construct]]).
2313
2314  Label stack_done, stack_overflow;
2315  __ mov(edx, Operand(ebp, StandardFrameConstants::kArgCOffset));
2316  __ dec(edx);  // Exclude receiver.
2317  __ sub(edx, ecx);
2318  __ j(less_equal, &stack_done);
2319  {
2320    // ----------- S t a t e -------------
2321    //  -- eax : the number of arguments already in the stack
2322    //  -- ecx : start index (to support rest parameters)
2323    //  -- edx : number of arguments to copy, i.e. arguments count - start index
2324    //  -- edi : the target to call (can be any Object)
2325    //  -- ebp : point to the caller stack frame
2326    //  -- xmm0 : context for the Call / Construct builtin
2327    //  -- xmm1 : the new target (for [[Construct]] calls)
2328    // -----------------------------------
2329
2330    // Forward the arguments from the caller frame.
2331    __ movd(xmm2, edi);  // Preserve the target to call.
2332    __ StackOverflowCheck(edx, edi, &stack_overflow);
2333    __ movd(xmm3, ebx);  // Preserve root register.
2334
2335    Register scratch = ebx;
2336
2337    // Move the arguments already in the stack,
2338    // including the receiver and the return address.
2339    // edx: Number of arguments to make room for.
2340    // eax: Number of arguments already on the stack.
2341    // esi: Points to first free slot on the stack after arguments were shifted.
2342    Generate_AllocateSpaceAndShiftExistingArguments(masm, edx, eax, esi, ebx,
2343                                                    edi);
2344
2345    // Point to the first argument to copy (skipping receiver).
2346    __ lea(ecx, Operand(ecx, times_system_pointer_size,
2347                        CommonFrameConstants::kFixedFrameSizeAboveFp +
2348                            kSystemPointerSize));
2349    __ add(ecx, ebp);
2350
2351    // Copy the additional caller arguments onto the stack.
2352    // TODO(victorgomes): Consider using forward order as potentially more cache
2353    // friendly.
2354    {
2355      Register src = ecx, dest = esi, num = edx;
2356      Label loop;
2357      __ bind(&loop);
2358      __ dec(num);
2359      __ mov(scratch, Operand(src, num, times_system_pointer_size, 0));
2360      __ mov(Operand(dest, num, times_system_pointer_size, 0), scratch);
2361      __ j(not_zero, &loop);
2362    }
2363
2364    __ movd(ebx, xmm3);  // Restore root register.
2365    __ movd(edi, xmm2);  // Restore the target to call.
2366  }
2367  __ bind(&stack_done);
2368
2369  __ movd(edx, xmm1);  // Restore new.target (in case of [[Construct]]).
2370  __ movd(esi, xmm0);  // Restore the context.
2371
2372  // Tail-call to the {code} handler.
2373  __ Jump(code, RelocInfo::CODE_TARGET);
2374
2375  __ bind(&stack_overflow);
2376  __ movd(edi, xmm2);  // Restore the target to call.
2377  __ movd(esi, xmm0);  // Restore the context.
2378  __ TailCallRuntime(Runtime::kThrowStackOverflow);
2379}
2380
2381// static
2382void Builtins::Generate_CallFunction(MacroAssembler* masm,
2383                                     ConvertReceiverMode mode) {
2384  // ----------- S t a t e -------------
2385  //  -- eax : the number of arguments
2386  //  -- edi : the function to call (checked to be a JSFunction)
2387  // -----------------------------------
2388  StackArgumentsAccessor args(eax);
2389  __ AssertCallableFunction(edi, edx);
2390
2391  __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2392
2393  // Enter the context of the function; ToObject has to run in the function
2394  // context, and we also need to take the global proxy from the function
2395  // context in case of conversion.
2396  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2397  // We need to convert the receiver for non-native sloppy mode functions.
2398  Label done_convert;
2399  __ test(FieldOperand(edx, SharedFunctionInfo::kFlagsOffset),
2400          Immediate(SharedFunctionInfo::IsNativeBit::kMask |
2401                    SharedFunctionInfo::IsStrictBit::kMask));
2402  __ j(not_zero, &done_convert);
2403  {
2404    // ----------- S t a t e -------------
2405    //  -- eax : the number of arguments
2406    //  -- edx : the shared function info.
2407    //  -- edi : the function to call (checked to be a JSFunction)
2408    //  -- esi : the function context.
2409    // -----------------------------------
2410
2411    if (mode == ConvertReceiverMode::kNullOrUndefined) {
2412      // Patch receiver to global proxy.
2413      __ LoadGlobalProxy(ecx);
2414    } else {
2415      Label convert_to_object, convert_receiver;
2416      __ mov(ecx, args.GetReceiverOperand());
2417      __ JumpIfSmi(ecx, &convert_to_object, Label::kNear);
2418      STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
2419      __ CmpObjectType(ecx, FIRST_JS_RECEIVER_TYPE, ecx);  // Clobbers ecx.
2420      __ j(above_equal, &done_convert);
2421      // Reload the receiver (it was clobbered by CmpObjectType).
2422      __ mov(ecx, args.GetReceiverOperand());
2423      if (mode != ConvertReceiverMode::kNotNullOrUndefined) {
2424        Label convert_global_proxy;
2425        __ JumpIfRoot(ecx, RootIndex::kUndefinedValue, &convert_global_proxy,
2426                      Label::kNear);
2427        __ JumpIfNotRoot(ecx, RootIndex::kNullValue, &convert_to_object,
2428                         Label::kNear);
2429        __ bind(&convert_global_proxy);
2430        {
2431          // Patch receiver to global proxy.
2432          __ LoadGlobalProxy(ecx);
2433        }
2434        __ jmp(&convert_receiver);
2435      }
2436      __ bind(&convert_to_object);
2437      {
2438        // Convert receiver using ToObject.
2439        // TODO(bmeurer): Inline the allocation here to avoid building the frame
2440        // in the fast case? (fall back to AllocateInNewSpace?)
2441        FrameScope scope(masm, StackFrame::INTERNAL);
2442        __ SmiTag(eax);
2443        __ Push(eax);
2444        __ Push(edi);
2445        __ mov(eax, ecx);
2446        __ Push(esi);
2447        __ Call(BUILTIN_CODE(masm->isolate(), ToObject),
2448                RelocInfo::CODE_TARGET);
2449        __ Pop(esi);
2450        __ mov(ecx, eax);
2451        __ Pop(edi);
2452        __ Pop(eax);
2453        __ SmiUntag(eax);
2454      }
2455      __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2456      __ bind(&convert_receiver);
2457    }
2458    __ mov(args.GetReceiverOperand(), ecx);
2459  }
2460  __ bind(&done_convert);
2461
2462  // ----------- S t a t e -------------
2463  //  -- eax : the number of arguments
2464  //  -- edx : the shared function info.
2465  //  -- edi : the function to call (checked to be a JSFunction)
2466  //  -- esi : the function context.
2467  // -----------------------------------
2468
2469  __ movzx_w(
2470      ecx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
2471  __ InvokeFunctionCode(edi, no_reg, ecx, eax, InvokeType::kJump);
2472}
2473
2474namespace {
2475
2476void Generate_PushBoundArguments(MacroAssembler* masm) {
2477  // ----------- S t a t e -------------
2478  //  -- eax : the number of arguments
2479  //  -- edx : new.target (only in case of [[Construct]])
2480  //  -- edi : target (checked to be a JSBoundFunction)
2481  // -----------------------------------
2482  __ movd(xmm0, edx);  // Spill edx.
2483
2484  // Load [[BoundArguments]] into ecx and length of that into edx.
2485  Label no_bound_arguments;
2486  __ mov(ecx, FieldOperand(edi, JSBoundFunction::kBoundArgumentsOffset));
2487  __ mov(edx, FieldOperand(ecx, FixedArray::kLengthOffset));
2488  __ SmiUntag(edx);
2489  __ test(edx, edx);
2490  __ j(zero, &no_bound_arguments);
2491  {
2492    // ----------- S t a t e -------------
2493    //  -- eax  : the number of arguments
2494    //  -- xmm0 : new.target (only in case of [[Construct]])
2495    //  -- edi  : target (checked to be a JSBoundFunction)
2496    //  -- ecx  : the [[BoundArguments]] (implemented as FixedArray)
2497    //  -- edx  : the number of [[BoundArguments]]
2498    // -----------------------------------
2499
2500    // Check the stack for overflow.
2501    {
2502      Label done, stack_overflow;
2503      __ StackOverflowCheck(edx, ecx, &stack_overflow);
2504      __ jmp(&done);
2505      __ bind(&stack_overflow);
2506      {
2507        FrameScope frame(masm, StackFrame::MANUAL);
2508        __ EnterFrame(StackFrame::INTERNAL);
2509        __ CallRuntime(Runtime::kThrowStackOverflow);
2510        __ int3();
2511      }
2512      __ bind(&done);
2513    }
2514
2515    // Spill context.
2516    __ movd(xmm3, esi);
2517
2518    // Save Return Adress and Receiver into registers.
2519    __ pop(esi);
2520    __ movd(xmm1, esi);
2521    __ pop(esi);
2522    __ movd(xmm2, esi);
2523
2524    // Push [[BoundArguments]] to the stack.
2525    {
2526      Label loop;
2527      __ mov(ecx, FieldOperand(edi, JSBoundFunction::kBoundArgumentsOffset));
2528      __ mov(edx, FieldOperand(ecx, FixedArray::kLengthOffset));
2529      __ SmiUntag(edx);
2530      // Adjust effective number of arguments (eax contains the number of
2531      // arguments from the call not including receiver plus the number of
2532      // [[BoundArguments]]).
2533      __ add(eax, edx);
2534      __ bind(&loop);
2535      __ dec(edx);
2536      __ mov(esi, FieldOperand(ecx, edx, times_tagged_size,
2537                               FixedArray::kHeaderSize));
2538      __ push(esi);
2539      __ j(greater, &loop);
2540    }
2541
2542    // Restore Receiver and Return Address.
2543    __ movd(esi, xmm2);
2544    __ push(esi);
2545    __ movd(esi, xmm1);
2546    __ push(esi);
2547
2548    // Restore context.
2549    __ movd(esi, xmm3);
2550  }
2551
2552  __ bind(&no_bound_arguments);
2553  __ movd(edx, xmm0);  // Reload edx.
2554}
2555
2556}  // namespace
2557
2558// static
2559void Builtins::Generate_CallBoundFunctionImpl(MacroAssembler* masm) {
2560  // ----------- S t a t e -------------
2561  //  -- eax : the number of arguments
2562  //  -- edi : the function to call (checked to be a JSBoundFunction)
2563  // -----------------------------------
2564  __ AssertBoundFunction(edi);
2565
2566  // Patch the receiver to [[BoundThis]].
2567  StackArgumentsAccessor args(eax);
2568  __ mov(ecx, FieldOperand(edi, JSBoundFunction::kBoundThisOffset));
2569  __ mov(args.GetReceiverOperand(), ecx);
2570
2571  // Push the [[BoundArguments]] onto the stack.
2572  Generate_PushBoundArguments(masm);
2573
2574  // Call the [[BoundTargetFunction]] via the Call builtin.
2575  __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset));
2576  __ Jump(BUILTIN_CODE(masm->isolate(), Call_ReceiverIsAny),
2577          RelocInfo::CODE_TARGET);
2578}
2579
2580// static
2581void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
2582  // ----------- S t a t e -------------
2583  //  -- eax : the number of arguments
2584  //  -- edi : the target to call (can be any Object).
2585  // -----------------------------------
2586  Register argc = eax;
2587  Register target = edi;
2588  Register map = ecx;
2589  Register instance_type = edx;
2590  DCHECK(!AreAliased(argc, target, map, instance_type));
2591
2592  StackArgumentsAccessor args(argc);
2593
2594  Label non_callable, non_smi, non_callable_jsfunction, non_jsboundfunction,
2595      non_proxy, non_wrapped_function, class_constructor;
2596  __ JumpIfSmi(target, &non_callable);
2597  __ bind(&non_smi);
2598  __ LoadMap(map, target);
2599  __ CmpInstanceTypeRange(map, instance_type, map,
2600                          FIRST_CALLABLE_JS_FUNCTION_TYPE,
2601                          LAST_CALLABLE_JS_FUNCTION_TYPE);
2602  __ j(above, &non_callable_jsfunction);
2603  __ Jump(masm->isolate()->builtins()->CallFunction(mode),
2604          RelocInfo::CODE_TARGET);
2605
2606  __ bind(&non_callable_jsfunction);
2607  __ cmpw(instance_type, Immediate(JS_BOUND_FUNCTION_TYPE));
2608  __ j(not_equal, &non_jsboundfunction);
2609  __ Jump(BUILTIN_CODE(masm->isolate(), CallBoundFunction),
2610          RelocInfo::CODE_TARGET);
2611
2612  // Check if target is a proxy and call CallProxy external builtin
2613  __ bind(&non_jsboundfunction);
2614  __ LoadMap(map, target);
2615  __ test_b(FieldOperand(map, Map::kBitFieldOffset),
2616            Immediate(Map::Bits1::IsCallableBit::kMask));
2617  __ j(zero, &non_callable);
2618
2619  // Call CallProxy external builtin
2620  __ cmpw(instance_type, Immediate(JS_PROXY_TYPE));
2621  __ j(not_equal, &non_proxy);
2622  __ Jump(BUILTIN_CODE(masm->isolate(), CallProxy), RelocInfo::CODE_TARGET);
2623
2624  // Check if target is a wrapped function and call CallWrappedFunction external
2625  // builtin
2626  __ bind(&non_proxy);
2627  __ cmpw(instance_type, Immediate(JS_WRAPPED_FUNCTION_TYPE));
2628  __ j(not_equal, &non_wrapped_function);
2629  __ Jump(BUILTIN_CODE(masm->isolate(), CallWrappedFunction),
2630          RelocInfo::CODE_TARGET);
2631
2632  // ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
2633  // Check that the function is not a "classConstructor".
2634  __ bind(&non_wrapped_function);
2635  __ cmpw(instance_type, Immediate(JS_CLASS_CONSTRUCTOR_TYPE));
2636  __ j(equal, &class_constructor);
2637
2638  // 2. Call to something else, which might have a [[Call]] internal method (if
2639  // not we raise an exception).
2640  // Overwrite the original receiver with the (original) target.
2641  __ mov(args.GetReceiverOperand(), target);
2642  // Let the "call_as_function_delegate" take care of the rest.
2643  __ LoadNativeContextSlot(target, Context::CALL_AS_FUNCTION_DELEGATE_INDEX);
2644  __ Jump(masm->isolate()->builtins()->CallFunction(
2645              ConvertReceiverMode::kNotNullOrUndefined),
2646          RelocInfo::CODE_TARGET);
2647
2648  // 3. Call to something that is not callable.
2649  __ bind(&non_callable);
2650  {
2651    FrameScope scope(masm, StackFrame::INTERNAL);
2652    __ Push(target);
2653    __ CallRuntime(Runtime::kThrowCalledNonCallable);
2654    __ Trap();  // Unreachable.
2655  }
2656
2657  // 4. The function is a "classConstructor", need to raise an exception.
2658  __ bind(&class_constructor);
2659  {
2660    FrameScope frame(masm, StackFrame::INTERNAL);
2661    __ Push(target);
2662    __ CallRuntime(Runtime::kThrowConstructorNonCallableError);
2663    __ Trap();  // Unreachable.
2664  }
2665}
2666
2667// static
2668void Builtins::Generate_ConstructFunction(MacroAssembler* masm) {
2669  // ----------- S t a t e -------------
2670  //  -- eax : the number of arguments
2671  //  -- edx : the new target (checked to be a constructor)
2672  //  -- edi : the constructor to call (checked to be a JSFunction)
2673  // -----------------------------------
2674  __ AssertConstructor(edi);
2675  __ AssertFunction(edi, ecx);
2676
2677  Label call_generic_stub;
2678
2679  // Jump to JSBuiltinsConstructStub or JSConstructStubGeneric.
2680  __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2681  __ test(FieldOperand(ecx, SharedFunctionInfo::kFlagsOffset),
2682          Immediate(SharedFunctionInfo::ConstructAsBuiltinBit::kMask));
2683  __ j(zero, &call_generic_stub, Label::kNear);
2684
2685  // Calling convention for function specific ConstructStubs require
2686  // ecx to contain either an AllocationSite or undefined.
2687  __ LoadRoot(ecx, RootIndex::kUndefinedValue);
2688  __ Jump(BUILTIN_CODE(masm->isolate(), JSBuiltinsConstructStub),
2689          RelocInfo::CODE_TARGET);
2690
2691  __ bind(&call_generic_stub);
2692  // Calling convention for function specific ConstructStubs require
2693  // ecx to contain either an AllocationSite or undefined.
2694  __ LoadRoot(ecx, RootIndex::kUndefinedValue);
2695  __ Jump(BUILTIN_CODE(masm->isolate(), JSConstructStubGeneric),
2696          RelocInfo::CODE_TARGET);
2697}
2698
2699// static
2700void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) {
2701  // ----------- S t a t e -------------
2702  //  -- eax : the number of arguments
2703  //  -- edx : the new target (checked to be a constructor)
2704  //  -- edi : the constructor to call (checked to be a JSBoundFunction)
2705  // -----------------------------------
2706  __ AssertConstructor(edi);
2707  __ AssertBoundFunction(edi);
2708
2709  // Push the [[BoundArguments]] onto the stack.
2710  Generate_PushBoundArguments(masm);
2711
2712  // Patch new.target to [[BoundTargetFunction]] if new.target equals target.
2713  {
2714    Label done;
2715    __ cmp(edi, edx);
2716    __ j(not_equal, &done, Label::kNear);
2717    __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset));
2718    __ bind(&done);
2719  }
2720
2721  // Construct the [[BoundTargetFunction]] via the Construct builtin.
2722  __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset));
2723  __ Jump(BUILTIN_CODE(masm->isolate(), Construct), RelocInfo::CODE_TARGET);
2724}
2725
2726// static
2727void Builtins::Generate_Construct(MacroAssembler* masm) {
2728  // ----------- S t a t e -------------
2729  //  -- eax : the number of arguments
2730  //  -- edx : the new target (either the same as the constructor or
2731  //           the JSFunction on which new was invoked initially)
2732  //  -- edi : the constructor to call (can be any Object)
2733  // -----------------------------------
2734  Register argc = eax;
2735  Register target = edi;
2736  Register map = ecx;
2737  DCHECK(!AreAliased(argc, target, map));
2738
2739  StackArgumentsAccessor args(argc);
2740
2741  // Check if target is a Smi.
2742  Label non_constructor, non_proxy, non_jsfunction, non_jsboundfunction;
2743  __ JumpIfSmi(target, &non_constructor);
2744
2745  // Check if target has a [[Construct]] internal method.
2746  __ mov(map, FieldOperand(target, HeapObject::kMapOffset));
2747  __ test_b(FieldOperand(map, Map::kBitFieldOffset),
2748            Immediate(Map::Bits1::IsConstructorBit::kMask));
2749  __ j(zero, &non_constructor);
2750
2751  // Dispatch based on instance type.
2752  __ CmpInstanceTypeRange(map, map, map, FIRST_JS_FUNCTION_TYPE,
2753                          LAST_JS_FUNCTION_TYPE);
2754  __ j(above, &non_jsfunction);
2755  __ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction),
2756          RelocInfo::CODE_TARGET);
2757
2758  // Only dispatch to bound functions after checking whether they are
2759  // constructors.
2760  __ bind(&non_jsfunction);
2761  __ mov(map, FieldOperand(target, HeapObject::kMapOffset));
2762  __ CmpInstanceType(map, JS_BOUND_FUNCTION_TYPE);
2763  __ j(not_equal, &non_jsboundfunction);
2764  __ Jump(BUILTIN_CODE(masm->isolate(), ConstructBoundFunction),
2765          RelocInfo::CODE_TARGET);
2766
2767  // Only dispatch to proxies after checking whether they are constructors.
2768  __ bind(&non_jsboundfunction);
2769  __ CmpInstanceType(map, JS_PROXY_TYPE);
2770  __ j(not_equal, &non_proxy);
2771  __ Jump(BUILTIN_CODE(masm->isolate(), ConstructProxy),
2772          RelocInfo::CODE_TARGET);
2773
2774  // Called Construct on an exotic Object with a [[Construct]] internal method.
2775  __ bind(&non_proxy);
2776  {
2777    // Overwrite the original receiver with the (original) target.
2778    __ mov(args.GetReceiverOperand(), target);
2779    // Let the "call_as_constructor_delegate" take care of the rest.
2780    __ LoadNativeContextSlot(target,
2781                             Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX);
2782    __ Jump(masm->isolate()->builtins()->CallFunction(),
2783            RelocInfo::CODE_TARGET);
2784  }
2785
2786  // Called Construct on an Object that doesn't have a [[Construct]] internal
2787  // method.
2788  __ bind(&non_constructor);
2789  __ Jump(BUILTIN_CODE(masm->isolate(), ConstructedNonConstructable),
2790          RelocInfo::CODE_TARGET);
2791}
2792
2793namespace {
2794
2795void Generate_OSREntry(MacroAssembler* masm, Register entry_address) {
2796  ASM_CODE_COMMENT(masm);
2797  // Overwrite the return address on the stack.
2798  __ mov(Operand(esp, 0), entry_address);
2799
2800  // And "return" to the OSR entry point of the function.
2801  __ ret(0);
2802}
2803
2804void OnStackReplacement(MacroAssembler* masm, bool is_interpreter) {
2805  ASM_CODE_COMMENT(masm);
2806  {
2807    FrameScope scope(masm, StackFrame::INTERNAL);
2808    __ CallRuntime(Runtime::kCompileOptimizedOSR);
2809  }
2810
2811  Label skip;
2812  // If the code object is null, just return to the caller.
2813  __ cmp(eax, Immediate(0));
2814  __ j(not_equal, &skip, Label::kNear);
2815  __ ret(0);
2816
2817  __ bind(&skip);
2818
2819  if (is_interpreter) {
2820    // Drop the handler frame that is be sitting on top of the actual
2821    // JavaScript frame. This is the case then OSR is triggered from bytecode.
2822    __ leave();
2823  }
2824
2825  // Load deoptimization data from the code object.
2826  __ mov(ecx, Operand(eax, Code::kDeoptimizationDataOrInterpreterDataOffset -
2827                               kHeapObjectTag));
2828
2829  // Load the OSR entrypoint offset from the deoptimization data.
2830  __ mov(ecx, Operand(ecx, FixedArray::OffsetOfElementAt(
2831                               DeoptimizationData::kOsrPcOffsetIndex) -
2832                               kHeapObjectTag));
2833  __ SmiUntag(ecx);
2834
2835  // Compute the target address = code_obj + header_size + osr_offset
2836  __ lea(eax, Operand(eax, ecx, times_1, Code::kHeaderSize - kHeapObjectTag));
2837
2838  Generate_OSREntry(masm, eax);
2839}
2840
2841}  // namespace
2842
2843void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) {
2844  return OnStackReplacement(masm, true);
2845}
2846
2847void Builtins::Generate_BaselineOnStackReplacement(MacroAssembler* masm) {
2848  __ mov(kContextRegister,
2849         MemOperand(ebp, BaselineFrameConstants::kContextOffset));
2850  return OnStackReplacement(masm, false);
2851}
2852
2853#if V8_ENABLE_WEBASSEMBLY
2854void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
2855  // The function index was put in edi by the jump table trampoline.
2856  // Convert to Smi for the runtime call.
2857  __ SmiTag(kWasmCompileLazyFuncIndexRegister);
2858  {
2859    HardAbortScope hard_abort(masm);  // Avoid calls to Abort.
2860    FrameScope scope(masm, StackFrame::WASM_COMPILE_LAZY);
2861
2862    // Save all parameter registers (see wasm-linkage.h). They might be
2863    // overwritten in the runtime call below. We don't have any callee-saved
2864    // registers in wasm, so no need to store anything else.
2865    static_assert(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs ==
2866                      arraysize(wasm::kGpParamRegisters),
2867                  "frame size mismatch");
2868    for (Register reg : wasm::kGpParamRegisters) {
2869      __ Push(reg);
2870    }
2871    static_assert(WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs ==
2872                      arraysize(wasm::kFpParamRegisters),
2873                  "frame size mismatch");
2874    __ AllocateStackSpace(kSimd128Size * arraysize(wasm::kFpParamRegisters));
2875    int offset = 0;
2876    for (DoubleRegister reg : wasm::kFpParamRegisters) {
2877      __ movdqu(Operand(esp, offset), reg);
2878      offset += kSimd128Size;
2879    }
2880
2881    // Push the Wasm instance for loading the jump table address after the
2882    // runtime call.
2883    __ Push(kWasmInstanceRegister);
2884
2885    // Push the Wasm instance again as an explicit argument to the runtime
2886    // function.
2887    __ Push(kWasmInstanceRegister);
2888    // Push the function index as second argument.
2889    __ Push(kWasmCompileLazyFuncIndexRegister);
2890    // Initialize the JavaScript context with 0. CEntry will use it to
2891    // set the current context on the isolate.
2892    __ Move(kContextRegister, Smi::zero());
2893    __ CallRuntime(Runtime::kWasmCompileLazy, 2);
2894    // The runtime function returns the jump table slot offset as a Smi. Use
2895    // that to compute the jump target in edi.
2896    __ Pop(kWasmInstanceRegister);
2897    __ mov(edi, MemOperand(kWasmInstanceRegister,
2898                           WasmInstanceObject::kJumpTableStartOffset -
2899                               kHeapObjectTag));
2900    __ SmiUntag(kReturnRegister0);
2901    __ add(edi, kReturnRegister0);
2902    // edi now holds the jump table slot where we want to jump to in the end.
2903
2904    // Restore registers.
2905    for (DoubleRegister reg : base::Reversed(wasm::kFpParamRegisters)) {
2906      offset -= kSimd128Size;
2907      __ movdqu(reg, Operand(esp, offset));
2908    }
2909    DCHECK_EQ(0, offset);
2910    __ add(esp, Immediate(kSimd128Size * arraysize(wasm::kFpParamRegisters)));
2911    for (Register reg : base::Reversed(wasm::kGpParamRegisters)) {
2912      __ Pop(reg);
2913    }
2914  }
2915
2916  // Finally, jump to the jump table slot for the function.
2917  __ jmp(edi);
2918}
2919
2920void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
2921  HardAbortScope hard_abort(masm);  // Avoid calls to Abort.
2922  {
2923    FrameScope scope(masm, StackFrame::WASM_DEBUG_BREAK);
2924
2925    // Save all parameter registers. They might hold live values, we restore
2926    // them after the runtime call.
2927    for (Register reg :
2928         base::Reversed(WasmDebugBreakFrameConstants::kPushedGpRegs)) {
2929      __ Push(reg);
2930    }
2931
2932    constexpr int kFpStackSize =
2933        kSimd128Size * WasmDebugBreakFrameConstants::kNumPushedFpRegisters;
2934    __ AllocateStackSpace(kFpStackSize);
2935    int offset = kFpStackSize;
2936    for (DoubleRegister reg :
2937         base::Reversed(WasmDebugBreakFrameConstants::kPushedFpRegs)) {
2938      offset -= kSimd128Size;
2939      __ movdqu(Operand(esp, offset), reg);
2940    }
2941
2942    // Initialize the JavaScript context with 0. CEntry will use it to
2943    // set the current context on the isolate.
2944    __ Move(kContextRegister, Smi::zero());
2945    __ CallRuntime(Runtime::kWasmDebugBreak, 0);
2946
2947    // Restore registers.
2948    for (DoubleRegister reg : WasmDebugBreakFrameConstants::kPushedFpRegs) {
2949      __ movdqu(reg, Operand(esp, offset));
2950      offset += kSimd128Size;
2951    }
2952    __ add(esp, Immediate(kFpStackSize));
2953    for (Register reg : WasmDebugBreakFrameConstants::kPushedGpRegs) {
2954      __ Pop(reg);
2955    }
2956  }
2957
2958  __ ret(0);
2959}
2960
2961void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) {
2962  // TODO(v8:10701): Implement for this platform.
2963  __ Trap();
2964}
2965
2966void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) {
2967  // TODO(v8:12191): Implement for this platform.
2968  __ Trap();
2969}
2970
2971void Builtins::Generate_WasmSuspend(MacroAssembler* masm) {
2972  // TODO(v8:12191): Implement for this platform.
2973  __ Trap();
2974}
2975
2976void Builtins::Generate_WasmResume(MacroAssembler* masm) {
2977  // TODO(v8:12191): Implement for this platform.
2978  __ Trap();
2979}
2980
2981void Builtins::Generate_WasmOnStackReplace(MacroAssembler* masm) {
2982  // Only needed on x64.
2983  __ Trap();
2984}
2985#endif  // V8_ENABLE_WEBASSEMBLY
2986
2987void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
2988                               SaveFPRegsMode save_doubles, ArgvMode argv_mode,
2989                               bool builtin_exit_frame) {
2990  // eax: number of arguments including receiver
2991  // edx: pointer to C function
2992  // ebp: frame pointer  (restored after C call)
2993  // esp: stack pointer  (restored after C call)
2994  // esi: current context (C callee-saved)
2995  // edi: JS function of the caller (C callee-saved)
2996  //
2997  // If argv_mode == ArgvMode::kRegister:
2998  // ecx: pointer to the first argument
2999
3000  STATIC_ASSERT(eax == kRuntimeCallArgCountRegister);
3001  STATIC_ASSERT(ecx == kRuntimeCallArgvRegister);
3002  STATIC_ASSERT(edx == kRuntimeCallFunctionRegister);
3003  STATIC_ASSERT(esi == kContextRegister);
3004  STATIC_ASSERT(edi == kJSFunctionRegister);
3005
3006  DCHECK(!AreAliased(kRuntimeCallArgCountRegister, kRuntimeCallArgvRegister,
3007                     kRuntimeCallFunctionRegister, kContextRegister,
3008                     kJSFunctionRegister, kRootRegister));
3009
3010  // Reserve space on the stack for the three arguments passed to the call. If
3011  // result size is greater than can be returned in registers, also reserve
3012  // space for the hidden argument for the result location, and space for the
3013  // result itself.
3014  int arg_stack_space = 3;
3015
3016  // Enter the exit frame that transitions from JavaScript to C++.
3017  if (argv_mode == ArgvMode::kRegister) {
3018    DCHECK(save_doubles == SaveFPRegsMode::kIgnore);
3019    DCHECK(!builtin_exit_frame);
3020    __ EnterApiExitFrame(arg_stack_space, edi);
3021
3022    // Move argc and argv into the correct registers.
3023    __ mov(esi, ecx);
3024    __ mov(edi, eax);
3025  } else {
3026    __ EnterExitFrame(
3027        arg_stack_space, save_doubles == SaveFPRegsMode::kSave,
3028        builtin_exit_frame ? StackFrame::BUILTIN_EXIT : StackFrame::EXIT);
3029  }
3030
3031  // edx: pointer to C function
3032  // ebp: frame pointer  (restored after C call)
3033  // esp: stack pointer  (restored after C call)
3034  // edi: number of arguments including receiver  (C callee-saved)
3035  // esi: pointer to the first argument (C callee-saved)
3036
3037  // Result returned in eax, or eax+edx if result size is 2.
3038
3039  // Check stack alignment.
3040  if (FLAG_debug_code) {
3041    __ CheckStackAlignment();
3042  }
3043  // Call C function.
3044  __ mov(Operand(esp, 0 * kSystemPointerSize), edi);  // argc.
3045  __ mov(Operand(esp, 1 * kSystemPointerSize), esi);  // argv.
3046  __ Move(ecx, Immediate(ExternalReference::isolate_address(masm->isolate())));
3047  __ mov(Operand(esp, 2 * kSystemPointerSize), ecx);
3048  __ call(kRuntimeCallFunctionRegister);
3049
3050  // Result is in eax or edx:eax - do not destroy these registers!
3051
3052  // Check result for exception sentinel.
3053  Label exception_returned;
3054  __ CompareRoot(eax, RootIndex::kException);
3055  __ j(equal, &exception_returned);
3056
3057  // Check that there is no pending exception, otherwise we
3058  // should have returned the exception sentinel.
3059  if (FLAG_debug_code) {
3060    __ push(edx);
3061    __ LoadRoot(edx, RootIndex::kTheHoleValue);
3062    Label okay;
3063    ExternalReference pending_exception_address = ExternalReference::Create(
3064        IsolateAddressId::kPendingExceptionAddress, masm->isolate());
3065    __ cmp(edx, __ ExternalReferenceAsOperand(pending_exception_address, ecx));
3066    // Cannot use check here as it attempts to generate call into runtime.
3067    __ j(equal, &okay, Label::kNear);
3068    __ int3();
3069    __ bind(&okay);
3070    __ pop(edx);
3071  }
3072
3073  // Exit the JavaScript to C++ exit frame.
3074  __ LeaveExitFrame(save_doubles == SaveFPRegsMode::kSave,
3075                    argv_mode == ArgvMode::kStack);
3076  __ ret(0);
3077
3078  // Handling of exception.
3079  __ bind(&exception_returned);
3080
3081  ExternalReference pending_handler_context_address = ExternalReference::Create(
3082      IsolateAddressId::kPendingHandlerContextAddress, masm->isolate());
3083  ExternalReference pending_handler_entrypoint_address =
3084      ExternalReference::Create(
3085          IsolateAddressId::kPendingHandlerEntrypointAddress, masm->isolate());
3086  ExternalReference pending_handler_fp_address = ExternalReference::Create(
3087      IsolateAddressId::kPendingHandlerFPAddress, masm->isolate());
3088  ExternalReference pending_handler_sp_address = ExternalReference::Create(
3089      IsolateAddressId::kPendingHandlerSPAddress, masm->isolate());
3090
3091  // Ask the runtime for help to determine the handler. This will set eax to
3092  // contain the current pending exception, don't clobber it.
3093  ExternalReference find_handler =
3094      ExternalReference::Create(Runtime::kUnwindAndFindExceptionHandler);
3095  {
3096    FrameScope scope(masm, StackFrame::MANUAL);
3097    __ PrepareCallCFunction(3, eax);
3098    __ mov(Operand(esp, 0 * kSystemPointerSize), Immediate(0));  // argc.
3099    __ mov(Operand(esp, 1 * kSystemPointerSize), Immediate(0));  // argv.
3100    __ Move(esi,
3101            Immediate(ExternalReference::isolate_address(masm->isolate())));
3102    __ mov(Operand(esp, 2 * kSystemPointerSize), esi);
3103    __ CallCFunction(find_handler, 3);
3104  }
3105
3106  // Retrieve the handler context, SP and FP.
3107  __ mov(esp, __ ExternalReferenceAsOperand(pending_handler_sp_address, esi));
3108  __ mov(ebp, __ ExternalReferenceAsOperand(pending_handler_fp_address, esi));
3109  __ mov(esi,
3110         __ ExternalReferenceAsOperand(pending_handler_context_address, esi));
3111
3112  // If the handler is a JS frame, restore the context to the frame. Note that
3113  // the context will be set to (esi == 0) for non-JS frames.
3114  Label skip;
3115  __ test(esi, esi);
3116  __ j(zero, &skip, Label::kNear);
3117  __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
3118  __ bind(&skip);
3119
3120  // Clear c_entry_fp, like we do in `LeaveExitFrame`.
3121  ExternalReference c_entry_fp_address = ExternalReference::Create(
3122      IsolateAddressId::kCEntryFPAddress, masm->isolate());
3123  __ mov(__ ExternalReferenceAsOperand(c_entry_fp_address, esi), Immediate(0));
3124
3125  // Compute the handler entry address and jump to it.
3126  __ mov(edi, __ ExternalReferenceAsOperand(pending_handler_entrypoint_address,
3127                                            edi));
3128  __ jmp(edi);
3129}
3130
3131void Builtins::Generate_DoubleToI(MacroAssembler* masm) {
3132  Label check_negative, process_64_bits, done;
3133
3134  // Account for return address and saved regs.
3135  const int kArgumentOffset = 4 * kSystemPointerSize;
3136
3137  MemOperand mantissa_operand(MemOperand(esp, kArgumentOffset));
3138  MemOperand exponent_operand(
3139      MemOperand(esp, kArgumentOffset + kDoubleSize / 2));
3140
3141  // The result is returned on the stack.
3142  MemOperand return_operand = mantissa_operand;
3143
3144  Register scratch1 = ebx;
3145
3146  // Since we must use ecx for shifts below, use some other register (eax)
3147  // to calculate the result.
3148  Register result_reg = eax;
3149  // Save ecx if it isn't the return register and therefore volatile, or if it
3150  // is the return register, then save the temp register we use in its stead for
3151  // the result.
3152  Register save_reg = eax;
3153  __ push(ecx);
3154  __ push(scratch1);
3155  __ push(save_reg);
3156
3157  __ mov(scratch1, mantissa_operand);
3158  if (CpuFeatures::IsSupported(SSE3)) {
3159    CpuFeatureScope scope(masm, SSE3);
3160    // Load x87 register with heap number.
3161    __ fld_d(mantissa_operand);
3162  }
3163  __ mov(ecx, exponent_operand);
3164
3165  __ and_(ecx, HeapNumber::kExponentMask);
3166  __ shr(ecx, HeapNumber::kExponentShift);
3167  __ lea(result_reg, MemOperand(ecx, -HeapNumber::kExponentBias));
3168  __ cmp(result_reg, Immediate(HeapNumber::kMantissaBits));
3169  __ j(below, &process_64_bits);
3170
3171  // Result is entirely in lower 32-bits of mantissa
3172  int delta =
3173      HeapNumber::kExponentBias + base::Double::kPhysicalSignificandSize;
3174  if (CpuFeatures::IsSupported(SSE3)) {
3175    __ fstp(0);
3176  }
3177  __ sub(ecx, Immediate(delta));
3178  __ xor_(result_reg, result_reg);
3179  __ cmp(ecx, Immediate(31));
3180  __ j(above, &done);
3181  __ shl_cl(scratch1);
3182  __ jmp(&check_negative);
3183
3184  __ bind(&process_64_bits);
3185  if (CpuFeatures::IsSupported(SSE3)) {
3186    CpuFeatureScope scope(masm, SSE3);
3187    // Reserve space for 64 bit answer.
3188    __ AllocateStackSpace(kDoubleSize);  // Nolint.
3189    // Do conversion, which cannot fail because we checked the exponent.
3190    __ fisttp_d(Operand(esp, 0));
3191    __ mov(result_reg, Operand(esp, 0));  // Load low word of answer as result
3192    __ add(esp, Immediate(kDoubleSize));
3193    __ jmp(&done);
3194  } else {
3195    // Result must be extracted from shifted 32-bit mantissa
3196    __ sub(ecx, Immediate(delta));
3197    __ neg(ecx);
3198    __ mov(result_reg, exponent_operand);
3199    __ and_(
3200        result_reg,
3201        Immediate(static_cast<uint32_t>(base::Double::kSignificandMask >> 32)));
3202    __ add(result_reg,
3203           Immediate(static_cast<uint32_t>(base::Double::kHiddenBit >> 32)));
3204    __ shrd_cl(scratch1, result_reg);
3205    __ shr_cl(result_reg);
3206    __ test(ecx, Immediate(32));
3207    __ cmov(not_equal, scratch1, result_reg);
3208  }
3209
3210  // If the double was negative, negate the integer result.
3211  __ bind(&check_negative);
3212  __ mov(result_reg, scratch1);
3213  __ neg(result_reg);
3214  __ cmp(exponent_operand, Immediate(0));
3215  __ cmov(greater, result_reg, scratch1);
3216
3217  // Restore registers
3218  __ bind(&done);
3219  __ mov(return_operand, result_reg);
3220  __ pop(save_reg);
3221  __ pop(scratch1);
3222  __ pop(ecx);
3223  __ ret(0);
3224}
3225
3226namespace {
3227
3228// Generates an Operand for saving parameters after PrepareCallApiFunction.
3229Operand ApiParameterOperand(int index) {
3230  return Operand(esp, index * kSystemPointerSize);
3231}
3232
3233// Prepares stack to put arguments (aligns and so on). Reserves
3234// space for return value if needed (assumes the return value is a handle).
3235// Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1)
3236// etc. Saves context (esi). If space was reserved for return value then
3237// stores the pointer to the reserved slot into esi.
3238void PrepareCallApiFunction(MacroAssembler* masm, int argc, Register scratch) {
3239  ASM_CODE_COMMENT(masm);
3240  __ EnterApiExitFrame(argc, scratch);
3241  if (FLAG_debug_code) {
3242    __ mov(esi, Immediate(bit_cast<int32_t>(kZapValue)));
3243  }
3244}
3245
3246// Calls an API function.  Allocates HandleScope, extracts returned value
3247// from handle and propagates exceptions.  Clobbers esi, edi and
3248// caller-save registers.  Restores context.  On return removes
3249// stack_space * kSystemPointerSize (GCed).
3250void CallApiFunctionAndReturn(MacroAssembler* masm, Register function_address,
3251                              ExternalReference thunk_ref,
3252                              Operand thunk_last_arg, int stack_space,
3253                              Operand* stack_space_operand,
3254                              Operand return_value_operand) {
3255  Isolate* isolate = masm->isolate();
3256
3257  ExternalReference next_address =
3258      ExternalReference::handle_scope_next_address(isolate);
3259  ExternalReference limit_address =
3260      ExternalReference::handle_scope_limit_address(isolate);
3261  ExternalReference level_address =
3262      ExternalReference::handle_scope_level_address(isolate);
3263
3264  DCHECK(edx == function_address);
3265  // Allocate HandleScope in callee-save registers.
3266  __ add(__ ExternalReferenceAsOperand(level_address, esi), Immediate(1));
3267  __ mov(esi, __ ExternalReferenceAsOperand(next_address, esi));
3268  __ mov(edi, __ ExternalReferenceAsOperand(limit_address, edi));
3269
3270  Label profiler_enabled, end_profiler_check;
3271  __ Move(eax, Immediate(ExternalReference::is_profiling_address(isolate)));
3272  __ cmpb(Operand(eax, 0), Immediate(0));
3273  __ j(not_zero, &profiler_enabled);
3274  __ Move(eax, Immediate(ExternalReference::address_of_runtime_stats_flag()));
3275  __ cmp(Operand(eax, 0), Immediate(0));
3276  __ j(not_zero, &profiler_enabled);
3277  {
3278    // Call the api function directly.
3279    __ mov(eax, function_address);
3280    __ jmp(&end_profiler_check);
3281  }
3282  __ bind(&profiler_enabled);
3283  {
3284    // Additional parameter is the address of the actual getter function.
3285    __ mov(thunk_last_arg, function_address);
3286    __ Move(eax, Immediate(thunk_ref));
3287  }
3288  __ bind(&end_profiler_check);
3289
3290  // Call the api function.
3291  __ call(eax);
3292
3293  Label prologue;
3294  // Load the value from ReturnValue
3295  __ mov(eax, return_value_operand);
3296
3297  Label promote_scheduled_exception;
3298  Label delete_allocated_handles;
3299  Label leave_exit_frame;
3300
3301  __ bind(&prologue);
3302  // No more valid handles (the result handle was the last one). Restore
3303  // previous handle scope.
3304  __ mov(__ ExternalReferenceAsOperand(next_address, ecx), esi);
3305  __ sub(__ ExternalReferenceAsOperand(level_address, ecx), Immediate(1));
3306  __ Assert(above_equal, AbortReason::kInvalidHandleScopeLevel);
3307  __ cmp(edi, __ ExternalReferenceAsOperand(limit_address, ecx));
3308  __ j(not_equal, &delete_allocated_handles);
3309
3310  // Leave the API exit frame.
3311  __ bind(&leave_exit_frame);
3312  if (stack_space_operand != nullptr) {
3313    DCHECK_EQ(stack_space, 0);
3314    __ mov(edx, *stack_space_operand);
3315  }
3316  __ LeaveApiExitFrame();
3317
3318  // Check if the function scheduled an exception.
3319  ExternalReference scheduled_exception_address =
3320      ExternalReference::scheduled_exception_address(isolate);
3321  __ mov(ecx, __ ExternalReferenceAsOperand(scheduled_exception_address, ecx));
3322  __ CompareRoot(ecx, RootIndex::kTheHoleValue);
3323  __ j(not_equal, &promote_scheduled_exception);
3324
3325#if DEBUG
3326  // Check if the function returned a valid JavaScript value.
3327  Label ok;
3328  Register return_value = eax;
3329  Register map = ecx;
3330
3331  __ JumpIfSmi(return_value, &ok, Label::kNear);
3332  __ mov(map, FieldOperand(return_value, HeapObject::kMapOffset));
3333
3334  __ CmpInstanceType(map, LAST_NAME_TYPE);
3335  __ j(below_equal, &ok, Label::kNear);
3336
3337  __ CmpInstanceType(map, FIRST_JS_RECEIVER_TYPE);
3338  __ j(above_equal, &ok, Label::kNear);
3339
3340  __ CompareRoot(map, RootIndex::kHeapNumberMap);
3341  __ j(equal, &ok, Label::kNear);
3342
3343  __ CompareRoot(map, RootIndex::kBigIntMap);
3344  __ j(equal, &ok, Label::kNear);
3345
3346  __ CompareRoot(return_value, RootIndex::kUndefinedValue);
3347  __ j(equal, &ok, Label::kNear);
3348
3349  __ CompareRoot(return_value, RootIndex::kTrueValue);
3350  __ j(equal, &ok, Label::kNear);
3351
3352  __ CompareRoot(return_value, RootIndex::kFalseValue);
3353  __ j(equal, &ok, Label::kNear);
3354
3355  __ CompareRoot(return_value, RootIndex::kNullValue);
3356  __ j(equal, &ok, Label::kNear);
3357
3358  __ Abort(AbortReason::kAPICallReturnedInvalidObject);
3359
3360  __ bind(&ok);
3361#endif
3362
3363  if (stack_space_operand == nullptr) {
3364    DCHECK_NE(stack_space, 0);
3365    __ ret(stack_space * kSystemPointerSize);
3366  } else {
3367    DCHECK_EQ(0, stack_space);
3368    __ pop(ecx);
3369    __ add(esp, edx);
3370    __ jmp(ecx);
3371  }
3372
3373  // Re-throw by promoting a scheduled exception.
3374  __ bind(&promote_scheduled_exception);
3375  __ TailCallRuntime(Runtime::kPromoteScheduledException);
3376
3377  // HandleScope limit has changed. Delete allocated extensions.
3378  ExternalReference delete_extensions =
3379      ExternalReference::delete_handle_scope_extensions();
3380  __ bind(&delete_allocated_handles);
3381  __ mov(__ ExternalReferenceAsOperand(limit_address, ecx), edi);
3382  __ mov(edi, eax);
3383  __ Move(eax, Immediate(ExternalReference::isolate_address(isolate)));
3384  __ mov(Operand(esp, 0), eax);
3385  __ Move(eax, Immediate(delete_extensions));
3386  __ call(eax);
3387  __ mov(eax, edi);
3388  __ jmp(&leave_exit_frame);
3389}
3390
3391}  // namespace
3392
3393void Builtins::Generate_CallApiCallback(MacroAssembler* masm) {
3394  // ----------- S t a t e -------------
3395  //  -- esi                 : context
3396  //  -- edx                 : api function address
3397  //  -- ecx                 : arguments count (not including the receiver)
3398  //  -- eax                 : call data
3399  //  -- edi                 : holder
3400  //  -- esp[0]              : return address
3401  //  -- esp[8]              : argument 0 (receiver)
3402  //  -- esp[16]             : argument 1
3403  //  -- ...
3404  //  -- esp[argc * 8]       : argument (argc - 1)
3405  //  -- esp[(argc + 1) * 8] : argument argc
3406  // -----------------------------------
3407
3408  Register api_function_address = edx;
3409  Register argc = ecx;
3410  Register call_data = eax;
3411  Register holder = edi;
3412
3413  // Park argc in xmm0.
3414  __ movd(xmm0, argc);
3415
3416  DCHECK(!AreAliased(api_function_address, argc, holder));
3417
3418  using FCA = FunctionCallbackArguments;
3419
3420  STATIC_ASSERT(FCA::kArgsLength == 6);
3421  STATIC_ASSERT(FCA::kNewTargetIndex == 5);
3422  STATIC_ASSERT(FCA::kDataIndex == 4);
3423  STATIC_ASSERT(FCA::kReturnValueOffset == 3);
3424  STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
3425  STATIC_ASSERT(FCA::kIsolateIndex == 1);
3426  STATIC_ASSERT(FCA::kHolderIndex == 0);
3427
3428  // Set up FunctionCallbackInfo's implicit_args on the stack as follows:
3429  //
3430  // Current state:
3431  //   esp[0]: return address
3432  //
3433  // Target state:
3434  //   esp[0 * kSystemPointerSize]: return address
3435  //   esp[1 * kSystemPointerSize]: kHolder
3436  //   esp[2 * kSystemPointerSize]: kIsolate
3437  //   esp[3 * kSystemPointerSize]: undefined (kReturnValueDefaultValue)
3438  //   esp[4 * kSystemPointerSize]: undefined (kReturnValue)
3439  //   esp[5 * kSystemPointerSize]: kData
3440  //   esp[6 * kSystemPointerSize]: undefined (kNewTarget)
3441
3442  __ PopReturnAddressTo(ecx);
3443  __ PushRoot(RootIndex::kUndefinedValue);
3444  __ Push(call_data);
3445  __ PushRoot(RootIndex::kUndefinedValue);
3446  __ PushRoot(RootIndex::kUndefinedValue);
3447  __ Push(Immediate(ExternalReference::isolate_address(masm->isolate())));
3448  __ Push(holder);
3449  __ PushReturnAddressFrom(ecx);
3450
3451  // Reload argc from xmm0.
3452  __ movd(argc, xmm0);
3453
3454  // Keep a pointer to kHolder (= implicit_args) in a scratch register.
3455  // We use it below to set up the FunctionCallbackInfo object.
3456  Register scratch = eax;
3457  __ lea(scratch, Operand(esp, 1 * kSystemPointerSize));
3458
3459  // The API function takes a reference to v8::Arguments. If the CPU profiler
3460  // is enabled, a wrapper function will be called and we need to pass
3461  // the address of the callback as an additional parameter. Always allocate
3462  // space for it.
3463  static constexpr int kApiArgc = 1 + 1;
3464
3465  // Allocate the v8::Arguments structure in the arguments' space since
3466  // it's not controlled by GC.
3467  static constexpr int kApiStackSpace = 4;
3468
3469  PrepareCallApiFunction(masm, kApiArgc + kApiStackSpace, edi);
3470
3471  // FunctionCallbackInfo::implicit_args_ (points at kHolder as set up above).
3472  __ mov(ApiParameterOperand(kApiArgc + 0), scratch);
3473
3474  // FunctionCallbackInfo::values_ (points at the first varargs argument passed
3475  // on the stack).
3476  __ lea(scratch,
3477         Operand(scratch, (FCA::kArgsLength + 1) * kSystemPointerSize));
3478  __ mov(ApiParameterOperand(kApiArgc + 1), scratch);
3479
3480  // FunctionCallbackInfo::length_.
3481  __ mov(ApiParameterOperand(kApiArgc + 2), argc);
3482
3483  // We also store the number of bytes to drop from the stack after returning
3484  // from the API function here.
3485  __ lea(scratch,
3486         Operand(argc, times_system_pointer_size,
3487                 (FCA::kArgsLength + 1 /* receiver */) * kSystemPointerSize));
3488  __ mov(ApiParameterOperand(kApiArgc + 3), scratch);
3489
3490  // v8::InvocationCallback's argument.
3491  __ lea(scratch, ApiParameterOperand(kApiArgc + 0));
3492  __ mov(ApiParameterOperand(0), scratch);
3493
3494  ExternalReference thunk_ref = ExternalReference::invoke_function_callback();
3495
3496  // There are two stack slots above the arguments we constructed on the stack:
3497  // the stored ebp (pushed by EnterApiExitFrame), and the return address.
3498  static constexpr int kStackSlotsAboveFCA = 2;
3499  Operand return_value_operand(
3500      ebp,
3501      (kStackSlotsAboveFCA + FCA::kReturnValueOffset) * kSystemPointerSize);
3502
3503  static constexpr int kUseStackSpaceOperand = 0;
3504  Operand stack_space_operand = ApiParameterOperand(kApiArgc + 3);
3505  CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
3506                           ApiParameterOperand(1), kUseStackSpaceOperand,
3507                           &stack_space_operand, return_value_operand);
3508}
3509
3510void Builtins::Generate_CallApiGetter(MacroAssembler* masm) {
3511  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
3512  // name below the exit frame to make GC aware of them.
3513  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
3514  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
3515  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
3516  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
3517  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
3518  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
3519  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
3520  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
3521
3522  Register receiver = ApiGetterDescriptor::ReceiverRegister();
3523  Register holder = ApiGetterDescriptor::HolderRegister();
3524  Register callback = ApiGetterDescriptor::CallbackRegister();
3525  Register scratch = edi;
3526  DCHECK(!AreAliased(receiver, holder, callback, scratch));
3527
3528  __ pop(scratch);  // Pop return address to extend the frame.
3529  __ push(receiver);
3530  __ push(FieldOperand(callback, AccessorInfo::kDataOffset));
3531  __ PushRoot(RootIndex::kUndefinedValue);  // ReturnValue
3532  // ReturnValue default value
3533  __ PushRoot(RootIndex::kUndefinedValue);
3534  __ Push(Immediate(ExternalReference::isolate_address(masm->isolate())));
3535  __ push(holder);
3536  __ push(Immediate(Smi::zero()));  // should_throw_on_error -> false
3537  __ push(FieldOperand(callback, AccessorInfo::kNameOffset));
3538  __ push(scratch);  // Restore return address.
3539
3540  // v8::PropertyCallbackInfo::args_ array and name handle.
3541  const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
3542
3543  // Allocate v8::PropertyCallbackInfo object, arguments for callback and
3544  // space for optional callback address parameter (in case CPU profiler is
3545  // active) in non-GCed stack space.
3546  const int kApiArgc = 3 + 1;
3547
3548  PrepareCallApiFunction(masm, kApiArgc, scratch);
3549
3550  // Load address of v8::PropertyAccessorInfo::args_ array. The value in ebp
3551  // here corresponds to esp + kSystemPointerSize before PrepareCallApiFunction.
3552  __ lea(scratch, Operand(ebp, kSystemPointerSize + 2 * kSystemPointerSize));
3553  // Create v8::PropertyCallbackInfo object on the stack and initialize
3554  // it's args_ field.
3555  Operand info_object = ApiParameterOperand(3);
3556  __ mov(info_object, scratch);
3557
3558  // Name as handle.
3559  __ sub(scratch, Immediate(kSystemPointerSize));
3560  __ mov(ApiParameterOperand(0), scratch);
3561  // Arguments pointer.
3562  __ lea(scratch, info_object);
3563  __ mov(ApiParameterOperand(1), scratch);
3564  // Reserve space for optional callback address parameter.
3565  Operand thunk_last_arg = ApiParameterOperand(2);
3566
3567  ExternalReference thunk_ref =
3568      ExternalReference::invoke_accessor_getter_callback();
3569
3570  __ mov(scratch, FieldOperand(callback, AccessorInfo::kJsGetterOffset));
3571  Register function_address = edx;
3572  __ mov(function_address,
3573         FieldOperand(scratch, Foreign::kForeignAddressOffset));
3574  // +3 is to skip prolog, return address and name handle.
3575  Operand return_value_operand(
3576      ebp,
3577      (PropertyCallbackArguments::kReturnValueOffset + 3) * kSystemPointerSize);
3578  Operand* const kUseStackSpaceConstant = nullptr;
3579  CallApiFunctionAndReturn(masm, function_address, thunk_ref, thunk_last_arg,
3580                           kStackUnwindSpace, kUseStackSpaceConstant,
3581                           return_value_operand);
3582}
3583
3584void Builtins::Generate_DirectCEntry(MacroAssembler* masm) {
3585  __ int3();  // Unused on this architecture.
3586}
3587
3588namespace {
3589
3590enum Direction { FORWARD, BACKWARD };
3591enum Alignment { MOVE_ALIGNED, MOVE_UNALIGNED };
3592
3593// Expects registers:
3594// esi - source, aligned if alignment == ALIGNED
3595// edi - destination, always aligned
3596// ecx - count (copy size in bytes)
3597// edx - loop count (number of 64 byte chunks)
3598void MemMoveEmitMainLoop(MacroAssembler* masm, Label* move_last_15,
3599                         Direction direction, Alignment alignment) {
3600  ASM_CODE_COMMENT(masm);
3601  Register src = esi;
3602  Register dst = edi;
3603  Register count = ecx;
3604  Register loop_count = edx;
3605  Label loop, move_last_31, move_last_63;
3606  __ cmp(loop_count, 0);
3607  __ j(equal, &move_last_63);
3608  __ bind(&loop);
3609  // Main loop. Copy in 64 byte chunks.
3610  if (direction == BACKWARD) __ sub(src, Immediate(0x40));
3611  __ movdq(alignment == MOVE_ALIGNED, xmm0, Operand(src, 0x00));
3612  __ movdq(alignment == MOVE_ALIGNED, xmm1, Operand(src, 0x10));
3613  __ movdq(alignment == MOVE_ALIGNED, xmm2, Operand(src, 0x20));
3614  __ movdq(alignment == MOVE_ALIGNED, xmm3, Operand(src, 0x30));
3615  if (direction == FORWARD) __ add(src, Immediate(0x40));
3616  if (direction == BACKWARD) __ sub(dst, Immediate(0x40));
3617  __ movdqa(Operand(dst, 0x00), xmm0);
3618  __ movdqa(Operand(dst, 0x10), xmm1);
3619  __ movdqa(Operand(dst, 0x20), xmm2);
3620  __ movdqa(Operand(dst, 0x30), xmm3);
3621  if (direction == FORWARD) __ add(dst, Immediate(0x40));
3622  __ dec(loop_count);
3623  __ j(not_zero, &loop);
3624  // At most 63 bytes left to copy.
3625  __ bind(&move_last_63);
3626  __ test(count, Immediate(0x20));
3627  __ j(zero, &move_last_31);
3628  if (direction == BACKWARD) __ sub(src, Immediate(0x20));
3629  __ movdq(alignment == MOVE_ALIGNED, xmm0, Operand(src, 0x00));
3630  __ movdq(alignment == MOVE_ALIGNED, xmm1, Operand(src, 0x10));
3631  if (direction == FORWARD) __ add(src, Immediate(0x20));
3632  if (direction == BACKWARD) __ sub(dst, Immediate(0x20));
3633  __ movdqa(Operand(dst, 0x00), xmm0);
3634  __ movdqa(Operand(dst, 0x10), xmm1);
3635  if (direction == FORWARD) __ add(dst, Immediate(0x20));
3636  // At most 31 bytes left to copy.
3637  __ bind(&move_last_31);
3638  __ test(count, Immediate(0x10));
3639  __ j(zero, move_last_15);
3640  if (direction == BACKWARD) __ sub(src, Immediate(0x10));
3641  __ movdq(alignment == MOVE_ALIGNED, xmm0, Operand(src, 0));
3642  if (direction == FORWARD) __ add(src, Immediate(0x10));
3643  if (direction == BACKWARD) __ sub(dst, Immediate(0x10));
3644  __ movdqa(Operand(dst, 0), xmm0);
3645  if (direction == FORWARD) __ add(dst, Immediate(0x10));
3646}
3647
3648void MemMoveEmitPopAndReturn(MacroAssembler* masm) {
3649  __ pop(esi);
3650  __ pop(edi);
3651  __ ret(0);
3652}
3653
3654}  // namespace
3655
3656void Builtins::Generate_MemMove(MacroAssembler* masm) {
3657  // Generated code is put into a fixed, unmovable buffer, and not into
3658  // the V8 heap. We can't, and don't, refer to any relocatable addresses
3659  // (e.g. the JavaScript nan-object).
3660
3661  // 32-bit C declaration function calls pass arguments on stack.
3662
3663  // Stack layout:
3664  // esp[12]: Third argument, size.
3665  // esp[8]: Second argument, source pointer.
3666  // esp[4]: First argument, destination pointer.
3667  // esp[0]: return address
3668
3669  const int kDestinationOffset = 1 * kSystemPointerSize;
3670  const int kSourceOffset = 2 * kSystemPointerSize;
3671  const int kSizeOffset = 3 * kSystemPointerSize;
3672
3673  // When copying up to this many bytes, use special "small" handlers.
3674  const size_t kSmallCopySize = 8;
3675  // When copying up to this many bytes, use special "medium" handlers.
3676  const size_t kMediumCopySize = 63;
3677  // When non-overlapping region of src and dst is less than this,
3678  // use a more careful implementation (slightly slower).
3679  const size_t kMinMoveDistance = 16;
3680  // Note that these values are dictated by the implementation below,
3681  // do not just change them and hope things will work!
3682
3683  int stack_offset = 0;  // Update if we change the stack height.
3684
3685  Label backward, backward_much_overlap;
3686  Label forward_much_overlap, small_size, medium_size, pop_and_return;
3687  __ push(edi);
3688  __ push(esi);
3689  stack_offset += 2 * kSystemPointerSize;
3690  Register dst = edi;
3691  Register src = esi;
3692  Register count = ecx;
3693  Register loop_count = edx;
3694  __ mov(dst, Operand(esp, stack_offset + kDestinationOffset));
3695  __ mov(src, Operand(esp, stack_offset + kSourceOffset));
3696  __ mov(count, Operand(esp, stack_offset + kSizeOffset));
3697
3698  __ cmp(dst, src);
3699  __ j(equal, &pop_and_return);
3700
3701  __ prefetch(Operand(src, 0), 1);
3702  __ cmp(count, kSmallCopySize);
3703  __ j(below_equal, &small_size);
3704  __ cmp(count, kMediumCopySize);
3705  __ j(below_equal, &medium_size);
3706  __ cmp(dst, src);
3707  __ j(above, &backward);
3708
3709  {
3710    // |dst| is a lower address than |src|. Copy front-to-back.
3711    Label unaligned_source, move_last_15, skip_last_move;
3712    __ mov(eax, src);
3713    __ sub(eax, dst);
3714    __ cmp(eax, kMinMoveDistance);
3715    __ j(below, &forward_much_overlap);
3716    // Copy first 16 bytes.
3717    __ movdqu(xmm0, Operand(src, 0));
3718    __ movdqu(Operand(dst, 0), xmm0);
3719    // Determine distance to alignment: 16 - (dst & 0xF).
3720    __ mov(edx, dst);
3721    __ and_(edx, 0xF);
3722    __ neg(edx);
3723    __ add(edx, Immediate(16));
3724    __ add(dst, edx);
3725    __ add(src, edx);
3726    __ sub(count, edx);
3727    // dst is now aligned. Main copy loop.
3728    __ mov(loop_count, count);
3729    __ shr(loop_count, 6);
3730    // Check if src is also aligned.
3731    __ test(src, Immediate(0xF));
3732    __ j(not_zero, &unaligned_source);
3733    // Copy loop for aligned source and destination.
3734    MemMoveEmitMainLoop(masm, &move_last_15, FORWARD, MOVE_ALIGNED);
3735    // At most 15 bytes to copy. Copy 16 bytes at end of string.
3736    __ bind(&move_last_15);
3737    __ and_(count, 0xF);
3738    __ j(zero, &skip_last_move, Label::kNear);
3739    __ movdqu(xmm0, Operand(src, count, times_1, -0x10));
3740    __ movdqu(Operand(dst, count, times_1, -0x10), xmm0);
3741    __ bind(&skip_last_move);
3742    MemMoveEmitPopAndReturn(masm);
3743
3744    // Copy loop for unaligned source and aligned destination.
3745    __ bind(&unaligned_source);
3746    MemMoveEmitMainLoop(masm, &move_last_15, FORWARD, MOVE_UNALIGNED);
3747    __ jmp(&move_last_15);
3748
3749    // Less than kMinMoveDistance offset between dst and src.
3750    Label loop_until_aligned, last_15_much_overlap;
3751    __ bind(&loop_until_aligned);
3752    __ mov_b(eax, Operand(src, 0));
3753    __ inc(src);
3754    __ mov_b(Operand(dst, 0), eax);
3755    __ inc(dst);
3756    __ dec(count);
3757    __ bind(&forward_much_overlap);  // Entry point into this block.
3758    __ test(dst, Immediate(0xF));
3759    __ j(not_zero, &loop_until_aligned);
3760    // dst is now aligned, src can't be. Main copy loop.
3761    __ mov(loop_count, count);
3762    __ shr(loop_count, 6);
3763    MemMoveEmitMainLoop(masm, &last_15_much_overlap, FORWARD, MOVE_UNALIGNED);
3764    __ bind(&last_15_much_overlap);
3765    __ and_(count, 0xF);
3766    __ j(zero, &pop_and_return);
3767    __ cmp(count, kSmallCopySize);
3768    __ j(below_equal, &small_size);
3769    __ jmp(&medium_size);
3770  }
3771
3772  {
3773    // |dst| is a higher address than |src|. Copy backwards.
3774    Label unaligned_source, move_first_15, skip_last_move;
3775    __ bind(&backward);
3776    // |dst| and |src| always point to the end of what's left to copy.
3777    __ add(dst, count);
3778    __ add(src, count);
3779    __ mov(eax, dst);
3780    __ sub(eax, src);
3781    __ cmp(eax, kMinMoveDistance);
3782    __ j(below, &backward_much_overlap);
3783    // Copy last 16 bytes.
3784    __ movdqu(xmm0, Operand(src, -0x10));
3785    __ movdqu(Operand(dst, -0x10), xmm0);
3786    // Find distance to alignment: dst & 0xF
3787    __ mov(edx, dst);
3788    __ and_(edx, 0xF);
3789    __ sub(dst, edx);
3790    __ sub(src, edx);
3791    __ sub(count, edx);
3792    // dst is now aligned. Main copy loop.
3793    __ mov(loop_count, count);
3794    __ shr(loop_count, 6);
3795    // Check if src is also aligned.
3796    __ test(src, Immediate(0xF));
3797    __ j(not_zero, &unaligned_source);
3798    // Copy loop for aligned source and destination.
3799    MemMoveEmitMainLoop(masm, &move_first_15, BACKWARD, MOVE_ALIGNED);
3800    // At most 15 bytes to copy. Copy 16 bytes at beginning of string.
3801    __ bind(&move_first_15);
3802    __ and_(count, 0xF);
3803    __ j(zero, &skip_last_move, Label::kNear);
3804    __ sub(src, count);
3805    __ sub(dst, count);
3806    __ movdqu(xmm0, Operand(src, 0));
3807    __ movdqu(Operand(dst, 0), xmm0);
3808    __ bind(&skip_last_move);
3809    MemMoveEmitPopAndReturn(masm);
3810
3811    // Copy loop for unaligned source and aligned destination.
3812    __ bind(&unaligned_source);
3813    MemMoveEmitMainLoop(masm, &move_first_15, BACKWARD, MOVE_UNALIGNED);
3814    __ jmp(&move_first_15);
3815
3816    // Less than kMinMoveDistance offset between dst and src.
3817    Label loop_until_aligned, first_15_much_overlap;
3818    __ bind(&loop_until_aligned);
3819    __ dec(src);
3820    __ dec(dst);
3821    __ mov_b(eax, Operand(src, 0));
3822    __ mov_b(Operand(dst, 0), eax);
3823    __ dec(count);
3824    __ bind(&backward_much_overlap);  // Entry point into this block.
3825    __ test(dst, Immediate(0xF));
3826    __ j(not_zero, &loop_until_aligned);
3827    // dst is now aligned, src can't be. Main copy loop.
3828    __ mov(loop_count, count);
3829    __ shr(loop_count, 6);
3830    MemMoveEmitMainLoop(masm, &first_15_much_overlap, BACKWARD, MOVE_UNALIGNED);
3831    __ bind(&first_15_much_overlap);
3832    __ and_(count, 0xF);
3833    __ j(zero, &pop_and_return);
3834    // Small/medium handlers expect dst/src to point to the beginning.
3835    __ sub(dst, count);
3836    __ sub(src, count);
3837    __ cmp(count, kSmallCopySize);
3838    __ j(below_equal, &small_size);
3839    __ jmp(&medium_size);
3840  }
3841  {
3842    // Special handlers for 9 <= copy_size < 64. No assumptions about
3843    // alignment or move distance, so all reads must be unaligned and
3844    // must happen before any writes.
3845    Label f9_16, f17_32, f33_48, f49_63;
3846
3847    __ bind(&f9_16);
3848    __ movsd(xmm0, Operand(src, 0));
3849    __ movsd(xmm1, Operand(src, count, times_1, -8));
3850    __ movsd(Operand(dst, 0), xmm0);
3851    __ movsd(Operand(dst, count, times_1, -8), xmm1);
3852    MemMoveEmitPopAndReturn(masm);
3853
3854    __ bind(&f17_32);
3855    __ movdqu(xmm0, Operand(src, 0));
3856    __ movdqu(xmm1, Operand(src, count, times_1, -0x10));
3857    __ movdqu(Operand(dst, 0x00), xmm0);
3858    __ movdqu(Operand(dst, count, times_1, -0x10), xmm1);
3859    MemMoveEmitPopAndReturn(masm);
3860
3861    __ bind(&f33_48);
3862    __ movdqu(xmm0, Operand(src, 0x00));
3863    __ movdqu(xmm1, Operand(src, 0x10));
3864    __ movdqu(xmm2, Operand(src, count, times_1, -0x10));
3865    __ movdqu(Operand(dst, 0x00), xmm0);
3866    __ movdqu(Operand(dst, 0x10), xmm1);
3867    __ movdqu(Operand(dst, count, times_1, -0x10), xmm2);
3868    MemMoveEmitPopAndReturn(masm);
3869
3870    __ bind(&f49_63);
3871    __ movdqu(xmm0, Operand(src, 0x00));
3872    __ movdqu(xmm1, Operand(src, 0x10));
3873    __ movdqu(xmm2, Operand(src, 0x20));
3874    __ movdqu(xmm3, Operand(src, count, times_1, -0x10));
3875    __ movdqu(Operand(dst, 0x00), xmm0);
3876    __ movdqu(Operand(dst, 0x10), xmm1);
3877    __ movdqu(Operand(dst, 0x20), xmm2);
3878    __ movdqu(Operand(dst, count, times_1, -0x10), xmm3);
3879    MemMoveEmitPopAndReturn(masm);
3880
3881    __ bind(&medium_size);  // Entry point into this block.
3882    __ mov(eax, count);
3883    __ dec(eax);
3884    __ shr(eax, 4);
3885    if (FLAG_debug_code) {
3886      Label ok;
3887      __ cmp(eax, 3);
3888      __ j(below_equal, &ok);
3889      __ int3();
3890      __ bind(&ok);
3891    }
3892
3893    // Dispatch to handlers.
3894    Label eax_is_2_or_3;
3895
3896    __ cmp(eax, 1);
3897    __ j(greater, &eax_is_2_or_3);
3898    __ j(less, &f9_16);  // eax == 0.
3899    __ jmp(&f17_32);     // eax == 1.
3900
3901    __ bind(&eax_is_2_or_3);
3902    __ cmp(eax, 3);
3903    __ j(less, &f33_48);  // eax == 2.
3904    __ jmp(&f49_63);      // eax == 3.
3905  }
3906  {
3907    // Specialized copiers for copy_size <= 8 bytes.
3908    Label f0, f1, f2, f3, f4, f5_8;
3909    __ bind(&f0);
3910    MemMoveEmitPopAndReturn(masm);
3911
3912    __ bind(&f1);
3913    __ mov_b(eax, Operand(src, 0));
3914    __ mov_b(Operand(dst, 0), eax);
3915    MemMoveEmitPopAndReturn(masm);
3916
3917    __ bind(&f2);
3918    __ mov_w(eax, Operand(src, 0));
3919    __ mov_w(Operand(dst, 0), eax);
3920    MemMoveEmitPopAndReturn(masm);
3921
3922    __ bind(&f3);
3923    __ mov_w(eax, Operand(src, 0));
3924    __ mov_b(edx, Operand(src, 2));
3925    __ mov_w(Operand(dst, 0), eax);
3926    __ mov_b(Operand(dst, 2), edx);
3927    MemMoveEmitPopAndReturn(masm);
3928
3929    __ bind(&f4);
3930    __ mov(eax, Operand(src, 0));
3931    __ mov(Operand(dst, 0), eax);
3932    MemMoveEmitPopAndReturn(masm);
3933
3934    __ bind(&f5_8);
3935    __ mov(eax, Operand(src, 0));
3936    __ mov(edx, Operand(src, count, times_1, -4));
3937    __ mov(Operand(dst, 0), eax);
3938    __ mov(Operand(dst, count, times_1, -4), edx);
3939    MemMoveEmitPopAndReturn(masm);
3940
3941    __ bind(&small_size);  // Entry point into this block.
3942    if (FLAG_debug_code) {
3943      Label ok;
3944      __ cmp(count, 8);
3945      __ j(below_equal, &ok);
3946      __ int3();
3947      __ bind(&ok);
3948    }
3949
3950    // Dispatch to handlers.
3951    Label count_is_above_3, count_is_2_or_3;
3952
3953    __ cmp(count, 3);
3954    __ j(greater, &count_is_above_3);
3955
3956    __ cmp(count, 1);
3957    __ j(greater, &count_is_2_or_3);
3958    __ j(less, &f0);  // count == 0.
3959    __ jmp(&f1);      // count == 1.
3960
3961    __ bind(&count_is_2_or_3);
3962    __ cmp(count, 3);
3963    __ j(less, &f2);  // count == 2.
3964    __ jmp(&f3);      // count == 3.
3965
3966    __ bind(&count_is_above_3);
3967    __ cmp(count, 5);
3968    __ j(less, &f4);  // count == 4.
3969    __ jmp(&f5_8);    // count in [5, 8[.
3970  }
3971
3972  __ bind(&pop_and_return);
3973  MemMoveEmitPopAndReturn(masm);
3974}
3975
3976namespace {
3977
3978void Generate_DeoptimizationEntry(MacroAssembler* masm,
3979                                  DeoptimizeKind deopt_kind) {
3980  Isolate* isolate = masm->isolate();
3981
3982  // Save all general purpose registers before messing with them.
3983  const int kNumberOfRegisters = Register::kNumRegisters;
3984
3985  const int kDoubleRegsSize = kDoubleSize * XMMRegister::kNumRegisters;
3986  __ AllocateStackSpace(kDoubleRegsSize);
3987  const RegisterConfiguration* config = RegisterConfiguration::Default();
3988  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
3989    int code = config->GetAllocatableDoubleCode(i);
3990    XMMRegister xmm_reg = XMMRegister::from_code(code);
3991    int offset = code * kDoubleSize;
3992    __ movsd(Operand(esp, offset), xmm_reg);
3993  }
3994
3995  __ pushad();
3996
3997  ExternalReference c_entry_fp_address =
3998      ExternalReference::Create(IsolateAddressId::kCEntryFPAddress, isolate);
3999  __ mov(masm->ExternalReferenceAsOperand(c_entry_fp_address, esi), ebp);
4000
4001  const int kSavedRegistersAreaSize =
4002      kNumberOfRegisters * kSystemPointerSize + kDoubleRegsSize;
4003
4004  // Get the address of the location in the code object
4005  // and compute the fp-to-sp delta in register edx.
4006  __ mov(ecx, Operand(esp, kSavedRegistersAreaSize));
4007  __ lea(edx, Operand(esp, kSavedRegistersAreaSize + 1 * kSystemPointerSize));
4008
4009  __ sub(edx, ebp);
4010  __ neg(edx);
4011
4012  // Allocate a new deoptimizer object.
4013  __ PrepareCallCFunction(5, eax);
4014  __ mov(eax, Immediate(0));
4015  Label context_check;
4016  __ mov(edi, Operand(ebp, CommonFrameConstants::kContextOrFrameTypeOffset));
4017  __ JumpIfSmi(edi, &context_check);
4018  __ mov(eax, Operand(ebp, StandardFrameConstants::kFunctionOffset));
4019  __ bind(&context_check);
4020  __ mov(Operand(esp, 0 * kSystemPointerSize), eax);  // Function.
4021  __ mov(Operand(esp, 1 * kSystemPointerSize),
4022         Immediate(static_cast<int>(deopt_kind)));
4023  __ mov(Operand(esp, 2 * kSystemPointerSize), ecx);  // Code address or 0.
4024  __ mov(Operand(esp, 3 * kSystemPointerSize), edx);  // Fp-to-sp delta.
4025  __ Move(Operand(esp, 4 * kSystemPointerSize),
4026          Immediate(ExternalReference::isolate_address(masm->isolate())));
4027  {
4028    AllowExternalCallThatCantCauseGC scope(masm);
4029    __ CallCFunction(ExternalReference::new_deoptimizer_function(), 5);
4030  }
4031
4032  // Preserve deoptimizer object in register eax and get the input
4033  // frame descriptor pointer.
4034  __ mov(esi, Operand(eax, Deoptimizer::input_offset()));
4035
4036  // Fill in the input registers.
4037  for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
4038    int offset =
4039        (i * kSystemPointerSize) + FrameDescription::registers_offset();
4040    __ pop(Operand(esi, offset));
4041  }
4042
4043  int double_regs_offset = FrameDescription::double_registers_offset();
4044  // Fill in the double input registers.
4045  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
4046    int code = config->GetAllocatableDoubleCode(i);
4047    int dst_offset = code * kDoubleSize + double_regs_offset;
4048    int src_offset = code * kDoubleSize;
4049    __ movsd(xmm0, Operand(esp, src_offset));
4050    __ movsd(Operand(esi, dst_offset), xmm0);
4051  }
4052
4053  // Clear FPU all exceptions.
4054  // TODO(ulan): Find out why the TOP register is not zero here in some cases,
4055  // and check that the generated code never deoptimizes with unbalanced stack.
4056  __ fnclex();
4057
4058  // Mark the stack as not iterable for the CPU profiler which won't be able to
4059  // walk the stack without the return address.
4060  __ mov_b(__ ExternalReferenceAsOperand(
4061               ExternalReference::stack_is_iterable_address(isolate), edx),
4062           Immediate(0));
4063
4064  // Remove the return address and the double registers.
4065  __ add(esp, Immediate(kDoubleRegsSize + 1 * kSystemPointerSize));
4066
4067  // Compute a pointer to the unwinding limit in register ecx; that is
4068  // the first stack slot not part of the input frame.
4069  __ mov(ecx, Operand(esi, FrameDescription::frame_size_offset()));
4070  __ add(ecx, esp);
4071
4072  // Unwind the stack down to - but not including - the unwinding
4073  // limit and copy the contents of the activation frame to the input
4074  // frame description.
4075  __ lea(edx, Operand(esi, FrameDescription::frame_content_offset()));
4076  Label pop_loop_header;
4077  __ jmp(&pop_loop_header);
4078  Label pop_loop;
4079  __ bind(&pop_loop);
4080  __ pop(Operand(edx, 0));
4081  __ add(edx, Immediate(sizeof(uint32_t)));
4082  __ bind(&pop_loop_header);
4083  __ cmp(ecx, esp);
4084  __ j(not_equal, &pop_loop);
4085
4086  // Compute the output frame in the deoptimizer.
4087  __ push(eax);
4088  __ PrepareCallCFunction(1, esi);
4089  __ mov(Operand(esp, 0 * kSystemPointerSize), eax);
4090  {
4091    AllowExternalCallThatCantCauseGC scope(masm);
4092    __ CallCFunction(ExternalReference::compute_output_frames_function(), 1);
4093  }
4094  __ pop(eax);
4095
4096  __ mov(esp, Operand(eax, Deoptimizer::caller_frame_top_offset()));
4097
4098  // Replace the current (input) frame with the output frames.
4099  Label outer_push_loop, inner_push_loop, outer_loop_header, inner_loop_header;
4100  // Outer loop state: eax = current FrameDescription**, edx = one
4101  // past the last FrameDescription**.
4102  __ mov(edx, Operand(eax, Deoptimizer::output_count_offset()));
4103  __ mov(eax, Operand(eax, Deoptimizer::output_offset()));
4104  __ lea(edx, Operand(eax, edx, times_system_pointer_size, 0));
4105  __ jmp(&outer_loop_header);
4106  __ bind(&outer_push_loop);
4107  // Inner loop state: esi = current FrameDescription*, ecx = loop
4108  // index.
4109  __ mov(esi, Operand(eax, 0));
4110  __ mov(ecx, Operand(esi, FrameDescription::frame_size_offset()));
4111  __ jmp(&inner_loop_header);
4112  __ bind(&inner_push_loop);
4113  __ sub(ecx, Immediate(sizeof(uint32_t)));
4114  __ push(Operand(esi, ecx, times_1, FrameDescription::frame_content_offset()));
4115  __ bind(&inner_loop_header);
4116  __ test(ecx, ecx);
4117  __ j(not_zero, &inner_push_loop);
4118  __ add(eax, Immediate(kSystemPointerSize));
4119  __ bind(&outer_loop_header);
4120  __ cmp(eax, edx);
4121  __ j(below, &outer_push_loop);
4122
4123  // In case of a failed STUB, we have to restore the XMM registers.
4124  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
4125    int code = config->GetAllocatableDoubleCode(i);
4126    XMMRegister xmm_reg = XMMRegister::from_code(code);
4127    int src_offset = code * kDoubleSize + double_regs_offset;
4128    __ movsd(xmm_reg, Operand(esi, src_offset));
4129  }
4130
4131  // Push pc and continuation from the last output frame.
4132  __ push(Operand(esi, FrameDescription::pc_offset()));
4133  __ push(Operand(esi, FrameDescription::continuation_offset()));
4134
4135  // Push the registers from the last output frame.
4136  for (int i = 0; i < kNumberOfRegisters; i++) {
4137    int offset =
4138        (i * kSystemPointerSize) + FrameDescription::registers_offset();
4139    __ push(Operand(esi, offset));
4140  }
4141
4142  __ mov_b(__ ExternalReferenceAsOperand(
4143               ExternalReference::stack_is_iterable_address(isolate), edx),
4144           Immediate(1));
4145
4146  // Restore the registers from the stack.
4147  __ popad();
4148
4149  __ InitializeRootRegister();
4150
4151  // Return to the continuation point.
4152  __ ret(0);
4153}
4154
4155}  // namespace
4156
4157void Builtins::Generate_DeoptimizationEntry_Eager(MacroAssembler* masm) {
4158  Generate_DeoptimizationEntry(masm, DeoptimizeKind::kEager);
4159}
4160
4161void Builtins::Generate_DeoptimizationEntry_Lazy(MacroAssembler* masm) {
4162  Generate_DeoptimizationEntry(masm, DeoptimizeKind::kLazy);
4163}
4164
4165void Builtins::Generate_DeoptimizationEntry_Unused(MacroAssembler* masm) {
4166  Generate_DeoptimizationEntry(masm, DeoptimizeKind::kUnused);
4167}
4168
4169namespace {
4170
4171// Restarts execution either at the current or next (in execution order)
4172// bytecode. If there is baseline code on the shared function info, converts an
4173// interpreter frame into a baseline frame and continues execution in baseline
4174// code. Otherwise execution continues with bytecode.
4175void Generate_BaselineOrInterpreterEntry(MacroAssembler* masm,
4176                                         bool next_bytecode,
4177                                         bool is_osr = false) {
4178  Label start;
4179  __ bind(&start);
4180
4181  // Spill the accumulator register; note that we're not within a frame, so we
4182  // have to make sure to pop it before doing any GC-visible calls.
4183  __ push(kInterpreterAccumulatorRegister);
4184
4185  // Get function from the frame.
4186  Register closure = eax;
4187  __ mov(closure, MemOperand(ebp, StandardFrameConstants::kFunctionOffset));
4188
4189  // Get the Code object from the shared function info.
4190  Register code_obj = esi;
4191  __ mov(code_obj,
4192         FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset));
4193  __ mov(code_obj,
4194         FieldOperand(code_obj, SharedFunctionInfo::kFunctionDataOffset));
4195
4196  // Check if we have baseline code. For OSR entry it is safe to assume we
4197  // always have baseline code.
4198  if (!is_osr) {
4199    Label start_with_baseline;
4200    __ CmpObjectType(code_obj, CODET_TYPE, kInterpreterBytecodeOffsetRegister);
4201    __ j(equal, &start_with_baseline);
4202
4203    // Start with bytecode as there is no baseline code.
4204    __ pop(kInterpreterAccumulatorRegister);
4205    Builtin builtin_id = next_bytecode
4206                             ? Builtin::kInterpreterEnterAtNextBytecode
4207                             : Builtin::kInterpreterEnterAtBytecode;
4208    __ Jump(masm->isolate()->builtins()->code_handle(builtin_id),
4209            RelocInfo::CODE_TARGET);
4210
4211    __ bind(&start_with_baseline);
4212  } else if (FLAG_debug_code) {
4213    __ CmpObjectType(code_obj, CODET_TYPE, kInterpreterBytecodeOffsetRegister);
4214    __ Assert(equal, AbortReason::kExpectedBaselineData);
4215  }
4216
4217  if (FLAG_debug_code) {
4218    AssertCodeIsBaseline(masm, code_obj, ecx);
4219  }
4220
4221  // Load the feedback vector.
4222  Register feedback_vector = ecx;
4223  __ mov(feedback_vector,
4224         FieldOperand(closure, JSFunction::kFeedbackCellOffset));
4225  __ mov(feedback_vector, FieldOperand(feedback_vector, Cell::kValueOffset));
4226
4227  Label install_baseline_code;
4228  // Check if feedback vector is valid. If not, call prepare for baseline to
4229  // allocate it.
4230  __ CmpObjectType(feedback_vector, FEEDBACK_VECTOR_TYPE,
4231                   kInterpreterBytecodeOffsetRegister);
4232  __ j(not_equal, &install_baseline_code);
4233
4234  // Save BytecodeOffset from the stack frame.
4235  __ mov(kInterpreterBytecodeOffsetRegister,
4236         MemOperand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
4237  __ SmiUntag(kInterpreterBytecodeOffsetRegister);
4238  // Replace BytecodeOffset with the feedback vector.
4239  __ mov(MemOperand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp),
4240         feedback_vector);
4241  feedback_vector = no_reg;
4242
4243  // Compute baseline pc for bytecode offset.
4244  ExternalReference get_baseline_pc_extref;
4245  if (next_bytecode || is_osr) {
4246    get_baseline_pc_extref =
4247        ExternalReference::baseline_pc_for_next_executed_bytecode();
4248  } else {
4249    get_baseline_pc_extref =
4250        ExternalReference::baseline_pc_for_bytecode_offset();
4251  }
4252  Register get_baseline_pc = ecx;
4253  __ LoadAddress(get_baseline_pc, get_baseline_pc_extref);
4254
4255  // If the code deoptimizes during the implicit function entry stack interrupt
4256  // check, it will have a bailout ID of kFunctionEntryBytecodeOffset, which is
4257  // not a valid bytecode offset.
4258  // TODO(pthier): Investigate if it is feasible to handle this special case
4259  // in TurboFan instead of here.
4260  Label valid_bytecode_offset, function_entry_bytecode;
4261  if (!is_osr) {
4262    __ cmp(kInterpreterBytecodeOffsetRegister,
4263           Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag +
4264                     kFunctionEntryBytecodeOffset));
4265    __ j(equal, &function_entry_bytecode);
4266  }
4267
4268  __ sub(kInterpreterBytecodeOffsetRegister,
4269         Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
4270
4271  __ bind(&valid_bytecode_offset);
4272  // Get bytecode array from the stack frame.
4273  __ mov(kInterpreterBytecodeArrayRegister,
4274         MemOperand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp));
4275  {
4276    FrameScope scope(masm, StackFrame::INTERNAL);
4277    __ PrepareCallCFunction(3, eax);
4278    __ mov(Operand(esp, 0 * kSystemPointerSize), code_obj);
4279    __ mov(Operand(esp, 1 * kSystemPointerSize),
4280           kInterpreterBytecodeOffsetRegister);
4281    __ mov(Operand(esp, 2 * kSystemPointerSize),
4282           kInterpreterBytecodeArrayRegister);
4283    __ CallCFunction(get_baseline_pc, 3);
4284  }
4285  __ lea(code_obj,
4286         FieldOperand(code_obj, kReturnRegister0, times_1, Code::kHeaderSize));
4287  __ pop(kInterpreterAccumulatorRegister);
4288
4289  if (is_osr) {
4290    // TODO(pthier): Separate baseline Sparkplug from TF arming and don't
4291    // disarm Sparkplug here.
4292    ResetBytecodeAgeAndOsrState(masm, kInterpreterBytecodeArrayRegister);
4293    Generate_OSREntry(masm, code_obj);
4294  } else {
4295    __ jmp(code_obj);
4296  }
4297  __ Trap();  // Unreachable.
4298
4299  if (!is_osr) {
4300    __ bind(&function_entry_bytecode);
4301    // If the bytecode offset is kFunctionEntryOffset, get the start address of
4302    // the first bytecode.
4303    __ mov(kInterpreterBytecodeOffsetRegister, Immediate(0));
4304    if (next_bytecode) {
4305      __ LoadAddress(get_baseline_pc,
4306                     ExternalReference::baseline_pc_for_bytecode_offset());
4307    }
4308    __ jmp(&valid_bytecode_offset);
4309  }
4310
4311  __ bind(&install_baseline_code);
4312  // Pop/re-push the accumulator so that it's spilled within the below frame
4313  // scope, to keep the stack valid. Use ecx for this -- we can't save it in
4314  // kInterpreterAccumulatorRegister because that aliases with closure.
4315  DCHECK(!AreAliased(ecx, kContextRegister, closure));
4316  __ pop(ecx);
4317  // Restore the clobbered context register.
4318  __ mov(kContextRegister,
4319         Operand(ebp, StandardFrameConstants::kContextOffset));
4320  {
4321    FrameScope scope(masm, StackFrame::INTERNAL);
4322    __ Push(ecx);
4323    __ Push(closure);
4324    __ CallRuntime(Runtime::kInstallBaselineCode, 1);
4325    // Now that we're restarting, we don't have to worry about closure and
4326    // accumulator aliasing, so pop the spilled accumulator directly back into
4327    // the right register.
4328    __ Pop(kInterpreterAccumulatorRegister);
4329  }
4330  // Retry from the start after installing baseline code.
4331  __ jmp(&start);
4332}
4333
4334}  // namespace
4335
4336void Builtins::Generate_BaselineOrInterpreterEnterAtBytecode(
4337    MacroAssembler* masm) {
4338  Generate_BaselineOrInterpreterEntry(masm, false);
4339}
4340
4341void Builtins::Generate_BaselineOrInterpreterEnterAtNextBytecode(
4342    MacroAssembler* masm) {
4343  Generate_BaselineOrInterpreterEntry(masm, true);
4344}
4345
4346void Builtins::Generate_InterpreterOnStackReplacement_ToBaseline(
4347    MacroAssembler* masm) {
4348  Generate_BaselineOrInterpreterEntry(masm, false, true);
4349}
4350
4351#undef __
4352
4353}  // namespace internal
4354}  // namespace v8
4355
4356#endif  // V8_TARGET_ARCH_IA32
4357