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_IA32
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/ia32/frames-ia32.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     __ movd(xmm0, edx);
1787     __ PopReturnAddressTo(edx);
1788     __ Move(ecx, Immediate(0));
1789     Label done, loop;
1790     __ bind(&loop);
1791     __ cmp(ecx, ebx);
1792     __ j(equal, &done, Label::kNear);
1793     __ Push(
1794         FieldOperand(eax, ecx, times_pointer_size, FixedArray::kHeaderSize));
1795     __ inc(ecx);
1796     __ jmp(&loop);
1797     __ bind(&done);
1798     __ PushReturnAddressFrom(edx);
1799     __ movd(edx, xmm0);
1800     __ Move(eax, ebx);
1801   }
1802 
1803   // Dispatch to Call or Construct depending on whether new.target is undefined.
1804   {
1805     __ CompareRoot(edx, Heap::kUndefinedValueRootIndex);
1806     __ j(equal, masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
1807     __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
1808   }
1809 }
1810 
1811 
1812 // static
Generate_CallFunction(MacroAssembler * masm,ConvertReceiverMode mode)1813 void Builtins::Generate_CallFunction(MacroAssembler* masm,
1814                                      ConvertReceiverMode mode) {
1815   // ----------- S t a t e -------------
1816   //  -- eax : the number of arguments (not including the receiver)
1817   //  -- edi : the function to call (checked to be a JSFunction)
1818   // -----------------------------------
1819   __ AssertFunction(edi);
1820 
1821   // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
1822   // Check that the function is not a "classConstructor".
1823   Label class_constructor;
1824   __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1825   __ test_b(FieldOperand(edx, SharedFunctionInfo::kFunctionKindByteOffset),
1826             SharedFunctionInfo::kClassConstructorBitsWithinByte);
1827   __ j(not_zero, &class_constructor);
1828 
1829   // Enter the context of the function; ToObject has to run in the function
1830   // context, and we also need to take the global proxy from the function
1831   // context in case of conversion.
1832   STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset ==
1833                 SharedFunctionInfo::kStrictModeByteOffset);
1834   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
1835   // We need to convert the receiver for non-native sloppy mode functions.
1836   Label done_convert;
1837   __ test_b(FieldOperand(edx, SharedFunctionInfo::kNativeByteOffset),
1838             (1 << SharedFunctionInfo::kNativeBitWithinByte) |
1839                 (1 << SharedFunctionInfo::kStrictModeBitWithinByte));
1840   __ j(not_zero, &done_convert);
1841   {
1842     // ----------- S t a t e -------------
1843     //  -- eax : the number of arguments (not including the receiver)
1844     //  -- edx : the shared function info.
1845     //  -- edi : the function to call (checked to be a JSFunction)
1846     //  -- esi : the function context.
1847     // -----------------------------------
1848 
1849     if (mode == ConvertReceiverMode::kNullOrUndefined) {
1850       // Patch receiver to global proxy.
1851       __ LoadGlobalProxy(ecx);
1852     } else {
1853       Label convert_to_object, convert_receiver;
1854       __ mov(ecx, Operand(esp, eax, times_pointer_size, kPointerSize));
1855       __ JumpIfSmi(ecx, &convert_to_object, Label::kNear);
1856       STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
1857       __ CmpObjectType(ecx, FIRST_JS_RECEIVER_TYPE, ebx);
1858       __ j(above_equal, &done_convert);
1859       if (mode != ConvertReceiverMode::kNotNullOrUndefined) {
1860         Label convert_global_proxy;
1861         __ JumpIfRoot(ecx, Heap::kUndefinedValueRootIndex,
1862                       &convert_global_proxy, Label::kNear);
1863         __ JumpIfNotRoot(ecx, Heap::kNullValueRootIndex, &convert_to_object,
1864                          Label::kNear);
1865         __ bind(&convert_global_proxy);
1866         {
1867           // Patch receiver to global proxy.
1868           __ LoadGlobalProxy(ecx);
1869         }
1870         __ jmp(&convert_receiver);
1871       }
1872       __ bind(&convert_to_object);
1873       {
1874         // Convert receiver using ToObject.
1875         // TODO(bmeurer): Inline the allocation here to avoid building the frame
1876         // in the fast case? (fall back to AllocateInNewSpace?)
1877         FrameScope scope(masm, StackFrame::INTERNAL);
1878         __ SmiTag(eax);
1879         __ Push(eax);
1880         __ Push(edi);
1881         __ mov(eax, ecx);
1882         ToObjectStub stub(masm->isolate());
1883         __ CallStub(&stub);
1884         __ mov(ecx, eax);
1885         __ Pop(edi);
1886         __ Pop(eax);
1887         __ SmiUntag(eax);
1888       }
1889       __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
1890       __ bind(&convert_receiver);
1891     }
1892     __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), ecx);
1893   }
1894   __ bind(&done_convert);
1895 
1896   // ----------- S t a t e -------------
1897   //  -- eax : the number of arguments (not including the receiver)
1898   //  -- edx : the shared function info.
1899   //  -- edi : the function to call (checked to be a JSFunction)
1900   //  -- esi : the function context.
1901   // -----------------------------------
1902 
1903   __ mov(ebx,
1904          FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
1905   __ SmiUntag(ebx);
1906   ParameterCount actual(eax);
1907   ParameterCount expected(ebx);
1908   __ InvokeFunctionCode(edi, no_reg, expected, actual, JUMP_FUNCTION,
1909                         CheckDebugStepCallWrapper());
1910   // The function is a "classConstructor", need to raise an exception.
1911   __ bind(&class_constructor);
1912   {
1913     FrameScope frame(masm, StackFrame::INTERNAL);
1914     __ push(edi);
1915     __ CallRuntime(Runtime::kThrowConstructorNonCallableError);
1916   }
1917 }
1918 
1919 
1920 namespace {
1921 
Generate_PushBoundArguments(MacroAssembler * masm)1922 void Generate_PushBoundArguments(MacroAssembler* masm) {
1923   // ----------- S t a t e -------------
1924   //  -- eax : the number of arguments (not including the receiver)
1925   //  -- edx : new.target (only in case of [[Construct]])
1926   //  -- edi : target (checked to be a JSBoundFunction)
1927   // -----------------------------------
1928 
1929   // Load [[BoundArguments]] into ecx and length of that into ebx.
1930   Label no_bound_arguments;
1931   __ mov(ecx, FieldOperand(edi, JSBoundFunction::kBoundArgumentsOffset));
1932   __ mov(ebx, FieldOperand(ecx, FixedArray::kLengthOffset));
1933   __ SmiUntag(ebx);
1934   __ test(ebx, ebx);
1935   __ j(zero, &no_bound_arguments);
1936   {
1937     // ----------- S t a t e -------------
1938     //  -- eax : the number of arguments (not including the receiver)
1939     //  -- edx : new.target (only in case of [[Construct]])
1940     //  -- edi : target (checked to be a JSBoundFunction)
1941     //  -- ecx : the [[BoundArguments]] (implemented as FixedArray)
1942     //  -- ebx : the number of [[BoundArguments]]
1943     // -----------------------------------
1944 
1945     // Reserve stack space for the [[BoundArguments]].
1946     {
1947       Label done;
1948       __ lea(ecx, Operand(ebx, times_pointer_size, 0));
1949       __ sub(esp, ecx);
1950       // Check the stack for overflow. We are not trying to catch interruptions
1951       // (i.e. debug break and preemption) here, so check the "real stack
1952       // limit".
1953       __ CompareRoot(esp, ecx, Heap::kRealStackLimitRootIndex);
1954       __ j(greater, &done, Label::kNear);  // Signed comparison.
1955       // Restore the stack pointer.
1956       __ lea(esp, Operand(esp, ebx, times_pointer_size, 0));
1957       {
1958         FrameScope scope(masm, StackFrame::MANUAL);
1959         __ EnterFrame(StackFrame::INTERNAL);
1960         __ CallRuntime(Runtime::kThrowStackOverflow);
1961       }
1962       __ bind(&done);
1963     }
1964 
1965     // Adjust effective number of arguments to include return address.
1966     __ inc(eax);
1967 
1968     // Relocate arguments and return address down the stack.
1969     {
1970       Label loop;
1971       __ Set(ecx, 0);
1972       __ lea(ebx, Operand(esp, ebx, times_pointer_size, 0));
1973       __ bind(&loop);
1974       __ movd(xmm0, Operand(ebx, ecx, times_pointer_size, 0));
1975       __ movd(Operand(esp, ecx, times_pointer_size, 0), xmm0);
1976       __ inc(ecx);
1977       __ cmp(ecx, eax);
1978       __ j(less, &loop);
1979     }
1980 
1981     // Copy [[BoundArguments]] to the stack (below the arguments).
1982     {
1983       Label loop;
1984       __ mov(ecx, FieldOperand(edi, JSBoundFunction::kBoundArgumentsOffset));
1985       __ mov(ebx, FieldOperand(ecx, FixedArray::kLengthOffset));
1986       __ SmiUntag(ebx);
1987       __ bind(&loop);
1988       __ dec(ebx);
1989       __ movd(xmm0, FieldOperand(ecx, ebx, times_pointer_size,
1990                                  FixedArray::kHeaderSize));
1991       __ movd(Operand(esp, eax, times_pointer_size, 0), xmm0);
1992       __ lea(eax, Operand(eax, 1));
1993       __ j(greater, &loop);
1994     }
1995 
1996     // Adjust effective number of arguments (eax contains the number of
1997     // arguments from the call plus return address plus the number of
1998     // [[BoundArguments]]), so we need to subtract one for the return address.
1999     __ dec(eax);
2000   }
2001   __ bind(&no_bound_arguments);
2002 }
2003 
2004 }  // namespace
2005 
2006 
2007 // static
Generate_CallBoundFunction(MacroAssembler * masm)2008 void Builtins::Generate_CallBoundFunction(MacroAssembler* masm) {
2009   // ----------- S t a t e -------------
2010   //  -- eax : the number of arguments (not including the receiver)
2011   //  -- edi : the function to call (checked to be a JSBoundFunction)
2012   // -----------------------------------
2013   __ AssertBoundFunction(edi);
2014 
2015   // Patch the receiver to [[BoundThis]].
2016   __ mov(ebx, FieldOperand(edi, JSBoundFunction::kBoundThisOffset));
2017   __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), ebx);
2018 
2019   // Push the [[BoundArguments]] onto the stack.
2020   Generate_PushBoundArguments(masm);
2021 
2022   // Call the [[BoundTargetFunction]] via the Call builtin.
2023   __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset));
2024   __ mov(ecx, Operand::StaticVariable(ExternalReference(
2025                   Builtins::kCall_ReceiverIsAny, masm->isolate())));
2026   __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
2027   __ jmp(ecx);
2028 }
2029 
2030 
2031 // static
Generate_Call(MacroAssembler * masm,ConvertReceiverMode mode)2032 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
2033   // ----------- S t a t e -------------
2034   //  -- eax : the number of arguments (not including the receiver)
2035   //  -- edi : the target to call (can be any Object).
2036   // -----------------------------------
2037 
2038   Label non_callable, non_function, non_smi;
2039   __ JumpIfSmi(edi, &non_callable);
2040   __ bind(&non_smi);
2041   __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
2042   __ j(equal, masm->isolate()->builtins()->CallFunction(mode),
2043        RelocInfo::CODE_TARGET);
2044   __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE);
2045   __ j(equal, masm->isolate()->builtins()->CallBoundFunction(),
2046        RelocInfo::CODE_TARGET);
2047   __ CmpInstanceType(ecx, JS_PROXY_TYPE);
2048   __ j(not_equal, &non_function);
2049 
2050   // 1. Runtime fallback for Proxy [[Call]].
2051   __ PopReturnAddressTo(ecx);
2052   __ Push(edi);
2053   __ PushReturnAddressFrom(ecx);
2054   // Increase the arguments size to include the pushed function and the
2055   // existing receiver on the stack.
2056   __ add(eax, Immediate(2));
2057   // Tail-call to the runtime.
2058   __ JumpToExternalReference(
2059       ExternalReference(Runtime::kJSProxyCall, masm->isolate()));
2060 
2061   // 2. Call to something else, which might have a [[Call]] internal method (if
2062   // not we raise an exception).
2063   __ bind(&non_function);
2064   // Check if target has a [[Call]] internal method.
2065   __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable);
2066   __ j(zero, &non_callable, Label::kNear);
2067   // Overwrite the original receiver with the (original) target.
2068   __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi);
2069   // Let the "call_as_function_delegate" take care of the rest.
2070   __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, edi);
2071   __ Jump(masm->isolate()->builtins()->CallFunction(
2072               ConvertReceiverMode::kNotNullOrUndefined),
2073           RelocInfo::CODE_TARGET);
2074 
2075   // 3. Call to something that is not callable.
2076   __ bind(&non_callable);
2077   {
2078     FrameScope scope(masm, StackFrame::INTERNAL);
2079     __ Push(edi);
2080     __ CallRuntime(Runtime::kThrowCalledNonCallable);
2081   }
2082 }
2083 
2084 
2085 // static
Generate_ConstructFunction(MacroAssembler * masm)2086 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) {
2087   // ----------- S t a t e -------------
2088   //  -- eax : the number of arguments (not including the receiver)
2089   //  -- edx : the new target (checked to be a constructor)
2090   //  -- edi : the constructor to call (checked to be a JSFunction)
2091   // -----------------------------------
2092   __ AssertFunction(edi);
2093 
2094   // Calling convention for function specific ConstructStubs require
2095   // ebx to contain either an AllocationSite or undefined.
2096   __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex);
2097 
2098   // Tail call to the function-specific construct stub (still in the caller
2099   // context at this point).
2100   __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2101   __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset));
2102   __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
2103   __ jmp(ecx);
2104 }
2105 
2106 
2107 // static
Generate_ConstructBoundFunction(MacroAssembler * masm)2108 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) {
2109   // ----------- S t a t e -------------
2110   //  -- eax : the number of arguments (not including the receiver)
2111   //  -- edx : the new target (checked to be a constructor)
2112   //  -- edi : the constructor to call (checked to be a JSBoundFunction)
2113   // -----------------------------------
2114   __ AssertBoundFunction(edi);
2115 
2116   // Push the [[BoundArguments]] onto the stack.
2117   Generate_PushBoundArguments(masm);
2118 
2119   // Patch new.target to [[BoundTargetFunction]] if new.target equals target.
2120   {
2121     Label done;
2122     __ cmp(edi, edx);
2123     __ j(not_equal, &done, Label::kNear);
2124     __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset));
2125     __ bind(&done);
2126   }
2127 
2128   // Construct the [[BoundTargetFunction]] via the Construct builtin.
2129   __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset));
2130   __ mov(ecx, Operand::StaticVariable(
2131                   ExternalReference(Builtins::kConstruct, masm->isolate())));
2132   __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
2133   __ jmp(ecx);
2134 }
2135 
2136 
2137 // static
Generate_ConstructProxy(MacroAssembler * masm)2138 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) {
2139   // ----------- S t a t e -------------
2140   //  -- eax : the number of arguments (not including the receiver)
2141   //  -- edi : the constructor to call (checked to be a JSProxy)
2142   //  -- edx : the new target (either the same as the constructor or
2143   //           the JSFunction on which new was invoked initially)
2144   // -----------------------------------
2145 
2146   // Call into the Runtime for Proxy [[Construct]].
2147   __ PopReturnAddressTo(ecx);
2148   __ Push(edi);
2149   __ Push(edx);
2150   __ PushReturnAddressFrom(ecx);
2151   // Include the pushed new_target, constructor and the receiver.
2152   __ add(eax, Immediate(3));
2153   // Tail-call to the runtime.
2154   __ JumpToExternalReference(
2155       ExternalReference(Runtime::kJSProxyConstruct, masm->isolate()));
2156 }
2157 
2158 
2159 // static
Generate_Construct(MacroAssembler * masm)2160 void Builtins::Generate_Construct(MacroAssembler* masm) {
2161   // ----------- S t a t e -------------
2162   //  -- eax : the number of arguments (not including the receiver)
2163   //  -- edx : the new target (either the same as the constructor or
2164   //           the JSFunction on which new was invoked initially)
2165   //  -- edi : the constructor to call (can be any Object)
2166   // -----------------------------------
2167 
2168   // Check if target is a Smi.
2169   Label non_constructor;
2170   __ JumpIfSmi(edi, &non_constructor, Label::kNear);
2171 
2172   // Dispatch based on instance type.
2173   __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
2174   __ j(equal, masm->isolate()->builtins()->ConstructFunction(),
2175        RelocInfo::CODE_TARGET);
2176 
2177   // Check if target has a [[Construct]] internal method.
2178   __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor);
2179   __ j(zero, &non_constructor, Label::kNear);
2180 
2181   // Only dispatch to bound functions after checking whether they are
2182   // constructors.
2183   __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE);
2184   __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(),
2185        RelocInfo::CODE_TARGET);
2186 
2187   // Only dispatch to proxies after checking whether they are constructors.
2188   __ CmpInstanceType(ecx, JS_PROXY_TYPE);
2189   __ j(equal, masm->isolate()->builtins()->ConstructProxy(),
2190        RelocInfo::CODE_TARGET);
2191 
2192   // Called Construct on an exotic Object with a [[Construct]] internal method.
2193   {
2194     // Overwrite the original receiver with the (original) target.
2195     __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi);
2196     // Let the "call_as_constructor_delegate" take care of the rest.
2197     __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, edi);
2198     __ Jump(masm->isolate()->builtins()->CallFunction(),
2199             RelocInfo::CODE_TARGET);
2200   }
2201 
2202   // Called Construct on an Object that doesn't have a [[Construct]] internal
2203   // method.
2204   __ bind(&non_constructor);
2205   __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(),
2206           RelocInfo::CODE_TARGET);
2207 }
2208 
2209 
Generate_ArgumentsAdaptorTrampoline(MacroAssembler * masm)2210 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
2211   // ----------- S t a t e -------------
2212   //  -- eax : actual number of arguments
2213   //  -- ebx : expected number of arguments
2214   //  -- edx : new target (passed through to callee)
2215   //  -- edi : function (passed through to callee)
2216   // -----------------------------------
2217 
2218   Label invoke, dont_adapt_arguments, stack_overflow;
2219   __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1);
2220 
2221   Label enough, too_few;
2222   __ cmp(eax, ebx);
2223   __ j(less, &too_few);
2224   __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel);
2225   __ j(equal, &dont_adapt_arguments);
2226 
2227   {  // Enough parameters: Actual >= expected.
2228     __ bind(&enough);
2229     EnterArgumentsAdaptorFrame(masm);
2230     ArgumentsAdaptorStackCheck(masm, &stack_overflow);
2231 
2232     // Copy receiver and all expected arguments.
2233     const int offset = StandardFrameConstants::kCallerSPOffset;
2234     __ lea(edi, Operand(ebp, eax, times_4, offset));
2235     __ mov(eax, -1);  // account for receiver
2236 
2237     Label copy;
2238     __ bind(&copy);
2239     __ inc(eax);
2240     __ push(Operand(edi, 0));
2241     __ sub(edi, Immediate(kPointerSize));
2242     __ cmp(eax, ebx);
2243     __ j(less, &copy);
2244     // eax now contains the expected number of arguments.
2245     __ jmp(&invoke);
2246   }
2247 
2248   {  // Too few parameters: Actual < expected.
2249     __ bind(&too_few);
2250 
2251     // If the function is strong we need to throw an error.
2252     Label no_strong_error;
2253     __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2254     __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrongModeByteOffset),
2255               1 << SharedFunctionInfo::kStrongModeBitWithinByte);
2256     __ j(equal, &no_strong_error, Label::kNear);
2257 
2258     // What we really care about is the required number of arguments.
2259     __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kLengthOffset));
2260     __ SmiUntag(ecx);
2261     __ cmp(eax, ecx);
2262     __ j(greater_equal, &no_strong_error, Label::kNear);
2263 
2264     {
2265       FrameScope frame(masm, StackFrame::MANUAL);
2266       EnterArgumentsAdaptorFrame(masm);
2267       __ CallRuntime(Runtime::kThrowStrongModeTooFewArguments);
2268     }
2269 
2270     __ bind(&no_strong_error);
2271     EnterArgumentsAdaptorFrame(masm);
2272     ArgumentsAdaptorStackCheck(masm, &stack_overflow);
2273 
2274     // Remember expected arguments in ecx.
2275     __ mov(ecx, ebx);
2276 
2277     // Copy receiver and all actual arguments.
2278     const int offset = StandardFrameConstants::kCallerSPOffset;
2279     __ lea(edi, Operand(ebp, eax, times_4, offset));
2280     // ebx = expected - actual.
2281     __ sub(ebx, eax);
2282     // eax = -actual - 1
2283     __ neg(eax);
2284     __ sub(eax, Immediate(1));
2285 
2286     Label copy;
2287     __ bind(&copy);
2288     __ inc(eax);
2289     __ push(Operand(edi, 0));
2290     __ sub(edi, Immediate(kPointerSize));
2291     __ test(eax, eax);
2292     __ j(not_zero, &copy);
2293 
2294     // Fill remaining expected arguments with undefined values.
2295     Label fill;
2296     __ bind(&fill);
2297     __ inc(eax);
2298     __ push(Immediate(masm->isolate()->factory()->undefined_value()));
2299     __ cmp(eax, ebx);
2300     __ j(less, &fill);
2301 
2302     // Restore expected arguments.
2303     __ mov(eax, ecx);
2304   }
2305 
2306   // Call the entry point.
2307   __ bind(&invoke);
2308   // Restore function pointer.
2309   __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
2310   // eax : expected number of arguments
2311   // edx : new target (passed through to callee)
2312   // edi : function (passed through to callee)
2313   __ mov(ecx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
2314   __ call(ecx);
2315 
2316   // Store offset of return address for deoptimizer.
2317   masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
2318 
2319   // Leave frame and return.
2320   LeaveArgumentsAdaptorFrame(masm);
2321   __ ret(0);
2322 
2323   // -------------------------------------------
2324   // Dont adapt arguments.
2325   // -------------------------------------------
2326   __ bind(&dont_adapt_arguments);
2327   __ mov(ecx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
2328   __ jmp(ecx);
2329 
2330   __ bind(&stack_overflow);
2331   {
2332     FrameScope frame(masm, StackFrame::MANUAL);
2333     __ CallRuntime(Runtime::kThrowStackOverflow);
2334     __ int3();
2335   }
2336 }
2337 
2338 
CompatibleReceiverCheck(MacroAssembler * masm,Register receiver,Register function_template_info,Register scratch0,Register scratch1,Label * receiver_check_failed)2339 static void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver,
2340                                     Register function_template_info,
2341                                     Register scratch0, Register scratch1,
2342                                     Label* receiver_check_failed) {
2343   // If there is no signature, return the holder.
2344   __ CompareRoot(FieldOperand(function_template_info,
2345                               FunctionTemplateInfo::kSignatureOffset),
2346                  Heap::kUndefinedValueRootIndex);
2347   Label receiver_check_passed;
2348   __ j(equal, &receiver_check_passed, Label::kNear);
2349 
2350   // Walk the prototype chain.
2351   __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset));
2352   Label prototype_loop_start;
2353   __ bind(&prototype_loop_start);
2354 
2355   // Get the constructor, if any.
2356   __ GetMapConstructor(scratch0, scratch0, scratch1);
2357   __ CmpInstanceType(scratch1, JS_FUNCTION_TYPE);
2358   Label next_prototype;
2359   __ j(not_equal, &next_prototype, Label::kNear);
2360 
2361   // Get the constructor's signature.
2362   __ mov(scratch0,
2363          FieldOperand(scratch0, JSFunction::kSharedFunctionInfoOffset));
2364   __ mov(scratch0,
2365          FieldOperand(scratch0, SharedFunctionInfo::kFunctionDataOffset));
2366 
2367   // Loop through the chain of inheriting function templates.
2368   Label function_template_loop;
2369   __ bind(&function_template_loop);
2370 
2371   // If the signatures match, we have a compatible receiver.
2372   __ cmp(scratch0, FieldOperand(function_template_info,
2373                                 FunctionTemplateInfo::kSignatureOffset));
2374   __ j(equal, &receiver_check_passed, Label::kNear);
2375 
2376   // If the current type is not a FunctionTemplateInfo, load the next prototype
2377   // in the chain.
2378   __ JumpIfSmi(scratch0, &next_prototype, Label::kNear);
2379   __ CmpObjectType(scratch0, FUNCTION_TEMPLATE_INFO_TYPE, scratch1);
2380   __ j(not_equal, &next_prototype, Label::kNear);
2381 
2382   // Otherwise load the parent function template and iterate.
2383   __ mov(scratch0,
2384          FieldOperand(scratch0, FunctionTemplateInfo::kParentTemplateOffset));
2385   __ jmp(&function_template_loop, Label::kNear);
2386 
2387   // Load the next prototype.
2388   __ bind(&next_prototype);
2389   __ mov(receiver, FieldOperand(receiver, HeapObject::kMapOffset));
2390   __ mov(receiver, FieldOperand(receiver, Map::kPrototypeOffset));
2391   // End if the prototype is null or not hidden.
2392   __ CompareRoot(receiver, Heap::kNullValueRootIndex);
2393   __ j(equal, receiver_check_failed);
2394   __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset));
2395   __ test(FieldOperand(scratch0, Map::kBitField3Offset),
2396           Immediate(Map::IsHiddenPrototype::kMask));
2397   __ j(zero, receiver_check_failed);
2398   // Iterate.
2399   __ jmp(&prototype_loop_start, Label::kNear);
2400 
2401   __ bind(&receiver_check_passed);
2402 }
2403 
2404 
Generate_HandleFastApiCall(MacroAssembler * masm)2405 void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) {
2406   // ----------- S t a t e -------------
2407   //  -- eax                : number of arguments (not including the receiver)
2408   //  -- edi                : callee
2409   //  -- esi                : context
2410   //  -- esp[0]             : return address
2411   //  -- esp[4]             : last argument
2412   //  -- ...
2413   //  -- esp[eax * 4]       : first argument
2414   //  -- esp[(eax + 1) * 4] : receiver
2415   // -----------------------------------
2416 
2417   // Load the FunctionTemplateInfo.
2418   __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
2419   __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFunctionDataOffset));
2420 
2421   // Do the compatible receiver check.
2422   Label receiver_check_failed;
2423   __ mov(ecx, Operand(esp, eax, times_pointer_size, kPCOnStackSize));
2424   __ Push(eax);
2425   CompatibleReceiverCheck(masm, ecx, ebx, edx, eax, &receiver_check_failed);
2426   __ Pop(eax);
2427   // Get the callback offset from the FunctionTemplateInfo, and jump to the
2428   // beginning of the code.
2429   __ mov(edx, FieldOperand(ebx, FunctionTemplateInfo::kCallCodeOffset));
2430   __ mov(edx, FieldOperand(edx, CallHandlerInfo::kFastHandlerOffset));
2431   __ add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag));
2432   __ jmp(edx);
2433 
2434   // Compatible receiver check failed: pop return address, arguments and
2435   // receiver and throw an Illegal Invocation exception.
2436   __ bind(&receiver_check_failed);
2437   __ Pop(eax);
2438   __ PopReturnAddressTo(ebx);
2439   __ lea(eax, Operand(eax, times_pointer_size, 1 * kPointerSize));
2440   __ add(esp, eax);
2441   __ PushReturnAddressFrom(ebx);
2442   {
2443     FrameScope scope(masm, StackFrame::INTERNAL);
2444     __ TailCallRuntime(Runtime::kThrowIllegalInvocation);
2445   }
2446 }
2447 
2448 
Generate_OnStackReplacement(MacroAssembler * masm)2449 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
2450   // Lookup the function in the JavaScript frame.
2451   __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
2452   {
2453     FrameScope scope(masm, StackFrame::INTERNAL);
2454     // Pass function as argument.
2455     __ push(eax);
2456     __ CallRuntime(Runtime::kCompileForOnStackReplacement);
2457   }
2458 
2459   Label skip;
2460   // If the code object is null, just return to the unoptimized code.
2461   __ cmp(eax, Immediate(0));
2462   __ j(not_equal, &skip, Label::kNear);
2463   __ ret(0);
2464 
2465   __ bind(&skip);
2466 
2467   // Load deoptimization data from the code object.
2468   __ mov(ebx, Operand(eax, Code::kDeoptimizationDataOffset - kHeapObjectTag));
2469 
2470   // Load the OSR entrypoint offset from the deoptimization data.
2471   __ mov(ebx, Operand(ebx, FixedArray::OffsetOfElementAt(
2472       DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag));
2473   __ SmiUntag(ebx);
2474 
2475   // Compute the target address = code_obj + header_size + osr_offset
2476   __ lea(eax, Operand(eax, ebx, times_1, Code::kHeaderSize - kHeapObjectTag));
2477 
2478   // Overwrite the return address on the stack.
2479   __ mov(Operand(esp, 0), eax);
2480 
2481   // And "return" to the OSR entry point of the function.
2482   __ ret(0);
2483 }
2484 
2485 
Generate_OsrAfterStackCheck(MacroAssembler * masm)2486 void Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
2487   // We check the stack limit as indicator that recompilation might be done.
2488   Label ok;
2489   ExternalReference stack_limit =
2490       ExternalReference::address_of_stack_limit(masm->isolate());
2491   __ cmp(esp, Operand::StaticVariable(stack_limit));
2492   __ j(above_equal, &ok, Label::kNear);
2493   {
2494     FrameScope scope(masm, StackFrame::INTERNAL);
2495     __ CallRuntime(Runtime::kStackGuard);
2496   }
2497   __ jmp(masm->isolate()->builtins()->OnStackReplacement(),
2498          RelocInfo::CODE_TARGET);
2499 
2500   __ bind(&ok);
2501   __ ret(0);
2502 }
2503 
2504 #undef __
2505 }  // namespace internal
2506 }  // namespace v8
2507 
2508 #endif  // V8_TARGET_ARCH_IA32
2509