builtins-x64.cc revision 589d6979ff2ef66fca2d8fa51404c369ca5e9250
1// Copyright 2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#if defined(V8_TARGET_ARCH_X64)
31
32#include "codegen.h"
33#include "deoptimizer.h"
34#include "full-codegen.h"
35
36namespace v8 {
37namespace internal {
38
39
40#define __ ACCESS_MASM(masm)
41
42
43void Builtins::Generate_Adaptor(MacroAssembler* masm,
44                                CFunctionId id,
45                                BuiltinExtraArguments extra_args) {
46  // ----------- S t a t e -------------
47  //  -- rax                : number of arguments excluding receiver
48  //  -- rdi                : called function (only guaranteed when
49  //                          extra_args requires it)
50  //  -- rsi                : context
51  //  -- rsp[0]             : return address
52  //  -- rsp[8]             : last argument
53  //  -- ...
54  //  -- rsp[8 * argc]      : first argument (argc == rax)
55  //  -- rsp[8 * (argc +1)] : receiver
56  // -----------------------------------
57
58  // Insert extra arguments.
59  int num_extra_args = 0;
60  if (extra_args == NEEDS_CALLED_FUNCTION) {
61    num_extra_args = 1;
62    __ pop(kScratchRegister);  // Save return address.
63    __ push(rdi);
64    __ push(kScratchRegister);  // Restore return address.
65  } else {
66    ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
67  }
68
69  // JumpToExternalReference expects rax to contain the number of arguments
70  // including the receiver and the extra arguments.
71  __ addq(rax, Immediate(num_extra_args + 1));
72  __ JumpToExternalReference(ExternalReference(id, masm->isolate()), 1);
73}
74
75
76void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
77  // ----------- S t a t e -------------
78  //  -- rax: number of arguments
79  //  -- rdi: constructor function
80  // -----------------------------------
81
82  Label non_function_call;
83  // Check that function is not a smi.
84  __ JumpIfSmi(rdi, &non_function_call);
85  // Check that function is a JSFunction.
86  __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
87  __ j(not_equal, &non_function_call);
88
89  // Jump to the function-specific construct stub.
90  __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
91  __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kConstructStubOffset));
92  __ lea(rbx, FieldOperand(rbx, Code::kHeaderSize));
93  __ jmp(rbx);
94
95  // rdi: called object
96  // rax: number of arguments
97  __ bind(&non_function_call);
98  // Set expected number of arguments to zero (not changing rax).
99  __ Set(rbx, 0);
100  __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
101  __ SetCallKind(rcx, CALL_AS_METHOD);
102  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
103          RelocInfo::CODE_TARGET);
104}
105
106
107static void Generate_JSConstructStubHelper(MacroAssembler* masm,
108                                           bool is_api_function,
109                                           bool count_constructions) {
110  // Should never count constructions for api objects.
111  ASSERT(!is_api_function || !count_constructions);
112
113    // Enter a construct frame.
114  __ EnterConstructFrame();
115
116  // Store a smi-tagged arguments count on the stack.
117  __ Integer32ToSmi(rax, rax);
118  __ push(rax);
119
120  // Push the function to invoke on the stack.
121  __ push(rdi);
122
123  // Try to allocate the object without transitioning into C code. If any of the
124  // preconditions is not met, the code bails out to the runtime call.
125  Label rt_call, allocated;
126  if (FLAG_inline_new) {
127    Label undo_allocation;
128
129#ifdef ENABLE_DEBUGGER_SUPPORT
130    ExternalReference debug_step_in_fp =
131        ExternalReference::debug_step_in_fp_address(masm->isolate());
132    __ movq(kScratchRegister, debug_step_in_fp);
133    __ cmpq(Operand(kScratchRegister, 0), Immediate(0));
134    __ j(not_equal, &rt_call);
135#endif
136
137    // Verified that the constructor is a JSFunction.
138    // Load the initial map and verify that it is in fact a map.
139    // rdi: constructor
140    __ movq(rax, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
141    // Will both indicate a NULL and a Smi
142    STATIC_ASSERT(kSmiTag == 0);
143    __ JumpIfSmi(rax, &rt_call);
144    // rdi: constructor
145    // rax: initial map (if proven valid below)
146    __ CmpObjectType(rax, MAP_TYPE, rbx);
147    __ j(not_equal, &rt_call);
148
149    // Check that the constructor is not constructing a JSFunction (see comments
150    // in Runtime_NewObject in runtime.cc). In which case the initial map's
151    // instance type would be JS_FUNCTION_TYPE.
152    // rdi: constructor
153    // rax: initial map
154    __ CmpInstanceType(rax, JS_FUNCTION_TYPE);
155    __ j(equal, &rt_call);
156
157    if (count_constructions) {
158      Label allocate;
159      // Decrease generous allocation count.
160      __ movq(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
161      __ decb(FieldOperand(rcx, SharedFunctionInfo::kConstructionCountOffset));
162      __ j(not_zero, &allocate);
163
164      __ push(rax);
165      __ push(rdi);
166
167      __ push(rdi);  // constructor
168      // The call will replace the stub, so the countdown is only done once.
169      __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
170
171      __ pop(rdi);
172      __ pop(rax);
173
174      __ bind(&allocate);
175    }
176
177    // Now allocate the JSObject on the heap.
178    __ movzxbq(rdi, FieldOperand(rax, Map::kInstanceSizeOffset));
179    __ shl(rdi, Immediate(kPointerSizeLog2));
180    // rdi: size of new object
181    __ AllocateInNewSpace(rdi,
182                          rbx,
183                          rdi,
184                          no_reg,
185                          &rt_call,
186                          NO_ALLOCATION_FLAGS);
187    // Allocated the JSObject, now initialize the fields.
188    // rax: initial map
189    // rbx: JSObject (not HeapObject tagged - the actual address).
190    // rdi: start of next object
191    __ movq(Operand(rbx, JSObject::kMapOffset), rax);
192    __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex);
193    __ movq(Operand(rbx, JSObject::kPropertiesOffset), rcx);
194    __ movq(Operand(rbx, JSObject::kElementsOffset), rcx);
195    // Set extra fields in the newly allocated object.
196    // rax: initial map
197    // rbx: JSObject
198    // rdi: start of next object
199    { Label loop, entry;
200      // To allow for truncation.
201      if (count_constructions) {
202        __ LoadRoot(rdx, Heap::kOnePointerFillerMapRootIndex);
203      } else {
204        __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
205      }
206      __ lea(rcx, Operand(rbx, JSObject::kHeaderSize));
207      __ jmp(&entry);
208      __ bind(&loop);
209      __ movq(Operand(rcx, 0), rdx);
210      __ addq(rcx, Immediate(kPointerSize));
211      __ bind(&entry);
212      __ cmpq(rcx, rdi);
213      __ j(less, &loop);
214    }
215
216    // Add the object tag to make the JSObject real, so that we can continue and
217    // jump into the continuation code at any time from now on. Any failures
218    // need to undo the allocation, so that the heap is in a consistent state
219    // and verifiable.
220    // rax: initial map
221    // rbx: JSObject
222    // rdi: start of next object
223    __ or_(rbx, Immediate(kHeapObjectTag));
224
225    // Check if a non-empty properties array is needed.
226    // Allocate and initialize a FixedArray if it is.
227    // rax: initial map
228    // rbx: JSObject
229    // rdi: start of next object
230    // Calculate total properties described map.
231    __ movzxbq(rdx, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset));
232    __ movzxbq(rcx, FieldOperand(rax, Map::kPreAllocatedPropertyFieldsOffset));
233    __ addq(rdx, rcx);
234    // Calculate unused properties past the end of the in-object properties.
235    __ movzxbq(rcx, FieldOperand(rax, Map::kInObjectPropertiesOffset));
236    __ subq(rdx, rcx);
237    // Done if no extra properties are to be allocated.
238    __ j(zero, &allocated);
239    __ Assert(positive, "Property allocation count failed.");
240
241    // Scale the number of elements by pointer size and add the header for
242    // FixedArrays to the start of the next object calculation from above.
243    // rbx: JSObject
244    // rdi: start of next object (will be start of FixedArray)
245    // rdx: number of elements in properties array
246    __ AllocateInNewSpace(FixedArray::kHeaderSize,
247                          times_pointer_size,
248                          rdx,
249                          rdi,
250                          rax,
251                          no_reg,
252                          &undo_allocation,
253                          RESULT_CONTAINS_TOP);
254
255    // Initialize the FixedArray.
256    // rbx: JSObject
257    // rdi: FixedArray
258    // rdx: number of elements
259    // rax: start of next object
260    __ LoadRoot(rcx, Heap::kFixedArrayMapRootIndex);
261    __ movq(Operand(rdi, HeapObject::kMapOffset), rcx);  // setup the map
262    __ Integer32ToSmi(rdx, rdx);
263    __ movq(Operand(rdi, FixedArray::kLengthOffset), rdx);  // and length
264
265    // Initialize the fields to undefined.
266    // rbx: JSObject
267    // rdi: FixedArray
268    // rax: start of next object
269    // rdx: number of elements
270    { Label loop, entry;
271      __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
272      __ lea(rcx, Operand(rdi, FixedArray::kHeaderSize));
273      __ jmp(&entry);
274      __ bind(&loop);
275      __ movq(Operand(rcx, 0), rdx);
276      __ addq(rcx, Immediate(kPointerSize));
277      __ bind(&entry);
278      __ cmpq(rcx, rax);
279      __ j(below, &loop);
280    }
281
282    // Store the initialized FixedArray into the properties field of
283    // the JSObject
284    // rbx: JSObject
285    // rdi: FixedArray
286    __ or_(rdi, Immediate(kHeapObjectTag));  // add the heap tag
287    __ movq(FieldOperand(rbx, JSObject::kPropertiesOffset), rdi);
288
289
290    // Continue with JSObject being successfully allocated
291    // rbx: JSObject
292    __ jmp(&allocated);
293
294    // Undo the setting of the new top so that the heap is verifiable. For
295    // example, the map's unused properties potentially do not match the
296    // allocated objects unused properties.
297    // rbx: JSObject (previous new top)
298    __ bind(&undo_allocation);
299    __ UndoAllocationInNewSpace(rbx);
300  }
301
302  // Allocate the new receiver object using the runtime call.
303  // rdi: function (constructor)
304  __ bind(&rt_call);
305  // Must restore rdi (constructor) before calling runtime.
306  __ movq(rdi, Operand(rsp, 0));
307  __ push(rdi);
308  __ CallRuntime(Runtime::kNewObject, 1);
309  __ movq(rbx, rax);  // store result in rbx
310
311  // New object allocated.
312  // rbx: newly allocated object
313  __ bind(&allocated);
314  // Retrieve the function from the stack.
315  __ pop(rdi);
316
317  // Retrieve smi-tagged arguments count from the stack.
318  __ movq(rax, Operand(rsp, 0));
319  __ SmiToInteger32(rax, rax);
320
321  // Push the allocated receiver to the stack. We need two copies
322  // because we may have to return the original one and the calling
323  // conventions dictate that the called function pops the receiver.
324  __ push(rbx);
325  __ push(rbx);
326
327  // Setup pointer to last argument.
328  __ lea(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset));
329
330  // Copy arguments and receiver to the expression stack.
331  Label loop, entry;
332  __ movq(rcx, rax);
333  __ jmp(&entry);
334  __ bind(&loop);
335  __ push(Operand(rbx, rcx, times_pointer_size, 0));
336  __ bind(&entry);
337  __ decq(rcx);
338  __ j(greater_equal, &loop);
339
340  // Call the function.
341  if (is_api_function) {
342    __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
343    Handle<Code> code =
344        masm->isolate()->builtins()->HandleApiCallConstruct();
345    ParameterCount expected(0);
346    __ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET,
347                  CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
348  } else {
349    ParameterCount actual(rax);
350    __ InvokeFunction(rdi, actual, CALL_FUNCTION,
351                      NullCallWrapper(), CALL_AS_METHOD);
352  }
353
354  // Restore context from the frame.
355  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
356
357  // If the result is an object (in the ECMA sense), we should get rid
358  // of the receiver and use the result; see ECMA-262 section 13.2.2-7
359  // on page 74.
360  Label use_receiver, exit;
361  // If the result is a smi, it is *not* an object in the ECMA sense.
362  __ JumpIfSmi(rax, &use_receiver);
363
364  // If the type of the result (stored in its map) is less than
365  // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
366  STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
367  __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
368  __ j(above_equal, &exit);
369
370  // Throw away the result of the constructor invocation and use the
371  // on-stack receiver as the result.
372  __ bind(&use_receiver);
373  __ movq(rax, Operand(rsp, 0));
374
375  // Restore the arguments count and leave the construct frame.
376  __ bind(&exit);
377  __ movq(rbx, Operand(rsp, kPointerSize));  // get arguments count
378  __ LeaveConstructFrame();
379
380  // Remove caller arguments from the stack and return.
381  __ pop(rcx);
382  SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2);
383  __ lea(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize));
384  __ push(rcx);
385  Counters* counters = masm->isolate()->counters();
386  __ IncrementCounter(counters->constructed_objects(), 1);
387  __ ret(0);
388}
389
390
391void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
392  Generate_JSConstructStubHelper(masm, false, true);
393}
394
395
396void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
397  Generate_JSConstructStubHelper(masm, false, false);
398}
399
400
401void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
402  Generate_JSConstructStubHelper(masm, true, false);
403}
404
405
406static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
407                                             bool is_construct) {
408  // Expects five C++ function parameters.
409  // - Address entry (ignored)
410  // - JSFunction* function (
411  // - Object* receiver
412  // - int argc
413  // - Object*** argv
414  // (see Handle::Invoke in execution.cc).
415
416  // Platform specific argument handling. After this, the stack contains
417  // an internal frame and the pushed function and receiver, and
418  // register rax and rbx holds the argument count and argument array,
419  // while rdi holds the function pointer and rsi the context.
420#ifdef _WIN64
421  // MSVC parameters in:
422  // rcx : entry (ignored)
423  // rdx : function
424  // r8 : receiver
425  // r9 : argc
426  // [rsp+0x20] : argv
427
428  // Clear the context before we push it when entering the JS frame.
429  __ Set(rsi, 0);
430  __ EnterInternalFrame();
431
432  // Load the function context into rsi.
433  __ movq(rsi, FieldOperand(rdx, JSFunction::kContextOffset));
434
435  // Push the function and the receiver onto the stack.
436  __ push(rdx);
437  __ push(r8);
438
439  // Load the number of arguments and setup pointer to the arguments.
440  __ movq(rax, r9);
441  // Load the previous frame pointer to access C argument on stack
442  __ movq(kScratchRegister, Operand(rbp, 0));
443  __ movq(rbx, Operand(kScratchRegister, EntryFrameConstants::kArgvOffset));
444  // Load the function pointer into rdi.
445  __ movq(rdi, rdx);
446#else  // _WIN64
447  // GCC parameters in:
448  // rdi : entry (ignored)
449  // rsi : function
450  // rdx : receiver
451  // rcx : argc
452  // r8  : argv
453
454  __ movq(rdi, rsi);
455  // rdi : function
456
457  // Clear the context before we push it when entering the JS frame.
458  __ Set(rsi, 0);
459  // Enter an internal frame.
460  __ EnterInternalFrame();
461
462  // Push the function and receiver and setup the context.
463  __ push(rdi);
464  __ push(rdx);
465  __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
466
467  // Load the number of arguments and setup pointer to the arguments.
468  __ movq(rax, rcx);
469  __ movq(rbx, r8);
470#endif  // _WIN64
471
472  // Current stack contents:
473  // [rsp + 2 * kPointerSize ... ]: Internal frame
474  // [rsp + kPointerSize]         : function
475  // [rsp]                        : receiver
476  // Current register contents:
477  // rax : argc
478  // rbx : argv
479  // rsi : context
480  // rdi : function
481
482  // Copy arguments to the stack in a loop.
483  // Register rbx points to array of pointers to handle locations.
484  // Push the values of these handles.
485  Label loop, entry;
486  __ Set(rcx, 0);  // Set loop variable to 0.
487  __ jmp(&entry);
488  __ bind(&loop);
489  __ movq(kScratchRegister, Operand(rbx, rcx, times_pointer_size, 0));
490  __ push(Operand(kScratchRegister, 0));  // dereference handle
491  __ addq(rcx, Immediate(1));
492  __ bind(&entry);
493  __ cmpq(rcx, rax);
494  __ j(not_equal, &loop);
495
496  // Invoke the code.
497  if (is_construct) {
498    // Expects rdi to hold function pointer.
499    __ Call(masm->isolate()->builtins()->JSConstructCall(),
500            RelocInfo::CODE_TARGET);
501  } else {
502    ParameterCount actual(rax);
503    // Function must be in rdi.
504    __ InvokeFunction(rdi, actual, CALL_FUNCTION,
505                      NullCallWrapper(), CALL_AS_METHOD);
506  }
507
508  // Exit the JS frame. Notice that this also removes the empty
509  // context and the function left on the stack by the code
510  // invocation.
511  __ LeaveInternalFrame();
512  // TODO(X64): Is argument correct? Is there a receiver to remove?
513  __ ret(1 * kPointerSize);  // remove receiver
514}
515
516
517void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
518  Generate_JSEntryTrampolineHelper(masm, false);
519}
520
521
522void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
523  Generate_JSEntryTrampolineHelper(masm, true);
524}
525
526
527void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
528  // Enter an internal frame.
529  __ EnterInternalFrame();
530
531  // Push a copy of the function onto the stack.
532  __ push(rdi);
533  // Push call kind information.
534  __ push(rcx);
535
536  __ push(rdi);  // Function is also the parameter to the runtime call.
537  __ CallRuntime(Runtime::kLazyCompile, 1);
538
539  // Restore call kind information.
540  __ pop(rcx);
541  // Restore receiver.
542  __ pop(rdi);
543
544  // Tear down temporary frame.
545  __ LeaveInternalFrame();
546
547  // Do a tail-call of the compiled function.
548  __ lea(rax, FieldOperand(rax, Code::kHeaderSize));
549  __ jmp(rax);
550}
551
552
553void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
554  // Enter an internal frame.
555  __ EnterInternalFrame();
556
557  // Push a copy of the function onto the stack.
558  __ push(rdi);
559  // Push call kind information.
560  __ push(rcx);
561
562  __ push(rdi);  // Function is also the parameter to the runtime call.
563  __ CallRuntime(Runtime::kLazyRecompile, 1);
564
565  // Restore call kind information.
566  __ pop(rcx);
567  // Restore function.
568  __ pop(rdi);
569
570  // Tear down temporary frame.
571  __ LeaveInternalFrame();
572
573  // Do a tail-call of the compiled function.
574  __ lea(rax, FieldOperand(rax, Code::kHeaderSize));
575  __ jmp(rax);
576}
577
578
579static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
580                                             Deoptimizer::BailoutType type) {
581  // Enter an internal frame.
582  __ EnterInternalFrame();
583
584  // Pass the deoptimization type to the runtime system.
585  __ Push(Smi::FromInt(static_cast<int>(type)));
586
587  __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
588  // Tear down temporary frame.
589  __ LeaveInternalFrame();
590
591  // Get the full codegen state from the stack and untag it.
592  __ SmiToInteger32(rcx, Operand(rsp, 1 * kPointerSize));
593
594  // Switch on the state.
595  Label not_no_registers, not_tos_rax;
596  __ cmpq(rcx, Immediate(FullCodeGenerator::NO_REGISTERS));
597  __ j(not_equal, &not_no_registers, Label::kNear);
598  __ ret(1 * kPointerSize);  // Remove state.
599
600  __ bind(&not_no_registers);
601  __ movq(rax, Operand(rsp, 2 * kPointerSize));
602  __ cmpq(rcx, Immediate(FullCodeGenerator::TOS_REG));
603  __ j(not_equal, &not_tos_rax, Label::kNear);
604  __ ret(2 * kPointerSize);  // Remove state, rax.
605
606  __ bind(&not_tos_rax);
607  __ Abort("no cases left");
608}
609
610void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
611  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
612}
613
614
615void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
616  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
617}
618
619
620void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
621  // For now, we are relying on the fact that Runtime::NotifyOSR
622  // doesn't do any garbage collection which allows us to save/restore
623  // the registers without worrying about which of them contain
624  // pointers. This seems a bit fragile.
625  __ Pushad();
626  __ EnterInternalFrame();
627  __ CallRuntime(Runtime::kNotifyOSR, 0);
628  __ LeaveInternalFrame();
629  __ Popad();
630  __ ret(0);
631}
632
633
634void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
635  // Stack Layout:
636  // rsp[0]:   Return address
637  // rsp[1]:   Argument n
638  // rsp[2]:   Argument n-1
639  //  ...
640  // rsp[n]:   Argument 1
641  // rsp[n+1]: Receiver (function to call)
642  //
643  // rax contains the number of arguments, n, not counting the receiver.
644  //
645  // 1. Make sure we have at least one argument.
646  { Label done;
647    __ testq(rax, rax);
648    __ j(not_zero, &done);
649    __ pop(rbx);
650    __ Push(FACTORY->undefined_value());
651    __ push(rbx);
652    __ incq(rax);
653    __ bind(&done);
654  }
655
656  // 2. Get the function to call (passed as receiver) from the stack, check
657  //    if it is a function.
658  Label slow, non_function;
659  // The function to call is at position n+1 on the stack.
660  __ movq(rdi, Operand(rsp, rax, times_pointer_size, 1 * kPointerSize));
661  __ JumpIfSmi(rdi, &non_function);
662  __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
663  __ j(not_equal, &slow);
664
665  // 3a. Patch the first argument if necessary when calling a function.
666  Label shift_arguments;
667  __ Set(rdx, 0);  // indicate regular JS_FUNCTION
668  { Label convert_to_object, use_global_receiver, patch_receiver;
669    // Change context eagerly in case we need the global receiver.
670    __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
671
672    // Do not transform the receiver for strict mode functions.
673    __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
674    __ testb(FieldOperand(rbx, SharedFunctionInfo::kStrictModeByteOffset),
675             Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
676    __ j(not_equal, &shift_arguments);
677
678    // Do not transform the receiver for natives.
679    // SharedFunctionInfo is already loaded into rbx.
680    __ testb(FieldOperand(rbx, SharedFunctionInfo::kNativeByteOffset),
681             Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
682    __ j(not_zero, &shift_arguments);
683
684    // Compute the receiver in non-strict mode.
685    __ movq(rbx, Operand(rsp, rax, times_pointer_size, 0));
686    __ JumpIfSmi(rbx, &convert_to_object, Label::kNear);
687
688    __ CompareRoot(rbx, Heap::kNullValueRootIndex);
689    __ j(equal, &use_global_receiver);
690    __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
691    __ j(equal, &use_global_receiver);
692
693    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
694    __ CmpObjectType(rbx, FIRST_SPEC_OBJECT_TYPE, rcx);
695    __ j(above_equal, &shift_arguments);
696
697    __ bind(&convert_to_object);
698    __ EnterInternalFrame();  // In order to preserve argument count.
699    __ Integer32ToSmi(rax, rax);
700    __ push(rax);
701
702    __ push(rbx);
703    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
704    __ movq(rbx, rax);
705    __ Set(rdx, 0);  // indicate regular JS_FUNCTION
706
707    __ pop(rax);
708    __ SmiToInteger32(rax, rax);
709    __ LeaveInternalFrame();
710    // Restore the function to rdi.
711    __ movq(rdi, Operand(rsp, rax, times_pointer_size, 1 * kPointerSize));
712    __ jmp(&patch_receiver, Label::kNear);
713
714    // Use the global receiver object from the called function as the
715    // receiver.
716    __ bind(&use_global_receiver);
717    const int kGlobalIndex =
718        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
719    __ movq(rbx, FieldOperand(rsi, kGlobalIndex));
720    __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalContextOffset));
721    __ movq(rbx, FieldOperand(rbx, kGlobalIndex));
722    __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
723
724    __ bind(&patch_receiver);
725    __ movq(Operand(rsp, rax, times_pointer_size, 0), rbx);
726
727    __ jmp(&shift_arguments);
728  }
729
730  // 3b. Check for function proxy.
731  __ bind(&slow);
732  __ Set(rdx, 1);  // indicate function proxy
733  __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
734  __ j(equal, &shift_arguments);
735  __ bind(&non_function);
736  __ Set(rdx, 2);  // indicate non-function
737
738  // 3c. Patch the first argument when calling a non-function.  The
739  //     CALL_NON_FUNCTION builtin expects the non-function callee as
740  //     receiver, so overwrite the first argument which will ultimately
741  //     become the receiver.
742  __ movq(Operand(rsp, rax, times_pointer_size, 0), rdi);
743
744  // 4. Shift arguments and return address one slot down on the stack
745  //    (overwriting the original receiver).  Adjust argument count to make
746  //    the original first argument the new receiver.
747  __ bind(&shift_arguments);
748  { Label loop;
749    __ movq(rcx, rax);
750    __ bind(&loop);
751    __ movq(rbx, Operand(rsp, rcx, times_pointer_size, 0));
752    __ movq(Operand(rsp, rcx, times_pointer_size, 1 * kPointerSize), rbx);
753    __ decq(rcx);
754    __ j(not_sign, &loop);  // While non-negative (to copy return address).
755    __ pop(rbx);  // Discard copy of return address.
756    __ decq(rax);  // One fewer argument (first argument is new receiver).
757  }
758
759  // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
760  //     or a function proxy via CALL_FUNCTION_PROXY.
761  { Label function, non_proxy;
762    __ testq(rdx, rdx);
763    __ j(zero, &function);
764    __ Set(rbx, 0);
765    __ SetCallKind(rcx, CALL_AS_METHOD);
766    __ cmpq(rdx, Immediate(1));
767    __ j(not_equal, &non_proxy);
768
769    __ pop(rdx);   // return address
770    __ push(rdi);  // re-add proxy object as additional argument
771    __ push(rdx);
772    __ incq(rax);
773    __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
774    __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
775           RelocInfo::CODE_TARGET);
776
777    __ bind(&non_proxy);
778    __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
779    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
780            RelocInfo::CODE_TARGET);
781    __ bind(&function);
782  }
783
784  // 5b. Get the code to call from the function and check that the number of
785  //     expected arguments matches what we're providing.  If so, jump
786  //     (tail-call) to the code in register edx without checking arguments.
787  __ movq(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
788  __ movsxlq(rbx,
789             FieldOperand(rdx,
790                          SharedFunctionInfo::kFormalParameterCountOffset));
791  __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
792  __ SetCallKind(rcx, CALL_AS_METHOD);
793  __ cmpq(rax, rbx);
794  __ j(not_equal,
795       masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
796       RelocInfo::CODE_TARGET);
797
798  ParameterCount expected(0);
799  __ InvokeCode(rdx, expected, expected, JUMP_FUNCTION,
800                NullCallWrapper(), CALL_AS_METHOD);
801}
802
803
804void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
805  // Stack at entry:
806  //    rsp: return address
807  //  rsp+8: arguments
808  // rsp+16: receiver ("this")
809  // rsp+24: function
810  __ EnterInternalFrame();
811  // Stack frame:
812  //    rbp: Old base pointer
813  // rbp[1]: return address
814  // rbp[2]: function arguments
815  // rbp[3]: receiver
816  // rbp[4]: function
817  static const int kArgumentsOffset = 2 * kPointerSize;
818  static const int kReceiverOffset = 3 * kPointerSize;
819  static const int kFunctionOffset = 4 * kPointerSize;
820
821  __ push(Operand(rbp, kFunctionOffset));
822  __ push(Operand(rbp, kArgumentsOffset));
823  __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
824
825  // Check the stack for overflow. We are not trying to catch
826  // interruptions (e.g. debug break and preemption) here, so the "real stack
827  // limit" is checked.
828  Label okay;
829  __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex);
830  __ movq(rcx, rsp);
831  // Make rcx the space we have left. The stack might already be overflowed
832  // here which will cause rcx to become negative.
833  __ subq(rcx, kScratchRegister);
834  // Make rdx the space we need for the array when it is unrolled onto the
835  // stack.
836  __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rax, kPointerSizeLog2);
837  // Check if the arguments will overflow the stack.
838  __ cmpq(rcx, rdx);
839  __ j(greater, &okay);  // Signed comparison.
840
841  // Out of stack space.
842  __ push(Operand(rbp, kFunctionOffset));
843  __ push(rax);
844  __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
845  __ bind(&okay);
846  // End of stack check.
847
848  // Push current index and limit.
849  const int kLimitOffset =
850      StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
851  const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
852  __ push(rax);  // limit
853  __ push(Immediate(0));  // index
854
855  // Get the receiver.
856  __ movq(rbx, Operand(rbp, kReceiverOffset));
857
858  // Check that the function is a JS function (otherwise it must be a proxy).
859  Label push_receiver;
860  __ movq(rdi, Operand(rbp, kFunctionOffset));
861  __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
862  __ j(not_equal, &push_receiver);
863
864  // Change context eagerly to get the right global object if necessary.
865  __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
866
867  // Do not transform the receiver for strict mode functions.
868  Label call_to_object, use_global_receiver;
869  __ movq(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
870  __ testb(FieldOperand(rdx, SharedFunctionInfo::kStrictModeByteOffset),
871           Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
872  __ j(not_equal, &push_receiver);
873
874  // Do not transform the receiver for natives.
875  __ testb(FieldOperand(rdx, SharedFunctionInfo::kNativeByteOffset),
876           Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
877  __ j(not_equal, &push_receiver);
878
879  // Compute the receiver in non-strict mode.
880  __ JumpIfSmi(rbx, &call_to_object, Label::kNear);
881  __ CompareRoot(rbx, Heap::kNullValueRootIndex);
882  __ j(equal, &use_global_receiver);
883  __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
884  __ j(equal, &use_global_receiver);
885
886  // If given receiver is already a JavaScript object then there's no
887  // reason for converting it.
888  STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
889  __ CmpObjectType(rbx, FIRST_SPEC_OBJECT_TYPE, rcx);
890  __ j(above_equal, &push_receiver);
891
892  // Convert the receiver to an object.
893  __ bind(&call_to_object);
894  __ push(rbx);
895  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
896  __ movq(rbx, rax);
897  __ jmp(&push_receiver, Label::kNear);
898
899  // Use the current global receiver object as the receiver.
900  __ bind(&use_global_receiver);
901  const int kGlobalOffset =
902      Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
903  __ movq(rbx, FieldOperand(rsi, kGlobalOffset));
904  __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalContextOffset));
905  __ movq(rbx, FieldOperand(rbx, kGlobalOffset));
906  __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
907
908  // Push the receiver.
909  __ bind(&push_receiver);
910  __ push(rbx);
911
912  // Copy all arguments from the array to the stack.
913  Label entry, loop;
914  __ movq(rax, Operand(rbp, kIndexOffset));
915  __ jmp(&entry);
916  __ bind(&loop);
917  __ movq(rdx, Operand(rbp, kArgumentsOffset));  // load arguments
918
919  // Use inline caching to speed up access to arguments.
920  Handle<Code> ic =
921      masm->isolate()->builtins()->KeyedLoadIC_Initialize();
922  __ Call(ic, RelocInfo::CODE_TARGET);
923  // It is important that we do not have a test instruction after the
924  // call.  A test instruction after the call is used to indicate that
925  // we have generated an inline version of the keyed load.  In this
926  // case, we know that we are not generating a test instruction next.
927
928  // Push the nth argument.
929  __ push(rax);
930
931  // Update the index on the stack and in register rax.
932  __ movq(rax, Operand(rbp, kIndexOffset));
933  __ SmiAddConstant(rax, rax, Smi::FromInt(1));
934  __ movq(Operand(rbp, kIndexOffset), rax);
935
936  __ bind(&entry);
937  __ cmpq(rax, Operand(rbp, kLimitOffset));
938  __ j(not_equal, &loop);
939
940  // Invoke the function.
941  Label call_proxy;
942  ParameterCount actual(rax);
943  __ SmiToInteger32(rax, rax);
944  __ movq(rdi, Operand(rbp, kFunctionOffset));
945  __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
946  __ j(not_equal, &call_proxy);
947  __ InvokeFunction(rdi, actual, CALL_FUNCTION,
948                    NullCallWrapper(), CALL_AS_METHOD);
949
950  __ LeaveInternalFrame();
951  __ ret(3 * kPointerSize);  // remove this, receiver, and arguments
952
953  // Invoke the function proxy.
954  __ bind(&call_proxy);
955  __ push(rdi);  // add function proxy as last argument
956  __ incq(rax);
957  __ Set(rbx, 0);
958  __ SetCallKind(rcx, CALL_AS_METHOD);
959  __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
960  __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
961          RelocInfo::CODE_TARGET);
962
963  __ LeaveInternalFrame();
964  __ ret(3 * kPointerSize);  // remove this, receiver, and arguments
965}
966
967
968// Number of empty elements to allocate for an empty array.
969static const int kPreallocatedArrayElements = 4;
970
971
972// Allocate an empty JSArray. The allocated array is put into the result
973// register. If the parameter initial_capacity is larger than zero an elements
974// backing store is allocated with this size and filled with the hole values.
975// Otherwise the elements backing store is set to the empty FixedArray.
976static void AllocateEmptyJSArray(MacroAssembler* masm,
977                                 Register array_function,
978                                 Register result,
979                                 Register scratch1,
980                                 Register scratch2,
981                                 Register scratch3,
982                                 int initial_capacity,
983                                 Label* gc_required) {
984  ASSERT(initial_capacity >= 0);
985
986  // Load the initial map from the array function.
987  __ movq(scratch1, FieldOperand(array_function,
988                                 JSFunction::kPrototypeOrInitialMapOffset));
989
990  // Allocate the JSArray object together with space for a fixed array with the
991  // requested elements.
992  int size = JSArray::kSize;
993  if (initial_capacity > 0) {
994    size += FixedArray::SizeFor(initial_capacity);
995  }
996  __ AllocateInNewSpace(size,
997                        result,
998                        scratch2,
999                        scratch3,
1000                        gc_required,
1001                        TAG_OBJECT);
1002
1003  // Allocated the JSArray. Now initialize the fields except for the elements
1004  // array.
1005  // result: JSObject
1006  // scratch1: initial map
1007  // scratch2: start of next object
1008  __ movq(FieldOperand(result, JSObject::kMapOffset), scratch1);
1009  __ Move(FieldOperand(result, JSArray::kPropertiesOffset),
1010          FACTORY->empty_fixed_array());
1011  // Field JSArray::kElementsOffset is initialized later.
1012  __ Move(FieldOperand(result, JSArray::kLengthOffset), Smi::FromInt(0));
1013
1014  // If no storage is requested for the elements array just set the empty
1015  // fixed array.
1016  if (initial_capacity == 0) {
1017    __ Move(FieldOperand(result, JSArray::kElementsOffset),
1018            FACTORY->empty_fixed_array());
1019    return;
1020  }
1021
1022  // Calculate the location of the elements array and set elements array member
1023  // of the JSArray.
1024  // result: JSObject
1025  // scratch2: start of next object
1026  __ lea(scratch1, Operand(result, JSArray::kSize));
1027  __ movq(FieldOperand(result, JSArray::kElementsOffset), scratch1);
1028
1029  // Initialize the FixedArray and fill it with holes. FixedArray length is
1030  // stored as a smi.
1031  // result: JSObject
1032  // scratch1: elements array
1033  // scratch2: start of next object
1034  __ Move(FieldOperand(scratch1, HeapObject::kMapOffset),
1035          FACTORY->fixed_array_map());
1036  __ Move(FieldOperand(scratch1, FixedArray::kLengthOffset),
1037          Smi::FromInt(initial_capacity));
1038
1039  // Fill the FixedArray with the hole value. Inline the code if short.
1040  // Reconsider loop unfolding if kPreallocatedArrayElements gets changed.
1041  static const int kLoopUnfoldLimit = 4;
1042  ASSERT(kPreallocatedArrayElements <= kLoopUnfoldLimit);
1043  __ Move(scratch3, FACTORY->the_hole_value());
1044  if (initial_capacity <= kLoopUnfoldLimit) {
1045    // Use a scratch register here to have only one reloc info when unfolding
1046    // the loop.
1047    for (int i = 0; i < initial_capacity; i++) {
1048      __ movq(FieldOperand(scratch1,
1049                           FixedArray::kHeaderSize + i * kPointerSize),
1050              scratch3);
1051    }
1052  } else {
1053    Label loop, entry;
1054    __ jmp(&entry);
1055    __ bind(&loop);
1056    __ movq(Operand(scratch1, 0), scratch3);
1057    __ addq(scratch1, Immediate(kPointerSize));
1058    __ bind(&entry);
1059    __ cmpq(scratch1, scratch2);
1060    __ j(below, &loop);
1061  }
1062}
1063
1064
1065// Allocate a JSArray with the number of elements stored in a register. The
1066// register array_function holds the built-in Array function and the register
1067// array_size holds the size of the array as a smi. The allocated array is put
1068// into the result register and beginning and end of the FixedArray elements
1069// storage is put into registers elements_array and elements_array_end  (see
1070// below for when that is not the case). If the parameter fill_with_holes is
1071// true the allocated elements backing store is filled with the hole values
1072// otherwise it is left uninitialized. When the backing store is filled the
1073// register elements_array is scratched.
1074static void AllocateJSArray(MacroAssembler* masm,
1075                            Register array_function,  // Array function.
1076                            Register array_size,  // As a smi.
1077                            Register result,
1078                            Register elements_array,
1079                            Register elements_array_end,
1080                            Register scratch,
1081                            bool fill_with_hole,
1082                            Label* gc_required) {
1083  Label not_empty, allocated;
1084
1085  // Load the initial map from the array function.
1086  __ movq(elements_array,
1087          FieldOperand(array_function,
1088                       JSFunction::kPrototypeOrInitialMapOffset));
1089
1090  // Check whether an empty sized array is requested.
1091  __ testq(array_size, array_size);
1092  __ j(not_zero, &not_empty);
1093
1094  // If an empty array is requested allocate a small elements array anyway. This
1095  // keeps the code below free of special casing for the empty array.
1096  int size = JSArray::kSize + FixedArray::SizeFor(kPreallocatedArrayElements);
1097  __ AllocateInNewSpace(size,
1098                        result,
1099                        elements_array_end,
1100                        scratch,
1101                        gc_required,
1102                        TAG_OBJECT);
1103  __ jmp(&allocated);
1104
1105  // Allocate the JSArray object together with space for a FixedArray with the
1106  // requested elements.
1107  __ bind(&not_empty);
1108  SmiIndex index =
1109      masm->SmiToIndex(kScratchRegister, array_size, kPointerSizeLog2);
1110  __ AllocateInNewSpace(JSArray::kSize + FixedArray::kHeaderSize,
1111                        index.scale,
1112                        index.reg,
1113                        result,
1114                        elements_array_end,
1115                        scratch,
1116                        gc_required,
1117                        TAG_OBJECT);
1118
1119  // Allocated the JSArray. Now initialize the fields except for the elements
1120  // array.
1121  // result: JSObject
1122  // elements_array: initial map
1123  // elements_array_end: start of next object
1124  // array_size: size of array (smi)
1125  __ bind(&allocated);
1126  __ movq(FieldOperand(result, JSObject::kMapOffset), elements_array);
1127  __ Move(elements_array, FACTORY->empty_fixed_array());
1128  __ movq(FieldOperand(result, JSArray::kPropertiesOffset), elements_array);
1129  // Field JSArray::kElementsOffset is initialized later.
1130  __ movq(FieldOperand(result, JSArray::kLengthOffset), array_size);
1131
1132  // Calculate the location of the elements array and set elements array member
1133  // of the JSArray.
1134  // result: JSObject
1135  // elements_array_end: start of next object
1136  // array_size: size of array (smi)
1137  __ lea(elements_array, Operand(result, JSArray::kSize));
1138  __ movq(FieldOperand(result, JSArray::kElementsOffset), elements_array);
1139
1140  // Initialize the fixed array. FixedArray length is stored as a smi.
1141  // result: JSObject
1142  // elements_array: elements array
1143  // elements_array_end: start of next object
1144  // array_size: size of array (smi)
1145  __ Move(FieldOperand(elements_array, JSObject::kMapOffset),
1146          FACTORY->fixed_array_map());
1147  Label not_empty_2, fill_array;
1148  __ SmiTest(array_size);
1149  __ j(not_zero, &not_empty_2);
1150  // Length of the FixedArray is the number of pre-allocated elements even
1151  // though the actual JSArray has length 0.
1152  __ Move(FieldOperand(elements_array, FixedArray::kLengthOffset),
1153          Smi::FromInt(kPreallocatedArrayElements));
1154  __ jmp(&fill_array);
1155  __ bind(&not_empty_2);
1156  // For non-empty JSArrays the length of the FixedArray and the JSArray is the
1157  // same.
1158  __ movq(FieldOperand(elements_array, FixedArray::kLengthOffset), array_size);
1159
1160  // Fill the allocated FixedArray with the hole value if requested.
1161  // result: JSObject
1162  // elements_array: elements array
1163  // elements_array_end: start of next object
1164  __ bind(&fill_array);
1165  if (fill_with_hole) {
1166    Label loop, entry;
1167    __ Move(scratch, FACTORY->the_hole_value());
1168    __ lea(elements_array, Operand(elements_array,
1169                                   FixedArray::kHeaderSize - kHeapObjectTag));
1170    __ jmp(&entry);
1171    __ bind(&loop);
1172    __ movq(Operand(elements_array, 0), scratch);
1173    __ addq(elements_array, Immediate(kPointerSize));
1174    __ bind(&entry);
1175    __ cmpq(elements_array, elements_array_end);
1176    __ j(below, &loop);
1177  }
1178}
1179
1180
1181// Create a new array for the built-in Array function. This function allocates
1182// the JSArray object and the FixedArray elements array and initializes these.
1183// If the Array cannot be constructed in native code the runtime is called. This
1184// function assumes the following state:
1185//   rdi: constructor (built-in Array function)
1186//   rax: argc
1187//   rsp[0]: return address
1188//   rsp[8]: last argument
1189// This function is used for both construct and normal calls of Array. The only
1190// difference between handling a construct call and a normal call is that for a
1191// construct call the constructor function in rdi needs to be preserved for
1192// entering the generic code. In both cases argc in rax needs to be preserved.
1193// Both registers are preserved by this code so no need to differentiate between
1194// a construct call and a normal call.
1195static void ArrayNativeCode(MacroAssembler* masm,
1196                            Label *call_generic_code) {
1197  Label argc_one_or_more, argc_two_or_more;
1198
1199  // Check for array construction with zero arguments.
1200  __ testq(rax, rax);
1201  __ j(not_zero, &argc_one_or_more);
1202
1203  // Handle construction of an empty array.
1204  AllocateEmptyJSArray(masm,
1205                       rdi,
1206                       rbx,
1207                       rcx,
1208                       rdx,
1209                       r8,
1210                       kPreallocatedArrayElements,
1211                       call_generic_code);
1212  Counters* counters = masm->isolate()->counters();
1213  __ IncrementCounter(counters->array_function_native(), 1);
1214  __ movq(rax, rbx);
1215  __ ret(kPointerSize);
1216
1217  // Check for one argument. Bail out if argument is not smi or if it is
1218  // negative.
1219  __ bind(&argc_one_or_more);
1220  __ cmpq(rax, Immediate(1));
1221  __ j(not_equal, &argc_two_or_more);
1222  __ movq(rdx, Operand(rsp, kPointerSize));  // Get the argument from the stack.
1223  __ JumpUnlessNonNegativeSmi(rdx, call_generic_code);
1224
1225  // Handle construction of an empty array of a certain size. Bail out if size
1226  // is to large to actually allocate an elements array.
1227  __ SmiCompare(rdx, Smi::FromInt(JSObject::kInitialMaxFastElementArray));
1228  __ j(greater_equal, call_generic_code);
1229
1230  // rax: argc
1231  // rdx: array_size (smi)
1232  // rdi: constructor
1233  // esp[0]: return address
1234  // esp[8]: argument
1235  AllocateJSArray(masm,
1236                  rdi,
1237                  rdx,
1238                  rbx,
1239                  rcx,
1240                  r8,
1241                  r9,
1242                  true,
1243                  call_generic_code);
1244  __ IncrementCounter(counters->array_function_native(), 1);
1245  __ movq(rax, rbx);
1246  __ ret(2 * kPointerSize);
1247
1248  // Handle construction of an array from a list of arguments.
1249  __ bind(&argc_two_or_more);
1250  __ movq(rdx, rax);
1251  __ Integer32ToSmi(rdx, rdx);  // Convet argc to a smi.
1252  // rax: argc
1253  // rdx: array_size (smi)
1254  // rdi: constructor
1255  // esp[0] : return address
1256  // esp[8] : last argument
1257  AllocateJSArray(masm,
1258                  rdi,
1259                  rdx,
1260                  rbx,
1261                  rcx,
1262                  r8,
1263                  r9,
1264                  false,
1265                  call_generic_code);
1266  __ IncrementCounter(counters->array_function_native(), 1);
1267
1268  // rax: argc
1269  // rbx: JSArray
1270  // rcx: elements_array
1271  // r8: elements_array_end (untagged)
1272  // esp[0]: return address
1273  // esp[8]: last argument
1274
1275  // Location of the last argument
1276  __ lea(r9, Operand(rsp, kPointerSize));
1277
1278  // Location of the first array element (Parameter fill_with_holes to
1279  // AllocateJSArrayis false, so the FixedArray is returned in rcx).
1280  __ lea(rdx, Operand(rcx, FixedArray::kHeaderSize - kHeapObjectTag));
1281
1282  // rax: argc
1283  // rbx: JSArray
1284  // rdx: location of the first array element
1285  // r9: location of the last argument
1286  // esp[0]: return address
1287  // esp[8]: last argument
1288  Label loop, entry;
1289  __ movq(rcx, rax);
1290  __ jmp(&entry);
1291  __ bind(&loop);
1292  __ movq(kScratchRegister, Operand(r9, rcx, times_pointer_size, 0));
1293  __ movq(Operand(rdx, 0), kScratchRegister);
1294  __ addq(rdx, Immediate(kPointerSize));
1295  __ bind(&entry);
1296  __ decq(rcx);
1297  __ j(greater_equal, &loop);
1298
1299  // Remove caller arguments from the stack and return.
1300  // rax: argc
1301  // rbx: JSArray
1302  // esp[0]: return address
1303  // esp[8]: last argument
1304  __ pop(rcx);
1305  __ lea(rsp, Operand(rsp, rax, times_pointer_size, 1 * kPointerSize));
1306  __ push(rcx);
1307  __ movq(rax, rbx);
1308  __ ret(0);
1309}
1310
1311
1312void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
1313  // ----------- S t a t e -------------
1314  //  -- rax : argc
1315  //  -- rsp[0] : return address
1316  //  -- rsp[8] : last argument
1317  // -----------------------------------
1318  Label generic_array_code;
1319
1320  // Get the Array function.
1321  __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rdi);
1322
1323  if (FLAG_debug_code) {
1324    // Initial map for the builtin Array functions should be maps.
1325    __ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
1326    // Will both indicate a NULL and a Smi.
1327    STATIC_ASSERT(kSmiTag == 0);
1328    Condition not_smi = NegateCondition(masm->CheckSmi(rbx));
1329    __ Check(not_smi, "Unexpected initial map for Array function");
1330    __ CmpObjectType(rbx, MAP_TYPE, rcx);
1331    __ Check(equal, "Unexpected initial map for Array function");
1332  }
1333
1334  // Run the native code for the Array function called as a normal function.
1335  ArrayNativeCode(masm, &generic_array_code);
1336
1337  // Jump to the generic array code in case the specialized code cannot handle
1338  // the construction.
1339  __ bind(&generic_array_code);
1340  Handle<Code> array_code =
1341      masm->isolate()->builtins()->ArrayCodeGeneric();
1342  __ Jump(array_code, RelocInfo::CODE_TARGET);
1343}
1344
1345
1346void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
1347  // ----------- S t a t e -------------
1348  //  -- rax : argc
1349  //  -- rdi : constructor
1350  //  -- rsp[0] : return address
1351  //  -- rsp[8] : last argument
1352  // -----------------------------------
1353  Label generic_constructor;
1354
1355  if (FLAG_debug_code) {
1356    // The array construct code is only set for the builtin and internal
1357    // Array functions which always have a map.
1358    // Initial map for the builtin Array function should be a map.
1359    __ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
1360    // Will both indicate a NULL and a Smi.
1361    STATIC_ASSERT(kSmiTag == 0);
1362    Condition not_smi = NegateCondition(masm->CheckSmi(rbx));
1363    __ Check(not_smi, "Unexpected initial map for Array function");
1364    __ CmpObjectType(rbx, MAP_TYPE, rcx);
1365    __ Check(equal, "Unexpected initial map for Array function");
1366  }
1367
1368  // Run the native code for the Array function called as constructor.
1369  ArrayNativeCode(masm, &generic_constructor);
1370
1371  // Jump to the generic construct code in case the specialized code cannot
1372  // handle the construction.
1373  __ bind(&generic_constructor);
1374  Handle<Code> generic_construct_stub =
1375      masm->isolate()->builtins()->JSConstructStubGeneric();
1376  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
1377}
1378
1379
1380void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
1381  // TODO(849): implement custom construct stub.
1382  // Generate a copy of the generic stub for now.
1383  Generate_JSConstructStubGeneric(masm);
1384}
1385
1386
1387static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1388  __ push(rbp);
1389  __ movq(rbp, rsp);
1390
1391  // Store the arguments adaptor context sentinel.
1392  __ Push(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
1393
1394  // Push the function on the stack.
1395  __ push(rdi);
1396
1397  // Preserve the number of arguments on the stack. Must preserve rax,
1398  // rbx and rcx because these registers are used when copying the
1399  // arguments and the receiver.
1400  __ Integer32ToSmi(r8, rax);
1401  __ push(r8);
1402}
1403
1404
1405static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1406  // Retrieve the number of arguments from the stack. Number is a Smi.
1407  __ movq(rbx, Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset));
1408
1409  // Leave the frame.
1410  __ movq(rsp, rbp);
1411  __ pop(rbp);
1412
1413  // Remove caller arguments from the stack.
1414  __ pop(rcx);
1415  SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2);
1416  __ lea(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize));
1417  __ push(rcx);
1418}
1419
1420
1421void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1422  // ----------- S t a t e -------------
1423  //  -- rax : actual number of arguments
1424  //  -- rbx : expected number of arguments
1425  //  -- rcx : call kind information
1426  //  -- rdx : code entry to call
1427  // -----------------------------------
1428
1429  Label invoke, dont_adapt_arguments;
1430  Counters* counters = masm->isolate()->counters();
1431  __ IncrementCounter(counters->arguments_adaptors(), 1);
1432
1433  Label enough, too_few;
1434  __ cmpq(rax, rbx);
1435  __ j(less, &too_few);
1436  __ cmpq(rbx, Immediate(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
1437  __ j(equal, &dont_adapt_arguments);
1438
1439  {  // Enough parameters: Actual >= expected.
1440    __ bind(&enough);
1441    EnterArgumentsAdaptorFrame(masm);
1442
1443    // Copy receiver and all expected arguments.
1444    const int offset = StandardFrameConstants::kCallerSPOffset;
1445    __ lea(rax, Operand(rbp, rax, times_pointer_size, offset));
1446    __ Set(r8, -1);  // account for receiver
1447
1448    Label copy;
1449    __ bind(&copy);
1450    __ incq(r8);
1451    __ push(Operand(rax, 0));
1452    __ subq(rax, Immediate(kPointerSize));
1453    __ cmpq(r8, rbx);
1454    __ j(less, &copy);
1455    __ jmp(&invoke);
1456  }
1457
1458  {  // Too few parameters: Actual < expected.
1459    __ bind(&too_few);
1460    EnterArgumentsAdaptorFrame(masm);
1461
1462    // Copy receiver and all actual arguments.
1463    const int offset = StandardFrameConstants::kCallerSPOffset;
1464    __ lea(rdi, Operand(rbp, rax, times_pointer_size, offset));
1465    __ Set(r8, -1);  // account for receiver
1466
1467    Label copy;
1468    __ bind(&copy);
1469    __ incq(r8);
1470    __ push(Operand(rdi, 0));
1471    __ subq(rdi, Immediate(kPointerSize));
1472    __ cmpq(r8, rax);
1473    __ j(less, &copy);
1474
1475    // Fill remaining expected arguments with undefined values.
1476    Label fill;
1477    __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
1478    __ bind(&fill);
1479    __ incq(r8);
1480    __ push(kScratchRegister);
1481    __ cmpq(r8, rbx);
1482    __ j(less, &fill);
1483
1484    // Restore function pointer.
1485    __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1486  }
1487
1488  // Call the entry point.
1489  __ bind(&invoke);
1490  __ call(rdx);
1491
1492  // Leave frame and return.
1493  LeaveArgumentsAdaptorFrame(masm);
1494  __ ret(0);
1495
1496  // -------------------------------------------
1497  // Dont adapt arguments.
1498  // -------------------------------------------
1499  __ bind(&dont_adapt_arguments);
1500  __ jmp(rdx);
1501}
1502
1503
1504void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1505  // Get the loop depth of the stack guard check. This is recorded in
1506  // a test(rax, depth) instruction right after the call.
1507  Label stack_check;
1508  __ movq(rbx, Operand(rsp, 0));  // return address
1509  __ movzxbq(rbx, Operand(rbx, 1));  // depth
1510
1511  // Get the loop nesting level at which we allow OSR from the
1512  // unoptimized code and check if we want to do OSR yet. If not we
1513  // should perform a stack guard check so we can get interrupts while
1514  // waiting for on-stack replacement.
1515  __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1516  __ movq(rcx, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
1517  __ movq(rcx, FieldOperand(rcx, SharedFunctionInfo::kCodeOffset));
1518  __ cmpb(rbx, FieldOperand(rcx, Code::kAllowOSRAtLoopNestingLevelOffset));
1519  __ j(greater, &stack_check);
1520
1521  // Pass the function to optimize as the argument to the on-stack
1522  // replacement runtime function.
1523  __ EnterInternalFrame();
1524  __ push(rax);
1525  __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1526  __ LeaveInternalFrame();
1527
1528  // If the result was -1 it means that we couldn't optimize the
1529  // function. Just return and continue in the unoptimized version.
1530  Label skip;
1531  __ SmiCompare(rax, Smi::FromInt(-1));
1532  __ j(not_equal, &skip, Label::kNear);
1533  __ ret(0);
1534
1535  // If we decide not to perform on-stack replacement we perform a
1536  // stack guard check to enable interrupts.
1537  __ bind(&stack_check);
1538  Label ok;
1539  __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
1540  __ j(above_equal, &ok, Label::kNear);
1541
1542  StackCheckStub stub;
1543  __ TailCallStub(&stub);
1544  __ Abort("Unreachable code: returned from tail call.");
1545  __ bind(&ok);
1546  __ ret(0);
1547
1548  __ bind(&skip);
1549  // Untag the AST id and push it on the stack.
1550  __ SmiToInteger32(rax, rax);
1551  __ push(rax);
1552
1553  // Generate the code for doing the frame-to-frame translation using
1554  // the deoptimizer infrastructure.
1555  Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR);
1556  generator.Generate();
1557}
1558
1559
1560#undef __
1561
1562} }  // namespace v8::internal
1563
1564#endif  // V8_TARGET_ARCH_X64
1565