• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #if V8_TARGET_ARCH_X87
6 
7 #include "src/code-factory.h"
8 #include "src/codegen.h"
9 #include "src/deoptimizer.h"
10 #include "src/full-codegen/full-codegen.h"
11 #include "src/x87/frames-x87.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 
17 #define __ ACCESS_MASM(masm)
18 
19 
Generate_Adaptor(MacroAssembler * masm,CFunctionId id,BuiltinExtraArguments extra_args)20 void Builtins::Generate_Adaptor(MacroAssembler* masm,
21                                 CFunctionId id,
22                                 BuiltinExtraArguments extra_args) {
23   // ----------- S t a t e -------------
24   //  -- eax                : number of arguments excluding receiver
25   //  -- edi                : target
26   //  -- edx                : new.target
27   //  -- esp[0]             : return address
28   //  -- esp[4]             : last argument
29   //  -- ...
30   //  -- esp[4 * argc]      : first argument
31   //  -- esp[4 * (argc +1)] : receiver
32   // -----------------------------------
33   __ AssertFunction(edi);
34 
35   // Make sure we operate in the context of the called function (for example
36   // ConstructStubs implemented in C++ will be run in the context of the caller
37   // instead of the callee, due to the way that [[Construct]] is defined for
38   // ordinary functions).
39   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
40 
41   // Insert extra arguments.
42   int num_extra_args = 0;
43   if (extra_args != BuiltinExtraArguments::kNone) {
44     __ PopReturnAddressTo(ecx);
45     if (extra_args & BuiltinExtraArguments::kTarget) {
46       ++num_extra_args;
47       __ Push(edi);
48     }
49     if (extra_args & BuiltinExtraArguments::kNewTarget) {
50       ++num_extra_args;
51       __ Push(edx);
52     }
53     __ PushReturnAddressFrom(ecx);
54   }
55 
56   // JumpToExternalReference expects eax to contain the number of arguments
57   // including the receiver and the extra arguments.
58   __ add(eax, Immediate(num_extra_args + 1));
59 
60   __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
61 }
62 
63 
CallRuntimePassFunction(MacroAssembler * masm,Runtime::FunctionId function_id)64 static void CallRuntimePassFunction(
65     MacroAssembler* masm, Runtime::FunctionId function_id) {
66   // ----------- S t a t e -------------
67   //  -- edx : new target (preserved for callee)
68   //  -- edi : target function (preserved for callee)
69   // -----------------------------------
70 
71   FrameScope scope(masm, StackFrame::INTERNAL);
72   // Push a copy of the target function and the new target.
73   __ push(edi);
74   __ push(edx);
75   // Function is also the parameter to the runtime call.
76   __ push(edi);
77 
78   __ CallRuntime(function_id, 1);
79   // Restore target function and new target.
80   __ pop(edx);
81   __ pop(edi);
82 }
83 
84 
GenerateTailCallToSharedCode(MacroAssembler * masm)85 static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
86   __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
87   __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kCodeOffset));
88   __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
89   __ jmp(eax);
90 }
91 
92 
GenerateTailCallToReturnedCode(MacroAssembler * masm)93 static void GenerateTailCallToReturnedCode(MacroAssembler* masm) {
94   __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
95   __ jmp(eax);
96 }
97 
98 
Generate_InOptimizationQueue(MacroAssembler * masm)99 void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
100   // Checking whether the queued function is ready for install is optional,
101   // since we come across interrupts and stack checks elsewhere.  However,
102   // not checking may delay installing ready functions, and always checking
103   // would be quite expensive.  A good compromise is to first check against
104   // stack limit as a cue for an interrupt signal.
105   Label ok;
106   ExternalReference stack_limit =
107       ExternalReference::address_of_stack_limit(masm->isolate());
108   __ cmp(esp, Operand::StaticVariable(stack_limit));
109   __ j(above_equal, &ok, Label::kNear);
110 
111   CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode);
112   GenerateTailCallToReturnedCode(masm);
113 
114   __ bind(&ok);
115   GenerateTailCallToSharedCode(masm);
116 }
117 
118 
Generate_JSConstructStubHelper(MacroAssembler * masm,bool is_api_function,bool create_implicit_receiver)119 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
120                                            bool is_api_function,
121                                            bool create_implicit_receiver) {
122   // ----------- S t a t e -------------
123   //  -- eax: number of arguments
124   //  -- edi: constructor function
125   //  -- ebx: allocation site or undefined
126   //  -- edx: new target
127   // -----------------------------------
128 
129   // Enter a construct frame.
130   {
131     FrameScope scope(masm, StackFrame::CONSTRUCT);
132 
133     // Preserve the incoming parameters on the stack.
134     __ AssertUndefinedOrAllocationSite(ebx);
135     __ push(ebx);
136     __ SmiTag(eax);
137     __ push(eax);
138 
139     if (create_implicit_receiver) {
140       __ push(edi);
141       __ push(edx);
142 
143       // Try to allocate the object without transitioning into C code. If any of
144       // the preconditions is not met, the code bails out to the runtime call.
145       Label rt_call, allocated;
146       if (FLAG_inline_new) {
147         // Verify that the new target is a JSFunction.
148         __ CmpObjectType(edx, JS_FUNCTION_TYPE, ebx);
149         __ j(not_equal, &rt_call);
150 
151         // Load the initial map and verify that it is in fact a map.
152         // edx: new target
153         __ mov(eax,
154                FieldOperand(edx, JSFunction::kPrototypeOrInitialMapOffset));
155         // Will both indicate a NULL and a Smi
156         __ JumpIfSmi(eax, &rt_call);
157         // edi: constructor
158         // eax: initial map (if proven valid below)
159         __ CmpObjectType(eax, MAP_TYPE, ebx);
160         __ j(not_equal, &rt_call);
161 
162         // Fall back to runtime if the expected base constructor and base
163         // constructor differ.
164         __ cmp(edi, FieldOperand(eax, Map::kConstructorOrBackPointerOffset));
165         __ j(not_equal, &rt_call);
166 
167         // Check that the constructor is not constructing a JSFunction (see
168         // comments in Runtime_NewObject in runtime.cc). In which case the
169         // initial map's instance type would be JS_FUNCTION_TYPE.
170         // edi: constructor
171         // eax: initial map
172         __ CmpInstanceType(eax, JS_FUNCTION_TYPE);
173         __ j(equal, &rt_call);
174 
175         // Now allocate the JSObject on the heap.
176         // edi: constructor
177         // eax: initial map
178         __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset));
179         __ shl(edi, kPointerSizeLog2);
180 
181         __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS);
182 
183         Factory* factory = masm->isolate()->factory();
184 
185         // Allocated the JSObject, now initialize the fields.
186         // eax: initial map
187         // ebx: JSObject (not HeapObject tagged - the actual address).
188         // edi: start of next object
189         __ mov(Operand(ebx, JSObject::kMapOffset), eax);
190         __ mov(ecx, factory->empty_fixed_array());
191         __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx);
192         __ mov(Operand(ebx, JSObject::kElementsOffset), ecx);
193         __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
194 
195         // Add the object tag to make the JSObject real, so that we can continue
196         // and jump into the continuation code at any time from now on.
197         __ or_(ebx, Immediate(kHeapObjectTag));
198 
199         // Fill all the in-object properties with the appropriate filler.
200         // ebx: JSObject (tagged)
201         // ecx: First in-object property of JSObject (not tagged)
202         __ mov(edx, factory->undefined_value());
203 
204         if (!is_api_function) {
205           Label no_inobject_slack_tracking;
206 
207           // The code below relies on these assumptions.
208           STATIC_ASSERT(Map::kNoSlackTracking == 0);
209           STATIC_ASSERT(Map::ConstructionCounter::kNext == 32);
210           // Check if slack tracking is enabled.
211           __ mov(esi, FieldOperand(eax, Map::kBitField3Offset));
212           __ shr(esi, Map::ConstructionCounter::kShift);
213           __ j(zero, &no_inobject_slack_tracking);  // Map::kNoSlackTracking
214           __ push(esi);  // Save allocation count value.
215           // Decrease generous allocation count.
216           __ sub(FieldOperand(eax, Map::kBitField3Offset),
217                  Immediate(1 << Map::ConstructionCounter::kShift));
218 
219           // Allocate object with a slack.
220           __ movzx_b(esi, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
221           __ neg(esi);
222           __ lea(esi, Operand(edi, esi, times_pointer_size, 0));
223           // esi: offset of first field after pre-allocated fields
224           if (FLAG_debug_code) {
225             __ cmp(ecx, esi);
226             __ Assert(less_equal,
227                       kUnexpectedNumberOfPreAllocatedPropertyFields);
228           }
229           __ InitializeFieldsWithFiller(ecx, esi, edx);
230 
231           // To allow truncation fill the remaining fields with one pointer
232           // filler map.
233           __ mov(edx, factory->one_pointer_filler_map());
234           __ InitializeFieldsWithFiller(ecx, edi, edx);
235 
236           __ pop(esi);  // Restore allocation count value before decreasing.
237           __ cmp(esi, Map::kSlackTrackingCounterEnd);
238           __ j(not_equal, &allocated);
239 
240           // Push the object to the stack, and then the initial map as
241           // an argument to the runtime call.
242           __ push(ebx);
243           __ push(eax);  // initial map
244           __ CallRuntime(Runtime::kFinalizeInstanceSize);
245           __ pop(ebx);
246 
247           // Continue with JSObject being successfully allocated
248           // ebx: JSObject (tagged)
249           __ jmp(&allocated);
250 
251           __ bind(&no_inobject_slack_tracking);
252         }
253 
254         __ InitializeFieldsWithFiller(ecx, edi, edx);
255 
256         // Continue with JSObject being successfully allocated
257         // ebx: JSObject (tagged)
258         __ jmp(&allocated);
259       }
260 
261       // Allocate the new receiver object using the runtime call.
262       // edx: new target
263       __ bind(&rt_call);
264       int offset = kPointerSize;
265 
266       // Must restore esi (context) and edi (constructor) before calling
267       // runtime.
268       __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
269       __ mov(edi, Operand(esp, offset));
270       __ push(edi);  // constructor function
271       __ push(edx);  // new target
272       __ CallRuntime(Runtime::kNewObject);
273       __ mov(ebx, eax);  // store result in ebx
274 
275       // New object allocated.
276       // ebx: newly allocated object
277       __ bind(&allocated);
278 
279       // Restore the parameters.
280       __ pop(edx);  // new.target
281       __ pop(edi);  // Constructor function.
282 
283       // Retrieve smi-tagged arguments count from the stack.
284       __ mov(eax, Operand(esp, 0));
285     }
286 
287     __ SmiUntag(eax);
288 
289     if (create_implicit_receiver) {
290       // Push the allocated receiver to the stack. We need two copies
291       // because we may have to return the original one and the calling
292       // conventions dictate that the called function pops the receiver.
293       __ push(ebx);
294       __ push(ebx);
295     } else {
296       __ PushRoot(Heap::kTheHoleValueRootIndex);
297     }
298 
299     // Set up pointer to last argument.
300     __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
301 
302     // Copy arguments and receiver to the expression stack.
303     Label loop, entry;
304     __ mov(ecx, eax);
305     __ jmp(&entry);
306     __ bind(&loop);
307     __ push(Operand(ebx, ecx, times_4, 0));
308     __ bind(&entry);
309     __ dec(ecx);
310     __ j(greater_equal, &loop);
311 
312     // Call the function.
313     if (is_api_function) {
314       __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
315       Handle<Code> code =
316           masm->isolate()->builtins()->HandleApiCallConstruct();
317       __ call(code, RelocInfo::CODE_TARGET);
318     } else {
319       ParameterCount actual(eax);
320       __ InvokeFunction(edi, edx, actual, CALL_FUNCTION,
321                         CheckDebugStepCallWrapper());
322     }
323 
324     // Store offset of return address for deoptimizer.
325     if (create_implicit_receiver && !is_api_function) {
326       masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
327     }
328 
329     // Restore context from the frame.
330     __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
331 
332     if (create_implicit_receiver) {
333       // If the result is an object (in the ECMA sense), we should get rid
334       // of the receiver and use the result; see ECMA-262 section 13.2.2-7
335       // on page 74.
336       Label use_receiver, exit;
337 
338       // If the result is a smi, it is *not* an object in the ECMA sense.
339       __ JumpIfSmi(eax, &use_receiver);
340 
341       // If the type of the result (stored in its map) is less than
342       // FIRST_JS_RECEIVER_TYPE, it is not an object in the ECMA sense.
343       __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, ecx);
344       __ j(above_equal, &exit);
345 
346       // Throw away the result of the constructor invocation and use the
347       // on-stack receiver as the result.
348       __ bind(&use_receiver);
349       __ mov(eax, Operand(esp, 0));
350 
351       // Restore the arguments count and leave the construct frame. The
352       // arguments count is stored below the receiver.
353       __ bind(&exit);
354       __ mov(ebx, Operand(esp, 1 * kPointerSize));
355     } else {
356       __ mov(ebx, Operand(esp, 0));
357     }
358 
359     // Leave construct frame.
360   }
361 
362   // Remove caller arguments from the stack and return.
363   STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
364   __ pop(ecx);
365   __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));  // 1 ~ receiver
366   __ push(ecx);
367   if (create_implicit_receiver) {
368     __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
369   }
370   __ ret(0);
371 }
372 
373 
Generate_JSConstructStubGeneric(MacroAssembler * masm)374 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
375   Generate_JSConstructStubHelper(masm, false, true);
376 }
377 
378 
Generate_JSConstructStubApi(MacroAssembler * masm)379 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
380   Generate_JSConstructStubHelper(masm, true, true);
381 }
382 
383 
Generate_JSBuiltinsConstructStub(MacroAssembler * masm)384 void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
385   Generate_JSConstructStubHelper(masm, false, false);
386 }
387 
388 
Generate_ConstructedNonConstructable(MacroAssembler * masm)389 void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
390   FrameScope scope(masm, StackFrame::INTERNAL);
391   __ push(edi);
392   __ CallRuntime(Runtime::kThrowConstructedNonConstructable);
393 }
394 
395 
396 enum IsTagged { kEaxIsSmiTagged, kEaxIsUntaggedInt };
397 
398 
399 // Clobbers ecx, edx, edi; preserves all other registers.
Generate_CheckStackOverflow(MacroAssembler * masm,IsTagged eax_is_tagged)400 static void Generate_CheckStackOverflow(MacroAssembler* masm,
401                                         IsTagged eax_is_tagged) {
402   // eax   : the number of items to be pushed to the stack
403   //
404   // Check the stack for overflow. We are not trying to catch
405   // interruptions (e.g. debug break and preemption) here, so the "real stack
406   // limit" is checked.
407   Label okay;
408   ExternalReference real_stack_limit =
409       ExternalReference::address_of_real_stack_limit(masm->isolate());
410   __ mov(edi, Operand::StaticVariable(real_stack_limit));
411   // Make ecx the space we have left. The stack might already be overflowed
412   // here which will cause ecx to become negative.
413   __ mov(ecx, esp);
414   __ sub(ecx, edi);
415   // Make edx the space we need for the array when it is unrolled onto the
416   // stack.
417   __ mov(edx, eax);
418   int smi_tag = eax_is_tagged == kEaxIsSmiTagged ? kSmiTagSize : 0;
419   __ shl(edx, kPointerSizeLog2 - smi_tag);
420   // Check if the arguments will overflow the stack.
421   __ cmp(ecx, edx);
422   __ j(greater, &okay);  // Signed comparison.
423 
424   // Out of stack space.
425   __ CallRuntime(Runtime::kThrowStackOverflow);
426 
427   __ bind(&okay);
428 }
429 
430 
Generate_JSEntryTrampolineHelper(MacroAssembler * masm,bool is_construct)431 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
432                                              bool is_construct) {
433   ProfileEntryHookStub::MaybeCallEntryHook(masm);
434 
435   // Clear the context before we push it when entering the internal frame.
436   __ Move(esi, Immediate(0));
437 
438   {
439     FrameScope scope(masm, StackFrame::INTERNAL);
440 
441     // Setup the context (we need to use the caller context from the isolate).
442     ExternalReference context_address(Isolate::kContextAddress,
443                                       masm->isolate());
444     __ mov(esi, Operand::StaticVariable(context_address));
445 
446     // Load the previous frame pointer (ebx) to access C arguments
447     __ mov(ebx, Operand(ebp, 0));
448 
449     // Push the function and the receiver onto the stack.
450     __ push(Operand(ebx, EntryFrameConstants::kFunctionArgOffset));
451     __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset));
452 
453     // Load the number of arguments and setup pointer to the arguments.
454     __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset));
455     __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset));
456 
457     // Check if we have enough stack space to push all arguments.
458     // Expects argument count in eax. Clobbers ecx, edx, edi.
459     Generate_CheckStackOverflow(masm, kEaxIsUntaggedInt);
460 
461     // Copy arguments to the stack in a loop.
462     Label loop, entry;
463     __ Move(ecx, Immediate(0));
464     __ jmp(&entry, Label::kNear);
465     __ bind(&loop);
466     __ mov(edx, Operand(ebx, ecx, times_4, 0));  // push parameter from argv
467     __ push(Operand(edx, 0));  // dereference handle
468     __ inc(ecx);
469     __ bind(&entry);
470     __ cmp(ecx, eax);
471     __ j(not_equal, &loop);
472 
473     // Load the previous frame pointer (ebx) to access C arguments
474     __ mov(ebx, Operand(ebp, 0));
475 
476     // Get the new.target and function from the frame.
477     __ mov(edx, Operand(ebx, EntryFrameConstants::kNewTargetArgOffset));
478     __ mov(edi, Operand(ebx, EntryFrameConstants::kFunctionArgOffset));
479 
480     // Invoke the code.
481     Handle<Code> builtin = is_construct
482                                ? masm->isolate()->builtins()->Construct()
483                                : masm->isolate()->builtins()->Call();
484     __ Call(builtin, RelocInfo::CODE_TARGET);
485 
486     // Exit the internal frame. Notice that this also removes the empty.
487     // context and the function left on the stack by the code
488     // invocation.
489   }
490   __ ret(kPointerSize);  // Remove receiver.
491 }
492 
493 
Generate_JSEntryTrampoline(MacroAssembler * masm)494 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
495   Generate_JSEntryTrampolineHelper(masm, false);
496 }
497 
498 
Generate_JSConstructEntryTrampoline(MacroAssembler * masm)499 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
500   Generate_JSEntryTrampolineHelper(masm, true);
501 }
502 
503 
504 // Generate code for entering a JS function with the interpreter.
505 // On entry to the function the receiver and arguments have been pushed on the
506 // stack left to right.  The actual argument count matches the formal parameter
507 // count expected by the function.
508 //
509 // The live registers are:
510 //   o edi: the JS function object being called
511 //   o edx: the new target
512 //   o esi: our context
513 //   o ebp: the caller's frame pointer
514 //   o esp: stack pointer (pointing to return address)
515 //
516 // The function builds a JS frame.  Please see JavaScriptFrameConstants in
517 // frames-ia32.h for its layout.
518 // TODO(rmcilroy): We will need to include the current bytecode pointer in the
519 // frame.
Generate_InterpreterEntryTrampoline(MacroAssembler * masm)520 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
521   // Open a frame scope to indicate that there is a frame on the stack.  The
522   // MANUAL indicates that the scope shouldn't actually generate code to set up
523   // the frame (that is done below).
524   FrameScope frame_scope(masm, StackFrame::MANUAL);
525   __ push(ebp);  // Caller's frame pointer.
526   __ mov(ebp, esp);
527   __ push(esi);  // Callee's context.
528   __ push(edi);  // Callee's JS function.
529   __ push(edx);  // Callee's new target.
530 
531   // Push zero for bytecode array offset.
532   __ push(Immediate(0));
533 
534   // Get the bytecode array from the function object and load the pointer to the
535   // first entry into edi (InterpreterBytecodeRegister).
536   __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
537   __ mov(kInterpreterBytecodeArrayRegister,
538          FieldOperand(eax, SharedFunctionInfo::kFunctionDataOffset));
539 
540   if (FLAG_debug_code) {
541     // Check function data field is actually a BytecodeArray object.
542     __ AssertNotSmi(kInterpreterBytecodeArrayRegister);
543     __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE,
544                      eax);
545     __ Assert(equal, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
546   }
547 
548   // Allocate the local and temporary register file on the stack.
549   {
550     // Load frame size from the BytecodeArray object.
551     __ mov(ebx, FieldOperand(kInterpreterBytecodeArrayRegister,
552                              BytecodeArray::kFrameSizeOffset));
553 
554     // Do a stack check to ensure we don't go over the limit.
555     Label ok;
556     __ mov(ecx, esp);
557     __ sub(ecx, ebx);
558     ExternalReference stack_limit =
559         ExternalReference::address_of_real_stack_limit(masm->isolate());
560     __ cmp(ecx, Operand::StaticVariable(stack_limit));
561     __ j(above_equal, &ok);
562     __ CallRuntime(Runtime::kThrowStackOverflow);
563     __ bind(&ok);
564 
565     // If ok, push undefined as the initial value for all register file entries.
566     Label loop_header;
567     Label loop_check;
568     __ mov(eax, Immediate(masm->isolate()->factory()->undefined_value()));
569     __ jmp(&loop_check);
570     __ bind(&loop_header);
571     // TODO(rmcilroy): Consider doing more than one push per loop iteration.
572     __ push(eax);
573     // Continue loop if not done.
574     __ bind(&loop_check);
575     __ sub(ebx, Immediate(kPointerSize));
576     __ j(greater_equal, &loop_header);
577   }
578 
579   // TODO(rmcilroy): List of things not currently dealt with here but done in
580   // fullcodegen's prologue:
581   //  - Support profiler (specifically profiling_counter).
582   //  - Call ProfileEntryHookStub when isolate has a function_entry_hook.
583   //  - Allow simulator stop operations if FLAG_stop_at is set.
584   //  - Code aging of the BytecodeArray object.
585 
586   // Perform stack guard check.
587   {
588     Label ok;
589     ExternalReference stack_limit =
590         ExternalReference::address_of_stack_limit(masm->isolate());
591     __ cmp(esp, Operand::StaticVariable(stack_limit));
592     __ j(above_equal, &ok);
593     __ push(kInterpreterBytecodeArrayRegister);
594     __ CallRuntime(Runtime::kStackGuard);
595     __ pop(kInterpreterBytecodeArrayRegister);
596     __ bind(&ok);
597   }
598 
599   // Load accumulator, register file, bytecode offset, dispatch table into
600   // registers.
601   __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
602   __ mov(kInterpreterRegisterFileRegister, ebp);
603   __ add(kInterpreterRegisterFileRegister,
604          Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
605   __ mov(kInterpreterBytecodeOffsetRegister,
606          Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
607   // Since the dispatch table root might be set after builtins are generated,
608   // load directly from the roots table.
609   __ LoadRoot(ebx, Heap::kInterpreterTableRootIndex);
610   __ add(ebx, Immediate(FixedArray::kHeaderSize - kHeapObjectTag));
611 
612   // Push dispatch table as a stack located parameter to the bytecode handler.
613   DCHECK_EQ(-1, kInterpreterDispatchTableSpillSlot);
614   __ push(ebx);
615 
616   // Dispatch to the first bytecode handler for the function.
617   __ movzx_b(eax, Operand(kInterpreterBytecodeArrayRegister,
618                           kInterpreterBytecodeOffsetRegister, times_1, 0));
619   __ mov(ebx, Operand(ebx, eax, times_pointer_size, 0));
620   // Restore undefined_value in accumulator (eax)
621   // TODO(rmcilroy): Remove this once we move the dispatch table back into a
622   // register.
623   __ mov(eax, Immediate(masm->isolate()->factory()->undefined_value()));
624   // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
625   // and header removal.
626   __ add(ebx, Immediate(Code::kHeaderSize - kHeapObjectTag));
627   __ call(ebx);
628   __ nop();  // Ensure that return address still counts as interpreter entry
629              // trampoline.
630 }
631 
632 
Generate_InterpreterExitTrampoline(MacroAssembler * masm)633 void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
634   // TODO(rmcilroy): List of things not currently dealt with here but done in
635   // fullcodegen's EmitReturnSequence.
636   //  - Supporting FLAG_trace for Runtime::TraceExit.
637   //  - Support profiler (specifically decrementing profiling_counter
638   //    appropriately and calling out to HandleInterrupts if necessary).
639 
640   // The return value is in accumulator, which is already in rax.
641 
642   // Leave the frame (also dropping the register file).
643   __ leave();
644 
645   // Drop receiver + arguments and return.
646   __ mov(ebx, FieldOperand(kInterpreterBytecodeArrayRegister,
647                            BytecodeArray::kParameterSizeOffset));
648   __ pop(ecx);
649   __ add(esp, ebx);
650   __ push(ecx);
651   __ ret(0);
652 }
653 
654 
Generate_InterpreterPushArgs(MacroAssembler * masm,Register array_limit)655 static void Generate_InterpreterPushArgs(MacroAssembler* masm,
656                                          Register array_limit) {
657   // ----------- S t a t e -------------
658   //  -- ebx : Pointer to the last argument in the args array.
659   //  -- array_limit : Pointer to one before the first argument in the
660   //                   args array.
661   // -----------------------------------
662   Label loop_header, loop_check;
663   __ jmp(&loop_check);
664   __ bind(&loop_header);
665   __ Push(Operand(ebx, 0));
666   __ sub(ebx, Immediate(kPointerSize));
667   __ bind(&loop_check);
668   __ cmp(ebx, array_limit);
669   __ j(greater, &loop_header, Label::kNear);
670 }
671 
672 
673 // static
Generate_InterpreterPushArgsAndCall(MacroAssembler * masm)674 void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
675   // ----------- S t a t e -------------
676   //  -- eax : the number of arguments (not including the receiver)
677   //  -- ebx : the address of the first argument to be pushed. Subsequent
678   //           arguments should be consecutive above this, in the same order as
679   //           they are to be pushed onto the stack.
680   //  -- edi : the target to call (can be any Object).
681   // -----------------------------------
682 
683   // Pop return address to allow tail-call after pushing arguments.
684   __ Pop(edx);
685 
686   // Find the address of the last argument.
687   __ mov(ecx, eax);
688   __ add(ecx, Immediate(1));  // Add one for receiver.
689   __ shl(ecx, kPointerSizeLog2);
690   __ neg(ecx);
691   __ add(ecx, ebx);
692 
693   Generate_InterpreterPushArgs(masm, ecx);
694 
695   // Call the target.
696   __ Push(edx);  // Re-push return address.
697   __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
698 }
699 
700 
701 // static
Generate_InterpreterPushArgsAndConstruct(MacroAssembler * masm)702 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
703   // ----------- S t a t e -------------
704   //  -- eax : the number of arguments (not including the receiver)
705   //  -- edx : the new target
706   //  -- edi : the constructor
707   //  -- ebx : the address of the first argument to be pushed. Subsequent
708   //           arguments should be consecutive above this, in the same order as
709   //           they are to be pushed onto the stack.
710   // -----------------------------------
711 
712   // Save number of arguments on the stack below where arguments are going
713   // to be pushed.
714   __ mov(ecx, eax);
715   __ neg(ecx);
716   __ mov(Operand(esp, ecx, times_pointer_size, -kPointerSize), eax);
717   __ mov(eax, ecx);
718 
719   // Pop return address to allow tail-call after pushing arguments.
720   __ Pop(ecx);
721 
722   // Find the address of the last argument.
723   __ shl(eax, kPointerSizeLog2);
724   __ add(eax, ebx);
725 
726   // Push padding for receiver.
727   __ Push(Immediate(0));
728 
729   Generate_InterpreterPushArgs(masm, eax);
730 
731   // Restore number of arguments from slot on stack.
732   __ mov(eax, Operand(esp, -kPointerSize));
733 
734   // Re-push return address.
735   __ Push(ecx);
736 
737   // Call the constructor with unmodified eax, edi, ebi values.
738   __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
739 }
740 
741 
Generate_InterpreterNotifyDeoptimizedHelper(MacroAssembler * masm,Deoptimizer::BailoutType type)742 static void Generate_InterpreterNotifyDeoptimizedHelper(
743     MacroAssembler* masm, Deoptimizer::BailoutType type) {
744   // Enter an internal frame.
745   {
746     FrameScope scope(masm, StackFrame::INTERNAL);
747     __ Push(kInterpreterAccumulatorRegister);  // Save accumulator register.
748 
749     // Pass the deoptimization type to the runtime system.
750     __ Push(Smi::FromInt(static_cast<int>(type)));
751 
752     __ CallRuntime(Runtime::kNotifyDeoptimized);
753 
754     __ Pop(kInterpreterAccumulatorRegister);  // Restore accumulator register.
755     // Tear down internal frame.
756   }
757 
758   // Initialize register file register.
759   __ mov(kInterpreterRegisterFileRegister, ebp);
760   __ add(kInterpreterRegisterFileRegister,
761          Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
762 
763   // Get the bytecode array pointer from the frame.
764   __ mov(ebx, Operand(kInterpreterRegisterFileRegister,
765                       InterpreterFrameConstants::kFunctionFromRegisterPointer));
766   __ mov(ebx, FieldOperand(ebx, JSFunction::kSharedFunctionInfoOffset));
767   __ mov(kInterpreterBytecodeArrayRegister,
768          FieldOperand(ebx, SharedFunctionInfo::kFunctionDataOffset));
769 
770   if (FLAG_debug_code) {
771     // Check function data field is actually a BytecodeArray object.
772     __ AssertNotSmi(kInterpreterBytecodeArrayRegister);
773     __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE,
774                      ebx);
775     __ Assert(equal, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
776   }
777 
778   // Get the target bytecode offset from the frame.
779   __ mov(
780       kInterpreterBytecodeOffsetRegister,
781       Operand(kInterpreterRegisterFileRegister,
782               InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
783   __ SmiUntag(kInterpreterBytecodeOffsetRegister);
784 
785   // Push dispatch table as a stack located parameter to the bytecode handler -
786   // overwrite the state slot (we don't use these for interpreter deopts).
787   __ LoadRoot(ebx, Heap::kInterpreterTableRootIndex);
788   __ add(ebx, Immediate(FixedArray::kHeaderSize - kHeapObjectTag));
789   DCHECK_EQ(-1, kInterpreterDispatchTableSpillSlot);
790   __ mov(Operand(esp, kPointerSize), ebx);
791 
792   // Dispatch to the target bytecode.
793   __ movzx_b(esi, Operand(kInterpreterBytecodeArrayRegister,
794                           kInterpreterBytecodeOffsetRegister, times_1, 0));
795   __ mov(ebx, Operand(ebx, esi, times_pointer_size, 0));
796 
797   // Get the context from the frame.
798   // TODO(rmcilroy): Update interpreter frame to expect current context at the
799   // context slot instead of the function context.
800   __ mov(kContextRegister,
801          Operand(kInterpreterRegisterFileRegister,
802                  InterpreterFrameConstants::kContextFromRegisterPointer));
803 
804   // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
805   // and header removal.
806   __ add(ebx, Immediate(Code::kHeaderSize - kHeapObjectTag));
807   __ jmp(ebx);
808 }
809 
810 
Generate_InterpreterNotifyDeoptimized(MacroAssembler * masm)811 void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
812   Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
813 }
814 
815 
Generate_InterpreterNotifySoftDeoptimized(MacroAssembler * masm)816 void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
817   Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
818 }
819 
820 
Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler * masm)821 void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
822   Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
823 }
824 
825 
Generate_CompileLazy(MacroAssembler * masm)826 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
827   CallRuntimePassFunction(masm, Runtime::kCompileLazy);
828   GenerateTailCallToReturnedCode(masm);
829 }
830 
831 
Generate_CompileOptimized(MacroAssembler * masm)832 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
833   CallRuntimePassFunction(masm, Runtime::kCompileOptimized_NotConcurrent);
834   GenerateTailCallToReturnedCode(masm);
835 }
836 
837 
Generate_CompileOptimizedConcurrent(MacroAssembler * masm)838 void Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) {
839   CallRuntimePassFunction(masm, Runtime::kCompileOptimized_Concurrent);
840   GenerateTailCallToReturnedCode(masm);
841 }
842 
843 
GenerateMakeCodeYoungAgainCommon(MacroAssembler * masm)844 static void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) {
845   // For now, we are relying on the fact that make_code_young doesn't do any
846   // garbage collection which allows us to save/restore the registers without
847   // worrying about which of them contain pointers. We also don't build an
848   // internal frame to make the code faster, since we shouldn't have to do stack
849   // crawls in MakeCodeYoung. This seems a bit fragile.
850 
851   // Re-execute the code that was patched back to the young age when
852   // the stub returns.
853   __ sub(Operand(esp, 0), Immediate(5));
854   __ pushad();
855   __ mov(eax, Operand(esp, 8 * kPointerSize));
856   {
857     FrameScope scope(masm, StackFrame::MANUAL);
858     __ PrepareCallCFunction(2, ebx);
859     __ mov(Operand(esp, 1 * kPointerSize),
860            Immediate(ExternalReference::isolate_address(masm->isolate())));
861     __ mov(Operand(esp, 0), eax);
862     __ CallCFunction(
863         ExternalReference::get_make_code_young_function(masm->isolate()), 2);
864   }
865   __ popad();
866   __ ret(0);
867 }
868 
869 #define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C)                 \
870 void Builtins::Generate_Make##C##CodeYoungAgainEvenMarking(  \
871     MacroAssembler* masm) {                                  \
872   GenerateMakeCodeYoungAgainCommon(masm);                    \
873 }                                                            \
874 void Builtins::Generate_Make##C##CodeYoungAgainOddMarking(   \
875     MacroAssembler* masm) {                                  \
876   GenerateMakeCodeYoungAgainCommon(masm);                    \
877 }
CODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR)878 CODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR)
879 #undef DEFINE_CODE_AGE_BUILTIN_GENERATOR
880 
881 
882 void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
883   // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact
884   // that make_code_young doesn't do any garbage collection which allows us to
885   // save/restore the registers without worrying about which of them contain
886   // pointers.
887   __ pushad();
888   __ mov(eax, Operand(esp, 8 * kPointerSize));
889   __ sub(eax, Immediate(Assembler::kCallInstructionLength));
890   {  // NOLINT
891     FrameScope scope(masm, StackFrame::MANUAL);
892     __ PrepareCallCFunction(2, ebx);
893     __ mov(Operand(esp, 1 * kPointerSize),
894            Immediate(ExternalReference::isolate_address(masm->isolate())));
895     __ mov(Operand(esp, 0), eax);
896     __ CallCFunction(
897         ExternalReference::get_mark_code_as_executed_function(masm->isolate()),
898         2);
899   }
900   __ popad();
901 
902   // Perform prologue operations usually performed by the young code stub.
903   __ pop(eax);   // Pop return address into scratch register.
904   __ push(ebp);  // Caller's frame pointer.
905   __ mov(ebp, esp);
906   __ push(esi);  // Callee's context.
907   __ push(edi);  // Callee's JS Function.
908   __ push(eax);  // Push return address after frame prologue.
909 
910   // Jump to point after the code-age stub.
911   __ ret(0);
912 }
913 
914 
Generate_MarkCodeAsExecutedTwice(MacroAssembler * masm)915 void Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) {
916   GenerateMakeCodeYoungAgainCommon(masm);
917 }
918 
919 
Generate_MarkCodeAsToBeExecutedOnce(MacroAssembler * masm)920 void Builtins::Generate_MarkCodeAsToBeExecutedOnce(MacroAssembler* masm) {
921   Generate_MarkCodeAsExecutedOnce(masm);
922 }
923 
924 
Generate_NotifyStubFailureHelper(MacroAssembler * masm,SaveFPRegsMode save_doubles)925 static void Generate_NotifyStubFailureHelper(MacroAssembler* masm,
926                                              SaveFPRegsMode save_doubles) {
927   // Enter an internal frame.
928   {
929     FrameScope scope(masm, StackFrame::INTERNAL);
930 
931     // Preserve registers across notification, this is important for compiled
932     // stubs that tail call the runtime on deopts passing their parameters in
933     // registers.
934     __ pushad();
935     __ CallRuntime(Runtime::kNotifyStubFailure, save_doubles);
936     __ popad();
937     // Tear down internal frame.
938   }
939 
940   __ pop(MemOperand(esp, 0));  // Ignore state offset
941   __ ret(0);  // Return to IC Miss stub, continuation still on stack.
942 }
943 
944 
Generate_NotifyStubFailure(MacroAssembler * masm)945 void Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) {
946   Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs);
947 }
948 
949 
Generate_NotifyStubFailureSaveDoubles(MacroAssembler * masm)950 void Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) {
951   Generate_NotifyStubFailureHelper(masm, kSaveFPRegs);
952 }
953 
954 
Generate_NotifyDeoptimizedHelper(MacroAssembler * masm,Deoptimizer::BailoutType type)955 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
956                                              Deoptimizer::BailoutType type) {
957   {
958     FrameScope scope(masm, StackFrame::INTERNAL);
959 
960     // Pass deoptimization type to the runtime system.
961     __ push(Immediate(Smi::FromInt(static_cast<int>(type))));
962     __ CallRuntime(Runtime::kNotifyDeoptimized);
963 
964     // Tear down internal frame.
965   }
966 
967   // Get the full codegen state from the stack and untag it.
968   __ mov(ecx, Operand(esp, 1 * kPointerSize));
969   __ SmiUntag(ecx);
970 
971   // Switch on the state.
972   Label not_no_registers, not_tos_eax;
973   __ cmp(ecx, FullCodeGenerator::NO_REGISTERS);
974   __ j(not_equal, &not_no_registers, Label::kNear);
975   __ ret(1 * kPointerSize);  // Remove state.
976 
977   __ bind(&not_no_registers);
978   __ mov(eax, Operand(esp, 2 * kPointerSize));
979   __ cmp(ecx, FullCodeGenerator::TOS_REG);
980   __ j(not_equal, &not_tos_eax, Label::kNear);
981   __ ret(2 * kPointerSize);  // Remove state, eax.
982 
983   __ bind(&not_tos_eax);
984   __ Abort(kNoCasesLeft);
985 }
986 
987 
Generate_NotifyDeoptimized(MacroAssembler * masm)988 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
989   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
990 }
991 
992 
Generate_NotifySoftDeoptimized(MacroAssembler * masm)993 void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
994   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
995 }
996 
997 
Generate_NotifyLazyDeoptimized(MacroAssembler * masm)998 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
999   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
1000 }
1001 
1002 
1003 // static
Generate_DatePrototype_GetField(MacroAssembler * masm,int field_index)1004 void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
1005                                                int field_index) {
1006   // ----------- S t a t e -------------
1007   //  -- esp[0] : return address
1008   //  -- esp[4] : receiver
1009   // -----------------------------------
1010 
1011   // 1. Load receiver into eax and check that it's actually a JSDate object.
1012   Label receiver_not_date;
1013   {
1014     __ mov(eax, Operand(esp, kPointerSize));
1015     __ JumpIfSmi(eax, &receiver_not_date);
1016     __ CmpObjectType(eax, JS_DATE_TYPE, ebx);
1017     __ j(not_equal, &receiver_not_date);
1018   }
1019 
1020   // 2. Load the specified date field, falling back to the runtime as necessary.
1021   if (field_index == JSDate::kDateValue) {
1022     __ mov(eax, FieldOperand(eax, JSDate::kValueOffset));
1023   } else {
1024     if (field_index < JSDate::kFirstUncachedField) {
1025       Label stamp_mismatch;
1026       __ mov(edx, Operand::StaticVariable(
1027                       ExternalReference::date_cache_stamp(masm->isolate())));
1028       __ cmp(edx, FieldOperand(eax, JSDate::kCacheStampOffset));
1029       __ j(not_equal, &stamp_mismatch, Label::kNear);
1030       __ mov(eax, FieldOperand(
1031                       eax, JSDate::kValueOffset + field_index * kPointerSize));
1032       __ ret(1 * kPointerSize);
1033       __ bind(&stamp_mismatch);
1034     }
1035     FrameScope scope(masm, StackFrame::INTERNAL);
1036     __ PrepareCallCFunction(2, ebx);
1037     __ mov(Operand(esp, 0), eax);
1038     __ mov(Operand(esp, 1 * kPointerSize),
1039            Immediate(Smi::FromInt(field_index)));
1040     __ CallCFunction(
1041         ExternalReference::get_date_field_function(masm->isolate()), 2);
1042   }
1043   __ ret(1 * kPointerSize);
1044 
1045   // 3. Raise a TypeError if the receiver is not a date.
1046   __ bind(&receiver_not_date);
1047   {
1048     FrameScope scope(masm, StackFrame::MANUAL);
1049     __ EnterFrame(StackFrame::INTERNAL);
1050     __ CallRuntime(Runtime::kThrowNotDateError);
1051   }
1052 }
1053 
1054 
1055 // static
Generate_FunctionPrototypeApply(MacroAssembler * masm)1056 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
1057   // ----------- S t a t e -------------
1058   //  -- eax     : argc
1059   //  -- esp[0]  : return address
1060   //  -- esp[4]  : argArray
1061   //  -- esp[8]  : thisArg
1062   //  -- esp[12] : receiver
1063   // -----------------------------------
1064 
1065   // 1. Load receiver into edi, argArray into eax (if present), remove all
1066   // arguments from the stack (including the receiver), and push thisArg (if
1067   // present) instead.
1068   {
1069     Label no_arg_array, no_this_arg;
1070     __ LoadRoot(edx, Heap::kUndefinedValueRootIndex);
1071     __ mov(ebx, edx);
1072     __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize));
1073     __ test(eax, eax);
1074     __ j(zero, &no_this_arg, Label::kNear);
1075     {
1076       __ mov(edx, Operand(esp, eax, times_pointer_size, 0));
1077       __ cmp(eax, Immediate(1));
1078       __ j(equal, &no_arg_array, Label::kNear);
1079       __ mov(ebx, Operand(esp, eax, times_pointer_size, -kPointerSize));
1080       __ bind(&no_arg_array);
1081     }
1082     __ bind(&no_this_arg);
1083     __ PopReturnAddressTo(ecx);
1084     __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1085     __ Push(edx);
1086     __ PushReturnAddressFrom(ecx);
1087     __ Move(eax, ebx);
1088   }
1089 
1090   // ----------- S t a t e -------------
1091   //  -- eax    : argArray
1092   //  -- edi    : receiver
1093   //  -- esp[0] : return address
1094   //  -- esp[4] : thisArg
1095   // -----------------------------------
1096 
1097   // 2. Make sure the receiver is actually callable.
1098   Label receiver_not_callable;
1099   __ JumpIfSmi(edi, &receiver_not_callable, Label::kNear);
1100   __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset));
1101   __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable);
1102   __ j(zero, &receiver_not_callable, Label::kNear);
1103 
1104   // 3. Tail call with no arguments if argArray is null or undefined.
1105   Label no_arguments;
1106   __ JumpIfRoot(eax, Heap::kNullValueRootIndex, &no_arguments, Label::kNear);
1107   __ JumpIfRoot(eax, Heap::kUndefinedValueRootIndex, &no_arguments,
1108                 Label::kNear);
1109 
1110   // 4a. Apply the receiver to the given argArray (passing undefined for
1111   // new.target).
1112   __ LoadRoot(edx, Heap::kUndefinedValueRootIndex);
1113   __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
1114 
1115   // 4b. The argArray is either null or undefined, so we tail call without any
1116   // arguments to the receiver.
1117   __ bind(&no_arguments);
1118   {
1119     __ Set(eax, 0);
1120     __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1121   }
1122 
1123   // 4c. The receiver is not callable, throw an appropriate TypeError.
1124   __ bind(&receiver_not_callable);
1125   {
1126     __ mov(Operand(esp, kPointerSize), edi);
1127     __ TailCallRuntime(Runtime::kThrowApplyNonFunction);
1128   }
1129 }
1130 
1131 
1132 // static
Generate_FunctionPrototypeCall(MacroAssembler * masm)1133 void Builtins::Generate_FunctionPrototypeCall(MacroAssembler* masm) {
1134   // Stack Layout:
1135   // esp[0]           : Return address
1136   // esp[8]           : Argument n
1137   // esp[16]          : Argument n-1
1138   //  ...
1139   // esp[8 * n]       : Argument 1
1140   // esp[8 * (n + 1)] : Receiver (callable to call)
1141   //
1142   // eax contains the number of arguments, n, not counting the receiver.
1143   //
1144   // 1. Make sure we have at least one argument.
1145   {
1146     Label done;
1147     __ test(eax, eax);
1148     __ j(not_zero, &done, Label::kNear);
1149     __ PopReturnAddressTo(ebx);
1150     __ PushRoot(Heap::kUndefinedValueRootIndex);
1151     __ PushReturnAddressFrom(ebx);
1152     __ inc(eax);
1153     __ bind(&done);
1154   }
1155 
1156   // 2. Get the callable to call (passed as receiver) from the stack.
1157   __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize));
1158 
1159   // 3. Shift arguments and return address one slot down on the stack
1160   //    (overwriting the original receiver).  Adjust argument count to make
1161   //    the original first argument the new receiver.
1162   {
1163     Label loop;
1164     __ mov(ecx, eax);
1165     __ bind(&loop);
1166     __ mov(ebx, Operand(esp, ecx, times_pointer_size, 0));
1167     __ mov(Operand(esp, ecx, times_pointer_size, kPointerSize), ebx);
1168     __ dec(ecx);
1169     __ j(not_sign, &loop);  // While non-negative (to copy return address).
1170     __ pop(ebx);            // Discard copy of return address.
1171     __ dec(eax);  // One fewer argument (first argument is new receiver).
1172   }
1173 
1174   // 4. Call the callable.
1175   __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1176 }
1177 
1178 
Generate_ReflectApply(MacroAssembler * masm)1179 void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
1180   // ----------- S t a t e -------------
1181   //  -- eax     : argc
1182   //  -- esp[0]  : return address
1183   //  -- esp[4]  : argumentsList
1184   //  -- esp[8]  : thisArgument
1185   //  -- esp[12] : target
1186   //  -- esp[16] : receiver
1187   // -----------------------------------
1188 
1189   // 1. Load target into edi (if present), argumentsList into eax (if present),
1190   // remove all arguments from the stack (including the receiver), and push
1191   // thisArgument (if present) instead.
1192   {
1193     Label done;
1194     __ LoadRoot(edi, Heap::kUndefinedValueRootIndex);
1195     __ mov(edx, edi);
1196     __ mov(ebx, edi);
1197     __ cmp(eax, Immediate(1));
1198     __ j(below, &done, Label::kNear);
1199     __ mov(edi, Operand(esp, eax, times_pointer_size, -0 * kPointerSize));
1200     __ j(equal, &done, Label::kNear);
1201     __ mov(edx, Operand(esp, eax, times_pointer_size, -1 * kPointerSize));
1202     __ cmp(eax, Immediate(3));
1203     __ j(below, &done, Label::kNear);
1204     __ mov(ebx, Operand(esp, eax, times_pointer_size, -2 * kPointerSize));
1205     __ bind(&done);
1206     __ PopReturnAddressTo(ecx);
1207     __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1208     __ Push(edx);
1209     __ PushReturnAddressFrom(ecx);
1210     __ Move(eax, ebx);
1211   }
1212 
1213   // ----------- S t a t e -------------
1214   //  -- eax    : argumentsList
1215   //  -- edi    : target
1216   //  -- esp[0] : return address
1217   //  -- esp[4] : thisArgument
1218   // -----------------------------------
1219 
1220   // 2. Make sure the target is actually callable.
1221   Label target_not_callable;
1222   __ JumpIfSmi(edi, &target_not_callable, Label::kNear);
1223   __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset));
1224   __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable);
1225   __ j(zero, &target_not_callable, Label::kNear);
1226 
1227   // 3a. Apply the target to the given argumentsList (passing undefined for
1228   // new.target).
1229   __ LoadRoot(edx, Heap::kUndefinedValueRootIndex);
1230   __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
1231 
1232   // 3b. The target is not callable, throw an appropriate TypeError.
1233   __ bind(&target_not_callable);
1234   {
1235     __ mov(Operand(esp, kPointerSize), edi);
1236     __ TailCallRuntime(Runtime::kThrowApplyNonFunction);
1237   }
1238 }
1239 
1240 
Generate_ReflectConstruct(MacroAssembler * masm)1241 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
1242   // ----------- S t a t e -------------
1243   //  -- eax     : argc
1244   //  -- esp[0]  : return address
1245   //  -- esp[4]  : new.target (optional)
1246   //  -- esp[8]  : argumentsList
1247   //  -- esp[12] : target
1248   //  -- esp[16] : receiver
1249   // -----------------------------------
1250 
1251   // 1. Load target into edi (if present), argumentsList into eax (if present),
1252   // new.target into edx (if present, otherwise use target), remove all
1253   // arguments from the stack (including the receiver), and push thisArgument
1254   // (if present) instead.
1255   {
1256     Label done;
1257     __ LoadRoot(edi, Heap::kUndefinedValueRootIndex);
1258     __ mov(edx, edi);
1259     __ mov(ebx, edi);
1260     __ cmp(eax, Immediate(1));
1261     __ j(below, &done, Label::kNear);
1262     __ mov(edi, Operand(esp, eax, times_pointer_size, -0 * kPointerSize));
1263     __ mov(edx, edi);
1264     __ j(equal, &done, Label::kNear);
1265     __ mov(ebx, Operand(esp, eax, times_pointer_size, -1 * kPointerSize));
1266     __ cmp(eax, Immediate(3));
1267     __ j(below, &done, Label::kNear);
1268     __ mov(edx, Operand(esp, eax, times_pointer_size, -2 * kPointerSize));
1269     __ bind(&done);
1270     __ PopReturnAddressTo(ecx);
1271     __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1272     __ PushRoot(Heap::kUndefinedValueRootIndex);
1273     __ PushReturnAddressFrom(ecx);
1274     __ Move(eax, ebx);
1275   }
1276 
1277   // ----------- S t a t e -------------
1278   //  -- eax    : argumentsList
1279   //  -- edx    : new.target
1280   //  -- edi    : target
1281   //  -- esp[0] : return address
1282   //  -- esp[4] : receiver (undefined)
1283   // -----------------------------------
1284 
1285   // 2. Make sure the target is actually a constructor.
1286   Label target_not_constructor;
1287   __ JumpIfSmi(edi, &target_not_constructor, Label::kNear);
1288   __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset));
1289   __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor);
1290   __ j(zero, &target_not_constructor, Label::kNear);
1291 
1292   // 3. Make sure the target is actually a constructor.
1293   Label new_target_not_constructor;
1294   __ JumpIfSmi(edx, &new_target_not_constructor, Label::kNear);
1295   __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
1296   __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor);
1297   __ j(zero, &new_target_not_constructor, Label::kNear);
1298 
1299   // 4a. Construct the target with the given new.target and argumentsList.
1300   __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET);
1301 
1302   // 4b. The target is not a constructor, throw an appropriate TypeError.
1303   __ bind(&target_not_constructor);
1304   {
1305     __ mov(Operand(esp, kPointerSize), edi);
1306     __ TailCallRuntime(Runtime::kThrowCalledNonCallable);
1307   }
1308 
1309   // 4c. The new.target is not a constructor, throw an appropriate TypeError.
1310   __ bind(&new_target_not_constructor);
1311   {
1312     __ mov(Operand(esp, kPointerSize), edx);
1313     __ TailCallRuntime(Runtime::kThrowCalledNonCallable);
1314   }
1315 }
1316 
1317 
Generate_InternalArrayCode(MacroAssembler * masm)1318 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
1319   // ----------- S t a t e -------------
1320   //  -- eax : argc
1321   //  -- esp[0] : return address
1322   //  -- esp[4] : last argument
1323   // -----------------------------------
1324   Label generic_array_code;
1325 
1326   // Get the InternalArray function.
1327   __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi);
1328 
1329   if (FLAG_debug_code) {
1330     // Initial map for the builtin InternalArray function should be a map.
1331     __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
1332     // Will both indicate a NULL and a Smi.
1333     __ test(ebx, Immediate(kSmiTagMask));
1334     __ Assert(not_zero, kUnexpectedInitialMapForInternalArrayFunction);
1335     __ CmpObjectType(ebx, MAP_TYPE, ecx);
1336     __ Assert(equal, kUnexpectedInitialMapForInternalArrayFunction);
1337   }
1338 
1339   // Run the native code for the InternalArray function called as a normal
1340   // function.
1341   // tail call a stub
1342   InternalArrayConstructorStub stub(masm->isolate());
1343   __ TailCallStub(&stub);
1344 }
1345 
1346 
Generate_ArrayCode(MacroAssembler * masm)1347 void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
1348   // ----------- S t a t e -------------
1349   //  -- eax : argc
1350   //  -- esp[0] : return address
1351   //  -- esp[4] : last argument
1352   // -----------------------------------
1353   Label generic_array_code;
1354 
1355   // Get the Array function.
1356   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, edi);
1357   __ mov(edx, edi);
1358 
1359   if (FLAG_debug_code) {
1360     // Initial map for the builtin Array function should be a map.
1361     __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
1362     // Will both indicate a NULL and a Smi.
1363     __ test(ebx, Immediate(kSmiTagMask));
1364     __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction);
1365     __ CmpObjectType(ebx, MAP_TYPE, ecx);
1366     __ Assert(equal, kUnexpectedInitialMapForArrayFunction);
1367   }
1368 
1369   // Run the native code for the Array function called as a normal function.
1370   // tail call a stub
1371   __ mov(ebx, masm->isolate()->factory()->undefined_value());
1372   ArrayConstructorStub stub(masm->isolate());
1373   __ TailCallStub(&stub);
1374 }
1375 
1376 
1377 // static
Generate_NumberConstructor(MacroAssembler * masm)1378 void Builtins::Generate_NumberConstructor(MacroAssembler* masm) {
1379   // ----------- S t a t e -------------
1380   //  -- eax                 : number of arguments
1381   //  -- edi                 : constructor function
1382   //  -- esp[0]              : return address
1383   //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1384   //  -- esp[(argc + 1) * 4] : receiver
1385   // -----------------------------------
1386 
1387   // 1. Load the first argument into eax and get rid of the rest (including the
1388   // receiver).
1389   Label no_arguments;
1390   {
1391     __ test(eax, eax);
1392     __ j(zero, &no_arguments, Label::kNear);
1393     __ mov(ebx, Operand(esp, eax, times_pointer_size, 0));
1394     __ PopReturnAddressTo(ecx);
1395     __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1396     __ PushReturnAddressFrom(ecx);
1397     __ mov(eax, ebx);
1398   }
1399 
1400   // 2a. Convert the first argument to a number.
1401   ToNumberStub stub(masm->isolate());
1402   __ TailCallStub(&stub);
1403 
1404   // 2b. No arguments, return +0 (already in eax).
1405   __ bind(&no_arguments);
1406   __ ret(1 * kPointerSize);
1407 }
1408 
1409 
1410 // static
Generate_NumberConstructor_ConstructStub(MacroAssembler * masm)1411 void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) {
1412   // ----------- S t a t e -------------
1413   //  -- eax                 : number of arguments
1414   //  -- edi                 : constructor function
1415   //  -- edx                 : new target
1416   //  -- esp[0]              : return address
1417   //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1418   //  -- esp[(argc + 1) * 4] : receiver
1419   // -----------------------------------
1420 
1421   // 1. Make sure we operate in the context of the called function.
1422   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
1423 
1424   // 2. Load the first argument into ebx and get rid of the rest (including the
1425   // receiver).
1426   {
1427     Label no_arguments, done;
1428     __ test(eax, eax);
1429     __ j(zero, &no_arguments, Label::kNear);
1430     __ mov(ebx, Operand(esp, eax, times_pointer_size, 0));
1431     __ jmp(&done, Label::kNear);
1432     __ bind(&no_arguments);
1433     __ Move(ebx, Smi::FromInt(0));
1434     __ bind(&done);
1435     __ PopReturnAddressTo(ecx);
1436     __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1437     __ PushReturnAddressFrom(ecx);
1438   }
1439 
1440   // 3. Make sure ebx is a number.
1441   {
1442     Label done_convert;
1443     __ JumpIfSmi(ebx, &done_convert);
1444     __ CompareRoot(FieldOperand(ebx, HeapObject::kMapOffset),
1445                    Heap::kHeapNumberMapRootIndex);
1446     __ j(equal, &done_convert);
1447     {
1448       FrameScope scope(masm, StackFrame::INTERNAL);
1449       __ Push(edi);
1450       __ Push(edx);
1451       __ Move(eax, ebx);
1452       ToNumberStub stub(masm->isolate());
1453       __ CallStub(&stub);
1454       __ Move(ebx, eax);
1455       __ Pop(edx);
1456       __ Pop(edi);
1457     }
1458     __ bind(&done_convert);
1459   }
1460 
1461   // 4. Check if new target and constructor differ.
1462   Label new_object;
1463   __ cmp(edx, edi);
1464   __ j(not_equal, &new_object);
1465 
1466   // 5. Allocate a JSValue wrapper for the number.
1467   __ AllocateJSValue(eax, edi, ebx, ecx, &new_object);
1468   __ Ret();
1469 
1470   // 6. Fallback to the runtime to create new object.
1471   __ bind(&new_object);
1472   {
1473     FrameScope scope(masm, StackFrame::INTERNAL);
1474     __ Push(ebx);  // the first argument
1475     __ Push(edi);  // constructor function
1476     __ Push(edx);  // new target
1477     __ CallRuntime(Runtime::kNewObject);
1478     __ Pop(FieldOperand(eax, JSValue::kValueOffset));
1479   }
1480   __ Ret();
1481 }
1482 
1483 
1484 // static
Generate_StringConstructor(MacroAssembler * masm)1485 void Builtins::Generate_StringConstructor(MacroAssembler* masm) {
1486   // ----------- S t a t e -------------
1487   //  -- eax                 : number of arguments
1488   //  -- edi                 : constructor function
1489   //  -- esp[0]              : return address
1490   //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1491   //  -- esp[(argc + 1) * 4] : receiver
1492   // -----------------------------------
1493 
1494   // 1. Load the first argument into eax and get rid of the rest (including the
1495   // receiver).
1496   Label no_arguments;
1497   {
1498     __ test(eax, eax);
1499     __ j(zero, &no_arguments, Label::kNear);
1500     __ mov(ebx, Operand(esp, eax, times_pointer_size, 0));
1501     __ PopReturnAddressTo(ecx);
1502     __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1503     __ PushReturnAddressFrom(ecx);
1504     __ mov(eax, ebx);
1505   }
1506 
1507   // 2a. At least one argument, return eax if it's a string, otherwise
1508   // dispatch to appropriate conversion.
1509   Label to_string, symbol_descriptive_string;
1510   {
1511     __ JumpIfSmi(eax, &to_string, Label::kNear);
1512     STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE);
1513     __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
1514     __ j(above, &to_string, Label::kNear);
1515     __ j(equal, &symbol_descriptive_string, Label::kNear);
1516     __ Ret();
1517   }
1518 
1519   // 2b. No arguments, return the empty string (and pop the receiver).
1520   __ bind(&no_arguments);
1521   {
1522     __ LoadRoot(eax, Heap::kempty_stringRootIndex);
1523     __ ret(1 * kPointerSize);
1524   }
1525 
1526   // 3a. Convert eax to a string.
1527   __ bind(&to_string);
1528   {
1529     ToStringStub stub(masm->isolate());
1530     __ TailCallStub(&stub);
1531   }
1532 
1533   // 3b. Convert symbol in eax to a string.
1534   __ bind(&symbol_descriptive_string);
1535   {
1536     __ PopReturnAddressTo(ecx);
1537     __ Push(eax);
1538     __ PushReturnAddressFrom(ecx);
1539     __ TailCallRuntime(Runtime::kSymbolDescriptiveString);
1540   }
1541 }
1542 
1543 
1544 // static
Generate_StringConstructor_ConstructStub(MacroAssembler * masm)1545 void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
1546   // ----------- S t a t e -------------
1547   //  -- eax                 : number of arguments
1548   //  -- edi                 : constructor function
1549   //  -- edx                 : new target
1550   //  -- esp[0]              : return address
1551   //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
1552   //  -- esp[(argc + 1) * 4] : receiver
1553   // -----------------------------------
1554 
1555   // 1. Make sure we operate in the context of the called function.
1556   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
1557 
1558   // 2. Load the first argument into ebx and get rid of the rest (including the
1559   // receiver).
1560   {
1561     Label no_arguments, done;
1562     __ test(eax, eax);
1563     __ j(zero, &no_arguments, Label::kNear);
1564     __ mov(ebx, Operand(esp, eax, times_pointer_size, 0));
1565     __ jmp(&done, Label::kNear);
1566     __ bind(&no_arguments);
1567     __ LoadRoot(ebx, Heap::kempty_stringRootIndex);
1568     __ bind(&done);
1569     __ PopReturnAddressTo(ecx);
1570     __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize));
1571     __ PushReturnAddressFrom(ecx);
1572   }
1573 
1574   // 3. Make sure ebx is a string.
1575   {
1576     Label convert, done_convert;
1577     __ JumpIfSmi(ebx, &convert, Label::kNear);
1578     __ CmpObjectType(ebx, FIRST_NONSTRING_TYPE, ecx);
1579     __ j(below, &done_convert);
1580     __ bind(&convert);
1581     {
1582       FrameScope scope(masm, StackFrame::INTERNAL);
1583       ToStringStub stub(masm->isolate());
1584       __ Push(edi);
1585       __ Push(edx);
1586       __ Move(eax, ebx);
1587       __ CallStub(&stub);
1588       __ Move(ebx, eax);
1589       __ Pop(edx);
1590       __ Pop(edi);
1591     }
1592     __ bind(&done_convert);
1593   }
1594 
1595   // 4. Check if new target and constructor differ.
1596   Label new_object;
1597   __ cmp(edx, edi);
1598   __ j(not_equal, &new_object);
1599 
1600   // 5. Allocate a JSValue wrapper for the string.
1601   __ AllocateJSValue(eax, edi, ebx, ecx, &new_object);
1602   __ Ret();
1603 
1604   // 6. Fallback to the runtime to create new object.
1605   __ bind(&new_object);
1606   {
1607     FrameScope scope(masm, StackFrame::INTERNAL);
1608     __ Push(ebx);  // the first argument
1609     __ Push(edi);  // constructor function
1610     __ Push(edx);  // new target
1611     __ CallRuntime(Runtime::kNewObject);
1612     __ Pop(FieldOperand(eax, JSValue::kValueOffset));
1613   }
1614   __ Ret();
1615 }
1616 
1617 
ArgumentsAdaptorStackCheck(MacroAssembler * masm,Label * stack_overflow)1618 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm,
1619                                        Label* stack_overflow) {
1620   // ----------- S t a t e -------------
1621   //  -- eax : actual number of arguments
1622   //  -- ebx : expected number of arguments
1623   //  -- edx : new target (passed through to callee)
1624   // -----------------------------------
1625   // Check the stack for overflow. We are not trying to catch
1626   // interruptions (e.g. debug break and preemption) here, so the "real stack
1627   // limit" is checked.
1628   ExternalReference real_stack_limit =
1629       ExternalReference::address_of_real_stack_limit(masm->isolate());
1630   __ mov(edi, Operand::StaticVariable(real_stack_limit));
1631   // Make ecx the space we have left. The stack might already be overflowed
1632   // here which will cause ecx to become negative.
1633   __ mov(ecx, esp);
1634   __ sub(ecx, edi);
1635   // Make edi the space we need for the array when it is unrolled onto the
1636   // stack.
1637   __ mov(edi, ebx);
1638   __ shl(edi, kPointerSizeLog2);
1639   // Check if the arguments will overflow the stack.
1640   __ cmp(ecx, edi);
1641   __ j(less_equal, stack_overflow);  // Signed comparison.
1642 }
1643 
1644 
EnterArgumentsAdaptorFrame(MacroAssembler * masm)1645 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1646   __ push(ebp);
1647   __ mov(ebp, esp);
1648 
1649   // Store the arguments adaptor context sentinel.
1650   __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1651 
1652   // Push the function on the stack.
1653   __ push(edi);
1654 
1655   // Preserve the number of arguments on the stack. Must preserve eax,
1656   // ebx and ecx because these registers are used when copying the
1657   // arguments and the receiver.
1658   STATIC_ASSERT(kSmiTagSize == 1);
1659   __ lea(edi, Operand(eax, eax, times_1, kSmiTag));
1660   __ push(edi);
1661 }
1662 
1663 
LeaveArgumentsAdaptorFrame(MacroAssembler * masm)1664 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1665   // Retrieve the number of arguments from the stack.
1666   __ mov(ebx, Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset));
1667 
1668   // Leave the frame.
1669   __ leave();
1670 
1671   // Remove caller arguments from the stack.
1672   STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
1673   __ pop(ecx);
1674   __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));  // 1 ~ receiver
1675   __ push(ecx);
1676 }
1677 
1678 
1679 // static
Generate_Apply(MacroAssembler * masm)1680 void Builtins::Generate_Apply(MacroAssembler* masm) {
1681   // ----------- S t a t e -------------
1682   //  -- eax    : argumentsList
1683   //  -- edi    : target
1684   //  -- edx    : new.target (checked to be constructor or undefined)
1685   //  -- esp[0] : return address.
1686   //  -- esp[4] : thisArgument
1687   // -----------------------------------
1688 
1689   // Create the list of arguments from the array-like argumentsList.
1690   {
1691     Label create_arguments, create_array, create_runtime, done_create;
1692     __ JumpIfSmi(eax, &create_runtime);
1693 
1694     // Load the map of argumentsList into ecx.
1695     __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
1696 
1697     // Load native context into ebx.
1698     __ mov(ebx, NativeContextOperand());
1699 
1700     // Check if argumentsList is an (unmodified) arguments object.
1701     __ cmp(ecx, ContextOperand(ebx, Context::SLOPPY_ARGUMENTS_MAP_INDEX));
1702     __ j(equal, &create_arguments);
1703     __ cmp(ecx, ContextOperand(ebx, Context::STRICT_ARGUMENTS_MAP_INDEX));
1704     __ j(equal, &create_arguments);
1705 
1706     // Check if argumentsList is a fast JSArray.
1707     __ CmpInstanceType(ecx, JS_ARRAY_TYPE);
1708     __ j(equal, &create_array);
1709 
1710     // Ask the runtime to create the list (actually a FixedArray).
1711     __ bind(&create_runtime);
1712     {
1713       FrameScope scope(masm, StackFrame::INTERNAL);
1714       __ Push(edi);
1715       __ Push(edx);
1716       __ Push(eax);
1717       __ CallRuntime(Runtime::kCreateListFromArrayLike);
1718       __ Pop(edx);
1719       __ Pop(edi);
1720       __ mov(ebx, FieldOperand(eax, FixedArray::kLengthOffset));
1721       __ SmiUntag(ebx);
1722     }
1723     __ jmp(&done_create);
1724 
1725     // Try to create the list from an arguments object.
1726     __ bind(&create_arguments);
1727     __ mov(ebx,
1728            FieldOperand(eax, JSObject::kHeaderSize +
1729                                  Heap::kArgumentsLengthIndex * kPointerSize));
1730     __ mov(ecx, FieldOperand(eax, JSObject::kElementsOffset));
1731     __ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset));
1732     __ j(not_equal, &create_runtime);
1733     __ SmiUntag(ebx);
1734     __ mov(eax, ecx);
1735     __ jmp(&done_create);
1736 
1737     // Try to create the list from a JSArray object.
1738     __ bind(&create_array);
1739     __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset));
1740     __ DecodeField<Map::ElementsKindBits>(ecx);
1741     STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
1742     STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
1743     STATIC_ASSERT(FAST_ELEMENTS == 2);
1744     __ cmp(ecx, Immediate(FAST_ELEMENTS));
1745     __ j(above, &create_runtime);
1746     __ cmp(ecx, Immediate(FAST_HOLEY_SMI_ELEMENTS));
1747     __ j(equal, &create_runtime);
1748     __ mov(ebx, FieldOperand(eax, JSArray::kLengthOffset));
1749     __ SmiUntag(ebx);
1750     __ mov(eax, FieldOperand(eax, JSArray::kElementsOffset));
1751 
1752     __ bind(&done_create);
1753   }
1754 
1755   // Check for stack overflow.
1756   {
1757     // Check the stack for overflow. We are not trying to catch interruptions
1758     // (i.e. debug break and preemption) here, so check the "real stack limit".
1759     Label done;
1760     ExternalReference real_stack_limit =
1761         ExternalReference::address_of_real_stack_limit(masm->isolate());
1762     __ mov(ecx, Operand::StaticVariable(real_stack_limit));
1763     // Make ecx the space we have left. The stack might already be overflowed
1764     // here which will cause ecx to become negative.
1765     __ neg(ecx);
1766     __ add(ecx, esp);
1767     __ sar(ecx, kPointerSizeLog2);
1768     // Check if the arguments will overflow the stack.
1769     __ cmp(ecx, ebx);
1770     __ j(greater, &done, Label::kNear);  // Signed comparison.
1771     __ TailCallRuntime(Runtime::kThrowStackOverflow);
1772     __ bind(&done);
1773   }
1774 
1775   // ----------- S t a t e -------------
1776   //  -- edi    : target
1777   //  -- eax    : args (a FixedArray built from argumentsList)
1778   //  -- ebx    : len (number of elements to push from args)
1779   //  -- edx    : new.target (checked to be constructor or undefined)
1780   //  -- esp[0] : return address.
1781   //  -- esp[4] : thisArgument
1782   // -----------------------------------
1783 
1784   // Push arguments onto the stack (thisArgument is already on the stack).
1785   {
1786     __ push(edx);
1787     __ fld_s(MemOperand(esp, 0));
1788     __ lea(esp, Operand(esp, kFloatSize));
1789 
1790     __ PopReturnAddressTo(edx);
1791     __ Move(ecx, Immediate(0));
1792     Label done, loop;
1793     __ bind(&loop);
1794     __ cmp(ecx, ebx);
1795     __ j(equal, &done, Label::kNear);
1796     __ Push(
1797         FieldOperand(eax, ecx, times_pointer_size, FixedArray::kHeaderSize));
1798     __ inc(ecx);
1799     __ jmp(&loop);
1800     __ bind(&done);
1801     __ PushReturnAddressFrom(edx);
1802 
1803     __ lea(esp, Operand(esp, -kFloatSize));
1804     __ fstp_s(MemOperand(esp, 0));
1805     __ pop(edx);
1806 
1807     __ Move(eax, ebx);
1808   }
1809 
1810   // Dispatch to Call or Construct depending on whether new.target is undefined.
1811   {
1812     __ CompareRoot(edx, Heap::kUndefinedValueRootIndex);
1813     __ j(equal, masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1814     __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
1815   }
1816 }
1817 
1818 
1819 // static
Generate_CallFunction(MacroAssembler * masm,ConvertReceiverMode mode)1820 void Builtins::Generate_CallFunction(MacroAssembler* masm,
1821                                      ConvertReceiverMode mode) {
1822   // ----------- S t a t e -------------
1823   //  -- eax : the number of arguments (not including the receiver)
1824   //  -- edi : the function to call (checked to be a JSFunction)
1825   // -----------------------------------
1826   __ AssertFunction(edi);
1827 
1828   // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
1829   // Check that the function is not a "classConstructor".
1830   Label class_constructor;
1831   __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1832   __ test_b(FieldOperand(edx, SharedFunctionInfo::kFunctionKindByteOffset),
1833             SharedFunctionInfo::kClassConstructorBitsWithinByte);
1834   __ j(not_zero, &class_constructor);
1835 
1836   // Enter the context of the function; ToObject has to run in the function
1837   // context, and we also need to take the global proxy from the function
1838   // context in case of conversion.
1839   STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset ==
1840                 SharedFunctionInfo::kStrictModeByteOffset);
1841   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
1842   // We need to convert the receiver for non-native sloppy mode functions.
1843   Label done_convert;
1844   __ test_b(FieldOperand(edx, SharedFunctionInfo::kNativeByteOffset),
1845             (1 << SharedFunctionInfo::kNativeBitWithinByte) |
1846                 (1 << SharedFunctionInfo::kStrictModeBitWithinByte));
1847   __ j(not_zero, &done_convert);
1848   {
1849     // ----------- S t a t e -------------
1850     //  -- eax : the number of arguments (not including the receiver)
1851     //  -- edx : the shared function info.
1852     //  -- edi : the function to call (checked to be a JSFunction)
1853     //  -- esi : the function context.
1854     // -----------------------------------
1855 
1856     if (mode == ConvertReceiverMode::kNullOrUndefined) {
1857       // Patch receiver to global proxy.
1858       __ LoadGlobalProxy(ecx);
1859     } else {
1860       Label convert_to_object, convert_receiver;
1861       __ mov(ecx, Operand(esp, eax, times_pointer_size, kPointerSize));
1862       __ JumpIfSmi(ecx, &convert_to_object, Label::kNear);
1863       STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
1864       __ CmpObjectType(ecx, FIRST_JS_RECEIVER_TYPE, ebx);
1865       __ j(above_equal, &done_convert);
1866       if (mode != ConvertReceiverMode::kNotNullOrUndefined) {
1867         Label convert_global_proxy;
1868         __ JumpIfRoot(ecx, Heap::kUndefinedValueRootIndex,
1869                       &convert_global_proxy, Label::kNear);
1870         __ JumpIfNotRoot(ecx, Heap::kNullValueRootIndex, &convert_to_object,
1871                          Label::kNear);
1872         __ bind(&convert_global_proxy);
1873         {
1874           // Patch receiver to global proxy.
1875           __ LoadGlobalProxy(ecx);
1876         }
1877         __ jmp(&convert_receiver);
1878       }
1879       __ bind(&convert_to_object);
1880       {
1881         // Convert receiver using ToObject.
1882         // TODO(bmeurer): Inline the allocation here to avoid building the frame
1883         // in the fast case? (fall back to AllocateInNewSpace?)
1884         FrameScope scope(masm, StackFrame::INTERNAL);
1885         __ SmiTag(eax);
1886         __ Push(eax);
1887         __ Push(edi);
1888         __ mov(eax, ecx);
1889         ToObjectStub stub(masm->isolate());
1890         __ CallStub(&stub);
1891         __ mov(ecx, eax);
1892         __ Pop(edi);
1893         __ Pop(eax);
1894         __ SmiUntag(eax);
1895       }
1896       __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1897       __ bind(&convert_receiver);
1898     }
1899     __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), ecx);
1900   }
1901   __ bind(&done_convert);
1902 
1903   // ----------- S t a t e -------------
1904   //  -- eax : the number of arguments (not including the receiver)
1905   //  -- edx : the shared function info.
1906   //  -- edi : the function to call (checked to be a JSFunction)
1907   //  -- esi : the function context.
1908   // -----------------------------------
1909 
1910   __ mov(ebx,
1911          FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
1912   __ SmiUntag(ebx);
1913   ParameterCount actual(eax);
1914   ParameterCount expected(ebx);
1915   __ InvokeFunctionCode(edi, no_reg, expected, actual, JUMP_FUNCTION,
1916                         CheckDebugStepCallWrapper());
1917   // The function is a "classConstructor", need to raise an exception.
1918   __ bind(&class_constructor);
1919   {
1920     FrameScope frame(masm, StackFrame::INTERNAL);
1921     __ push(edi);
1922     __ CallRuntime(Runtime::kThrowConstructorNonCallableError);
1923   }
1924 }
1925 
1926 
1927 namespace {
1928 
Generate_PushBoundArguments(MacroAssembler * masm)1929 void Generate_PushBoundArguments(MacroAssembler* masm) {
1930   // ----------- S t a t e -------------
1931   //  -- eax : the number of arguments (not including the receiver)
1932   //  -- edx : new.target (only in case of [[Construct]])
1933   //  -- edi : target (checked to be a JSBoundFunction)
1934   // -----------------------------------
1935 
1936   // Load [[BoundArguments]] into ecx and length of that into ebx.
1937   Label no_bound_arguments;
1938   __ mov(ecx, FieldOperand(edi, JSBoundFunction::kBoundArgumentsOffset));
1939   __ mov(ebx, FieldOperand(ecx, FixedArray::kLengthOffset));
1940   __ SmiUntag(ebx);
1941   __ test(ebx, ebx);
1942   __ j(zero, &no_bound_arguments);
1943   {
1944     // ----------- S t a t e -------------
1945     //  -- eax : the number of arguments (not including the receiver)
1946     //  -- edx : new.target (only in case of [[Construct]])
1947     //  -- edi : target (checked to be a JSBoundFunction)
1948     //  -- ecx : the [[BoundArguments]] (implemented as FixedArray)
1949     //  -- ebx : the number of [[BoundArguments]]
1950     // -----------------------------------
1951 
1952     // Reserve stack space for the [[BoundArguments]].
1953     {
1954       Label done;
1955       __ lea(ecx, Operand(ebx, times_pointer_size, 0));
1956       __ sub(esp, ecx);
1957       // Check the stack for overflow. We are not trying to catch interruptions
1958       // (i.e. debug break and preemption) here, so check the "real stack
1959       // limit".
1960       __ CompareRoot(esp, ecx, Heap::kRealStackLimitRootIndex);
1961       __ j(greater, &done, Label::kNear);  // Signed comparison.
1962       // Restore the stack pointer.
1963       __ lea(esp, Operand(esp, ebx, times_pointer_size, 0));
1964       {
1965         FrameScope scope(masm, StackFrame::MANUAL);
1966         __ EnterFrame(StackFrame::INTERNAL);
1967         __ CallRuntime(Runtime::kThrowStackOverflow);
1968       }
1969       __ bind(&done);
1970     }
1971 
1972     // Adjust effective number of arguments to include return address.
1973     __ inc(eax);
1974 
1975     // Relocate arguments and return address down the stack.
1976     {
1977       Label loop;
1978       __ Set(ecx, 0);
1979       __ lea(ebx, Operand(esp, ebx, times_pointer_size, 0));
1980       __ bind(&loop);
1981       __ fld_s(Operand(ebx, ecx, times_pointer_size, 0));
1982       __ fstp_s(Operand(esp, ecx, times_pointer_size, 0));
1983       __ inc(ecx);
1984       __ cmp(ecx, eax);
1985       __ j(less, &loop);
1986     }
1987 
1988     // Copy [[BoundArguments]] to the stack (below the arguments).
1989     {
1990       Label loop;
1991       __ mov(ecx, FieldOperand(edi, JSBoundFunction::kBoundArgumentsOffset));
1992       __ mov(ebx, FieldOperand(ecx, FixedArray::kLengthOffset));
1993       __ SmiUntag(ebx);
1994       __ bind(&loop);
1995       __ dec(ebx);
1996       __ fld_s(
1997           FieldOperand(ecx, ebx, times_pointer_size, FixedArray::kHeaderSize));
1998       __ fstp_s(Operand(esp, eax, times_pointer_size, 0));
1999       __ lea(eax, Operand(eax, 1));
2000       __ j(greater, &loop);
2001     }
2002 
2003     // Adjust effective number of arguments (eax contains the number of
2004     // arguments from the call plus return address plus the number of
2005     // [[BoundArguments]]), so we need to subtract one for the return address.
2006     __ dec(eax);
2007   }
2008   __ bind(&no_bound_arguments);
2009 }
2010 
2011 }  // namespace
2012 
2013 
2014 // static
Generate_CallBoundFunction(MacroAssembler * masm)2015 void Builtins::Generate_CallBoundFunction(MacroAssembler* masm) {
2016   // ----------- S t a t e -------------
2017   //  -- eax : the number of arguments (not including the receiver)
2018   //  -- edi : the function to call (checked to be a JSBoundFunction)
2019   // -----------------------------------
2020   __ AssertBoundFunction(edi);
2021 
2022   // Patch the receiver to [[BoundThis]].
2023   __ mov(ebx, FieldOperand(edi, JSBoundFunction::kBoundThisOffset));
2024   __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), ebx);
2025 
2026   // Push the [[BoundArguments]] onto the stack.
2027   Generate_PushBoundArguments(masm);
2028 
2029   // Call the [[BoundTargetFunction]] via the Call builtin.
2030   __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset));
2031   __ mov(ecx, Operand::StaticVariable(ExternalReference(
2032                   Builtins::kCall_ReceiverIsAny, masm->isolate())));
2033   __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
2034   __ jmp(ecx);
2035 }
2036 
2037 
2038 // static
Generate_Call(MacroAssembler * masm,ConvertReceiverMode mode)2039 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
2040   // ----------- S t a t e -------------
2041   //  -- eax : the number of arguments (not including the receiver)
2042   //  -- edi : the target to call (can be any Object).
2043   // -----------------------------------
2044 
2045   Label non_callable, non_function, non_smi;
2046   __ JumpIfSmi(edi, &non_callable);
2047   __ bind(&non_smi);
2048   __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
2049   __ j(equal, masm->isolate()->builtins()->CallFunction(mode),
2050        RelocInfo::CODE_TARGET);
2051   __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE);
2052   __ j(equal, masm->isolate()->builtins()->CallBoundFunction(),
2053        RelocInfo::CODE_TARGET);
2054   __ CmpInstanceType(ecx, JS_PROXY_TYPE);
2055   __ j(not_equal, &non_function);
2056 
2057   // 1. Runtime fallback for Proxy [[Call]].
2058   __ PopReturnAddressTo(ecx);
2059   __ Push(edi);
2060   __ PushReturnAddressFrom(ecx);
2061   // Increase the arguments size to include the pushed function and the
2062   // existing receiver on the stack.
2063   __ add(eax, Immediate(2));
2064   // Tail-call to the runtime.
2065   __ JumpToExternalReference(
2066       ExternalReference(Runtime::kJSProxyCall, masm->isolate()));
2067 
2068   // 2. Call to something else, which might have a [[Call]] internal method (if
2069   // not we raise an exception).
2070   __ bind(&non_function);
2071   // Check if target has a [[Call]] internal method.
2072   __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable);
2073   __ j(zero, &non_callable, Label::kNear);
2074   // Overwrite the original receiver with the (original) target.
2075   __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi);
2076   // Let the "call_as_function_delegate" take care of the rest.
2077   __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, edi);
2078   __ Jump(masm->isolate()->builtins()->CallFunction(
2079               ConvertReceiverMode::kNotNullOrUndefined),
2080           RelocInfo::CODE_TARGET);
2081 
2082   // 3. Call to something that is not callable.
2083   __ bind(&non_callable);
2084   {
2085     FrameScope scope(masm, StackFrame::INTERNAL);
2086     __ Push(edi);
2087     __ CallRuntime(Runtime::kThrowCalledNonCallable);
2088   }
2089 }
2090 
2091 
2092 // static
Generate_ConstructFunction(MacroAssembler * masm)2093 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) {
2094   // ----------- S t a t e -------------
2095   //  -- eax : the number of arguments (not including the receiver)
2096   //  -- edx : the new target (checked to be a constructor)
2097   //  -- edi : the constructor to call (checked to be a JSFunction)
2098   // -----------------------------------
2099   __ AssertFunction(edi);
2100 
2101   // Calling convention for function specific ConstructStubs require
2102   // ebx to contain either an AllocationSite or undefined.
2103   __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex);
2104 
2105   // Tail call to the function-specific construct stub (still in the caller
2106   // context at this point).
2107   __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2108   __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset));
2109   __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
2110   __ jmp(ecx);
2111 }
2112 
2113 
2114 // static
Generate_ConstructBoundFunction(MacroAssembler * masm)2115 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) {
2116   // ----------- S t a t e -------------
2117   //  -- eax : the number of arguments (not including the receiver)
2118   //  -- edx : the new target (checked to be a constructor)
2119   //  -- edi : the constructor to call (checked to be a JSBoundFunction)
2120   // -----------------------------------
2121   __ AssertBoundFunction(edi);
2122 
2123   // Push the [[BoundArguments]] onto the stack.
2124   Generate_PushBoundArguments(masm);
2125 
2126   // Patch new.target to [[BoundTargetFunction]] if new.target equals target.
2127   {
2128     Label done;
2129     __ cmp(edi, edx);
2130     __ j(not_equal, &done, Label::kNear);
2131     __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset));
2132     __ bind(&done);
2133   }
2134 
2135   // Construct the [[BoundTargetFunction]] via the Construct builtin.
2136   __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset));
2137   __ mov(ecx, Operand::StaticVariable(
2138                   ExternalReference(Builtins::kConstruct, masm->isolate())));
2139   __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
2140   __ jmp(ecx);
2141 }
2142 
2143 
2144 // static
Generate_ConstructProxy(MacroAssembler * masm)2145 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) {
2146   // ----------- S t a t e -------------
2147   //  -- eax : the number of arguments (not including the receiver)
2148   //  -- edi : the constructor to call (checked to be a JSProxy)
2149   //  -- edx : the new target (either the same as the constructor or
2150   //           the JSFunction on which new was invoked initially)
2151   // -----------------------------------
2152 
2153   // Call into the Runtime for Proxy [[Construct]].
2154   __ PopReturnAddressTo(ecx);
2155   __ Push(edi);
2156   __ Push(edx);
2157   __ PushReturnAddressFrom(ecx);
2158   // Include the pushed new_target, constructor and the receiver.
2159   __ add(eax, Immediate(3));
2160   // Tail-call to the runtime.
2161   __ JumpToExternalReference(
2162       ExternalReference(Runtime::kJSProxyConstruct, masm->isolate()));
2163 }
2164 
2165 
2166 // static
Generate_Construct(MacroAssembler * masm)2167 void Builtins::Generate_Construct(MacroAssembler* masm) {
2168   // ----------- S t a t e -------------
2169   //  -- eax : the number of arguments (not including the receiver)
2170   //  -- edx : the new target (either the same as the constructor or
2171   //           the JSFunction on which new was invoked initially)
2172   //  -- edi : the constructor to call (can be any Object)
2173   // -----------------------------------
2174 
2175   // Check if target is a Smi.
2176   Label non_constructor;
2177   __ JumpIfSmi(edi, &non_constructor, Label::kNear);
2178 
2179   // Dispatch based on instance type.
2180   __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
2181   __ j(equal, masm->isolate()->builtins()->ConstructFunction(),
2182        RelocInfo::CODE_TARGET);
2183 
2184   // Check if target has a [[Construct]] internal method.
2185   __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor);
2186   __ j(zero, &non_constructor, Label::kNear);
2187 
2188   // Only dispatch to bound functions after checking whether they are
2189   // constructors.
2190   __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE);
2191   __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(),
2192        RelocInfo::CODE_TARGET);
2193 
2194   // Only dispatch to proxies after checking whether they are constructors.
2195   __ CmpInstanceType(ecx, JS_PROXY_TYPE);
2196   __ j(equal, masm->isolate()->builtins()->ConstructProxy(),
2197        RelocInfo::CODE_TARGET);
2198 
2199   // Called Construct on an exotic Object with a [[Construct]] internal method.
2200   {
2201     // Overwrite the original receiver with the (original) target.
2202     __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi);
2203     // Let the "call_as_constructor_delegate" take care of the rest.
2204     __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, edi);
2205     __ Jump(masm->isolate()->builtins()->CallFunction(),
2206             RelocInfo::CODE_TARGET);
2207   }
2208 
2209   // Called Construct on an Object that doesn't have a [[Construct]] internal
2210   // method.
2211   __ bind(&non_constructor);
2212   __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(),
2213           RelocInfo::CODE_TARGET);
2214 }
2215 
2216 
Generate_ArgumentsAdaptorTrampoline(MacroAssembler * masm)2217 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
2218   // ----------- S t a t e -------------
2219   //  -- eax : actual number of arguments
2220   //  -- ebx : expected number of arguments
2221   //  -- edx : new target (passed through to callee)
2222   //  -- edi : function (passed through to callee)
2223   // -----------------------------------
2224 
2225   Label invoke, dont_adapt_arguments, stack_overflow;
2226   __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1);
2227 
2228   Label enough, too_few;
2229   __ cmp(eax, ebx);
2230   __ j(less, &too_few);
2231   __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel);
2232   __ j(equal, &dont_adapt_arguments);
2233 
2234   {  // Enough parameters: Actual >= expected.
2235     __ bind(&enough);
2236     EnterArgumentsAdaptorFrame(masm);
2237     ArgumentsAdaptorStackCheck(masm, &stack_overflow);
2238 
2239     // Copy receiver and all expected arguments.
2240     const int offset = StandardFrameConstants::kCallerSPOffset;
2241     __ lea(edi, Operand(ebp, eax, times_4, offset));
2242     __ mov(eax, -1);  // account for receiver
2243 
2244     Label copy;
2245     __ bind(&copy);
2246     __ inc(eax);
2247     __ push(Operand(edi, 0));
2248     __ sub(edi, Immediate(kPointerSize));
2249     __ cmp(eax, ebx);
2250     __ j(less, &copy);
2251     // eax now contains the expected number of arguments.
2252     __ jmp(&invoke);
2253   }
2254 
2255   {  // Too few parameters: Actual < expected.
2256     __ bind(&too_few);
2257 
2258     // If the function is strong we need to throw an error.
2259     Label no_strong_error;
2260     __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2261     __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrongModeByteOffset),
2262               1 << SharedFunctionInfo::kStrongModeBitWithinByte);
2263     __ j(equal, &no_strong_error, Label::kNear);
2264 
2265     // What we really care about is the required number of arguments.
2266     __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kLengthOffset));
2267     __ SmiUntag(ecx);
2268     __ cmp(eax, ecx);
2269     __ j(greater_equal, &no_strong_error, Label::kNear);
2270 
2271     {
2272       FrameScope frame(masm, StackFrame::MANUAL);
2273       EnterArgumentsAdaptorFrame(masm);
2274       __ CallRuntime(Runtime::kThrowStrongModeTooFewArguments);
2275     }
2276 
2277     __ bind(&no_strong_error);
2278     EnterArgumentsAdaptorFrame(masm);
2279     ArgumentsAdaptorStackCheck(masm, &stack_overflow);
2280 
2281     // Remember expected arguments in ecx.
2282     __ mov(ecx, ebx);
2283 
2284     // Copy receiver and all actual arguments.
2285     const int offset = StandardFrameConstants::kCallerSPOffset;
2286     __ lea(edi, Operand(ebp, eax, times_4, offset));
2287     // ebx = expected - actual.
2288     __ sub(ebx, eax);
2289     // eax = -actual - 1
2290     __ neg(eax);
2291     __ sub(eax, Immediate(1));
2292 
2293     Label copy;
2294     __ bind(&copy);
2295     __ inc(eax);
2296     __ push(Operand(edi, 0));
2297     __ sub(edi, Immediate(kPointerSize));
2298     __ test(eax, eax);
2299     __ j(not_zero, &copy);
2300 
2301     // Fill remaining expected arguments with undefined values.
2302     Label fill;
2303     __ bind(&fill);
2304     __ inc(eax);
2305     __ push(Immediate(masm->isolate()->factory()->undefined_value()));
2306     __ cmp(eax, ebx);
2307     __ j(less, &fill);
2308 
2309     // Restore expected arguments.
2310     __ mov(eax, ecx);
2311   }
2312 
2313   // Call the entry point.
2314   __ bind(&invoke);
2315   // Restore function pointer.
2316   __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
2317   // eax : expected number of arguments
2318   // edx : new target (passed through to callee)
2319   // edi : function (passed through to callee)
2320   __ mov(ecx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
2321   __ call(ecx);
2322 
2323   // Store offset of return address for deoptimizer.
2324   masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
2325 
2326   // Leave frame and return.
2327   LeaveArgumentsAdaptorFrame(masm);
2328   __ ret(0);
2329 
2330   // -------------------------------------------
2331   // Dont adapt arguments.
2332   // -------------------------------------------
2333   __ bind(&dont_adapt_arguments);
2334   __ mov(ecx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
2335   __ jmp(ecx);
2336 
2337   __ bind(&stack_overflow);
2338   {
2339     FrameScope frame(masm, StackFrame::MANUAL);
2340     __ CallRuntime(Runtime::kThrowStackOverflow);
2341     __ int3();
2342   }
2343 }
2344 
2345 
CompatibleReceiverCheck(MacroAssembler * masm,Register receiver,Register function_template_info,Register scratch0,Register scratch1,Label * receiver_check_failed)2346 static void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver,
2347                                     Register function_template_info,
2348                                     Register scratch0, Register scratch1,
2349                                     Label* receiver_check_failed) {
2350   // If there is no signature, return the holder.
2351   __ CompareRoot(FieldOperand(function_template_info,
2352                               FunctionTemplateInfo::kSignatureOffset),
2353                  Heap::kUndefinedValueRootIndex);
2354   Label receiver_check_passed;
2355   __ j(equal, &receiver_check_passed, Label::kNear);
2356 
2357   // Walk the prototype chain.
2358   __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset));
2359   Label prototype_loop_start;
2360   __ bind(&prototype_loop_start);
2361 
2362   // Get the constructor, if any.
2363   __ GetMapConstructor(scratch0, scratch0, scratch1);
2364   __ CmpInstanceType(scratch1, JS_FUNCTION_TYPE);
2365   Label next_prototype;
2366   __ j(not_equal, &next_prototype, Label::kNear);
2367 
2368   // Get the constructor's signature.
2369   __ mov(scratch0,
2370          FieldOperand(scratch0, JSFunction::kSharedFunctionInfoOffset));
2371   __ mov(scratch0,
2372          FieldOperand(scratch0, SharedFunctionInfo::kFunctionDataOffset));
2373 
2374   // Loop through the chain of inheriting function templates.
2375   Label function_template_loop;
2376   __ bind(&function_template_loop);
2377 
2378   // If the signatures match, we have a compatible receiver.
2379   __ cmp(scratch0, FieldOperand(function_template_info,
2380                                 FunctionTemplateInfo::kSignatureOffset));
2381   __ j(equal, &receiver_check_passed, Label::kNear);
2382 
2383   // If the current type is not a FunctionTemplateInfo, load the next prototype
2384   // in the chain.
2385   __ JumpIfSmi(scratch0, &next_prototype, Label::kNear);
2386   __ CmpObjectType(scratch0, FUNCTION_TEMPLATE_INFO_TYPE, scratch1);
2387   __ j(not_equal, &next_prototype, Label::kNear);
2388 
2389   // Otherwise load the parent function template and iterate.
2390   __ mov(scratch0,
2391          FieldOperand(scratch0, FunctionTemplateInfo::kParentTemplateOffset));
2392   __ jmp(&function_template_loop, Label::kNear);
2393 
2394   // Load the next prototype.
2395   __ bind(&next_prototype);
2396   __ mov(receiver, FieldOperand(receiver, HeapObject::kMapOffset));
2397   __ mov(receiver, FieldOperand(receiver, Map::kPrototypeOffset));
2398   // End if the prototype is null or not hidden.
2399   __ CompareRoot(receiver, Heap::kNullValueRootIndex);
2400   __ j(equal, receiver_check_failed);
2401   __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset));
2402   __ test(FieldOperand(scratch0, Map::kBitField3Offset),
2403           Immediate(Map::IsHiddenPrototype::kMask));
2404   __ j(zero, receiver_check_failed);
2405   // Iterate.
2406   __ jmp(&prototype_loop_start, Label::kNear);
2407 
2408   __ bind(&receiver_check_passed);
2409 }
2410 
2411 
Generate_HandleFastApiCall(MacroAssembler * masm)2412 void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
2413   // ----------- S t a t e -------------
2414   //  -- eax                : number of arguments (not including the receiver)
2415   //  -- edi                : callee
2416   //  -- esi                : context
2417   //  -- esp[0]             : return address
2418   //  -- esp[4]             : last argument
2419   //  -- ...
2420   //  -- esp[eax * 4]       : first argument
2421   //  -- esp[(eax + 1) * 4] : receiver
2422   // -----------------------------------
2423 
2424   // Load the FunctionTemplateInfo.
2425   __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2426   __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFunctionDataOffset));
2427 
2428   // Do the compatible receiver check.
2429   Label receiver_check_failed;
2430   __ mov(ecx, Operand(esp, eax, times_pointer_size, kPCOnStackSize));
2431   __ Push(eax);
2432   CompatibleReceiverCheck(masm, ecx, ebx, edx, eax, &receiver_check_failed);
2433   __ Pop(eax);
2434   // Get the callback offset from the FunctionTemplateInfo, and jump to the
2435   // beginning of the code.
2436   __ mov(edx, FieldOperand(ebx, FunctionTemplateInfo::kCallCodeOffset));
2437   __ mov(edx, FieldOperand(edx, CallHandlerInfo::kFastHandlerOffset));
2438   __ add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag));
2439   __ jmp(edx);
2440 
2441   // Compatible receiver check failed: pop return address, arguments and
2442   // receiver and throw an Illegal Invocation exception.
2443   __ bind(&receiver_check_failed);
2444   __ Pop(eax);
2445   __ PopReturnAddressTo(ebx);
2446   __ lea(eax, Operand(eax, times_pointer_size, 1 * kPointerSize));
2447   __ add(esp, eax);
2448   __ PushReturnAddressFrom(ebx);
2449   {
2450     FrameScope scope(masm, StackFrame::INTERNAL);
2451     __ TailCallRuntime(Runtime::kThrowIllegalInvocation);
2452   }
2453 }
2454 
2455 
Generate_OnStackReplacement(MacroAssembler * masm)2456 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
2457   // Lookup the function in the JavaScript frame.
2458   __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
2459   {
2460     FrameScope scope(masm, StackFrame::INTERNAL);
2461     // Pass function as argument.
2462     __ push(eax);
2463     __ CallRuntime(Runtime::kCompileForOnStackReplacement);
2464   }
2465 
2466   Label skip;
2467   // If the code object is null, just return to the unoptimized code.
2468   __ cmp(eax, Immediate(0));
2469   __ j(not_equal, &skip, Label::kNear);
2470   __ ret(0);
2471 
2472   __ bind(&skip);
2473 
2474   // Load deoptimization data from the code object.
2475   __ mov(ebx, Operand(eax, Code::kDeoptimizationDataOffset - kHeapObjectTag));
2476 
2477   // Load the OSR entrypoint offset from the deoptimization data.
2478   __ mov(ebx, Operand(ebx, FixedArray::OffsetOfElementAt(
2479       DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag));
2480   __ SmiUntag(ebx);
2481 
2482   // Compute the target address = code_obj + header_size + osr_offset
2483   __ lea(eax, Operand(eax, ebx, times_1, Code::kHeaderSize - kHeapObjectTag));
2484 
2485   // Overwrite the return address on the stack.
2486   __ mov(Operand(esp, 0), eax);
2487 
2488   // And "return" to the OSR entry point of the function.
2489   __ ret(0);
2490 }
2491 
2492 
Generate_OsrAfterStackCheck(MacroAssembler * masm)2493 void Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
2494   // We check the stack limit as indicator that recompilation might be done.
2495   Label ok;
2496   ExternalReference stack_limit =
2497       ExternalReference::address_of_stack_limit(masm->isolate());
2498   __ cmp(esp, Operand::StaticVariable(stack_limit));
2499   __ j(above_equal, &ok, Label::kNear);
2500   {
2501     FrameScope scope(masm, StackFrame::INTERNAL);
2502     __ CallRuntime(Runtime::kStackGuard);
2503   }
2504   __ jmp(masm->isolate()->builtins()->OnStackReplacement(),
2505          RelocInfo::CODE_TARGET);
2506 
2507   __ bind(&ok);
2508   __ ret(0);
2509 }
2510 
2511 #undef __
2512 }  // namespace internal
2513 }  // namespace v8
2514 
2515 #endif  // V8_TARGET_ARCH_X87
2516