deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / src / mips64 / builtins-mips64.cc
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
6
7 #include "src/v8.h"
8
9 #if V8_TARGET_ARCH_MIPS64
10
11 #include "src/codegen.h"
12 #include "src/debug.h"
13 #include "src/deoptimizer.h"
14 #include "src/full-codegen.h"
15 #include "src/runtime/runtime.h"
16
17 namespace v8 {
18 namespace internal {
19
20
21 #define __ ACCESS_MASM(masm)
22
23
24 void Builtins::Generate_Adaptor(MacroAssembler* masm,
25                                 CFunctionId id,
26                                 BuiltinExtraArguments extra_args) {
27   // ----------- S t a t e -------------
28   //  -- a0                 : number of arguments excluding receiver
29   //  -- a1                 : called function (only guaranteed when
30   //  --                      extra_args requires it)
31   //  -- cp                 : context
32   //  -- sp[0]              : last argument
33   //  -- ...
34   //  -- sp[8 * (argc - 1)] : first argument
35   //  -- sp[8 * agrc]       : receiver
36   // -----------------------------------
37
38   // Insert extra arguments.
39   int num_extra_args = 0;
40   if (extra_args == NEEDS_CALLED_FUNCTION) {
41     num_extra_args = 1;
42     __ push(a1);
43   } else {
44     DCHECK(extra_args == NO_EXTRA_ARGUMENTS);
45   }
46
47   // JumpToExternalReference expects a0 to contain the number of arguments
48   // including the receiver and the extra arguments.
49   __ Daddu(a0, a0, num_extra_args + 1);
50   __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
51 }
52
53
54 // Load the built-in InternalArray function from the current context.
55 static void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
56                                               Register result) {
57   // Load the native context.
58
59   __ ld(result,
60         MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
61   __ ld(result,
62         FieldMemOperand(result, GlobalObject::kNativeContextOffset));
63   // Load the InternalArray function from the native context.
64   __ ld(result,
65          MemOperand(result,
66                     Context::SlotOffset(
67                         Context::INTERNAL_ARRAY_FUNCTION_INDEX)));
68 }
69
70
71 // Load the built-in Array function from the current context.
72 static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
73   // Load the native context.
74
75   __ ld(result,
76         MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
77   __ ld(result,
78         FieldMemOperand(result, GlobalObject::kNativeContextOffset));
79   // Load the Array function from the native context.
80   __ ld(result,
81         MemOperand(result,
82                    Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
83 }
84
85
86 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
87   // ----------- S t a t e -------------
88   //  -- a0     : number of arguments
89   //  -- ra     : return address
90   //  -- sp[...]: constructor arguments
91   // -----------------------------------
92   Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
93
94   // Get the InternalArray function.
95   GenerateLoadInternalArrayFunction(masm, a1);
96
97   if (FLAG_debug_code) {
98     // Initial map for the builtin InternalArray functions should be maps.
99     __ ld(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
100     __ SmiTst(a2, a4);
101     __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction,
102               a4, Operand(zero_reg));
103     __ GetObjectType(a2, a3, a4);
104     __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction,
105               a4, Operand(MAP_TYPE));
106   }
107
108   // Run the native code for the InternalArray function called as a normal
109   // function.
110   // Tail call a stub.
111   InternalArrayConstructorStub stub(masm->isolate());
112   __ TailCallStub(&stub);
113 }
114
115
116 void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
117   // ----------- S t a t e -------------
118   //  -- a0     : number of arguments
119   //  -- ra     : return address
120   //  -- sp[...]: constructor arguments
121   // -----------------------------------
122   Label generic_array_code;
123
124   // Get the Array function.
125   GenerateLoadArrayFunction(masm, a1);
126
127   if (FLAG_debug_code) {
128     // Initial map for the builtin Array functions should be maps.
129     __ ld(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
130     __ SmiTst(a2, a4);
131     __ Assert(ne, kUnexpectedInitialMapForArrayFunction1,
132               a4, Operand(zero_reg));
133     __ GetObjectType(a2, a3, a4);
134     __ Assert(eq, kUnexpectedInitialMapForArrayFunction2,
135               a4, Operand(MAP_TYPE));
136   }
137
138   // Run the native code for the Array function called as a normal function.
139   // Tail call a stub.
140   __ mov(a3, a1);
141   __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
142   ArrayConstructorStub stub(masm->isolate());
143   __ TailCallStub(&stub);
144 }
145
146
147 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
148   // ----------- S t a t e -------------
149   //  -- a0                     : number of arguments
150   //  -- a1                     : constructor function
151   //  -- ra                     : return address
152   //  -- sp[(argc - n - 1) * 8] : arg[n] (zero based)
153   //  -- sp[argc * 8]           : receiver
154   // -----------------------------------
155   Counters* counters = masm->isolate()->counters();
156   __ IncrementCounter(counters->string_ctor_calls(), 1, a2, a3);
157
158   Register function = a1;
159   if (FLAG_debug_code) {
160     __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, a2);
161     __ Assert(eq, kUnexpectedStringFunction, function, Operand(a2));
162   }
163
164   // Load the first arguments in a0 and get rid of the rest.
165   Label no_arguments;
166   __ Branch(&no_arguments, eq, a0, Operand(zero_reg));
167   // First args = sp[(argc - 1) * 8].
168   __ Dsubu(a0, a0, Operand(1));
169   __ dsll(a0, a0, kPointerSizeLog2);
170   __ Daddu(sp, a0, sp);
171   __ ld(a0, MemOperand(sp));
172   // sp now point to args[0], drop args[0] + receiver.
173   __ Drop(2);
174
175   Register argument = a2;
176   Label not_cached, argument_is_string;
177   __ LookupNumberStringCache(a0,        // Input.
178                              argument,  // Result.
179                              a3,        // Scratch.
180                              a4,        // Scratch.
181                              a5,        // Scratch.
182                              &not_cached);
183   __ IncrementCounter(counters->string_ctor_cached_number(), 1, a3, a4);
184   __ bind(&argument_is_string);
185
186   // ----------- S t a t e -------------
187   //  -- a2     : argument converted to string
188   //  -- a1     : constructor function
189   //  -- ra     : return address
190   // -----------------------------------
191
192   Label gc_required;
193   __ Allocate(JSValue::kSize,
194               v0,  // Result.
195               a3,  // Scratch.
196               a4,  // Scratch.
197               &gc_required,
198               TAG_OBJECT);
199
200   // Initialising the String Object.
201   Register map = a3;
202   __ LoadGlobalFunctionInitialMap(function, map, a4);
203   if (FLAG_debug_code) {
204     __ lbu(a4, FieldMemOperand(map, Map::kInstanceSizeOffset));
205     __ Assert(eq, kUnexpectedStringWrapperInstanceSize,
206         a4, Operand(JSValue::kSize >> kPointerSizeLog2));
207     __ lbu(a4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
208     __ Assert(eq, kUnexpectedUnusedPropertiesOfStringWrapper,
209         a4, Operand(zero_reg));
210   }
211   __ sd(map, FieldMemOperand(v0, HeapObject::kMapOffset));
212
213   __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex);
214   __ sd(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset));
215   __ sd(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
216
217   __ sd(argument, FieldMemOperand(v0, JSValue::kValueOffset));
218
219   // Ensure the object is fully initialized.
220   STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
221
222   __ Ret();
223
224   // The argument was not found in the number to string cache. Check
225   // if it's a string already before calling the conversion builtin.
226   Label convert_argument;
227   __ bind(&not_cached);
228   __ JumpIfSmi(a0, &convert_argument);
229
230   // Is it a String?
231   __ ld(a2, FieldMemOperand(a0, HeapObject::kMapOffset));
232   __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
233   STATIC_ASSERT(kNotStringTag != 0);
234   __ And(a4, a3, Operand(kIsNotStringMask));
235   __ Branch(&convert_argument, ne, a4, Operand(zero_reg));
236   __ mov(argument, a0);
237   __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, a4);
238   __ Branch(&argument_is_string);
239
240   // Invoke the conversion builtin and put the result into a2.
241   __ bind(&convert_argument);
242   __ push(function);  // Preserve the function.
243   __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, a4);
244   {
245     FrameScope scope(masm, StackFrame::INTERNAL);
246     __ push(a0);
247     __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
248   }
249   __ pop(function);
250   __ mov(argument, v0);
251   __ Branch(&argument_is_string);
252
253   // Load the empty string into a2, remove the receiver from the
254   // stack, and jump back to the case where the argument is a string.
255   __ bind(&no_arguments);
256   __ LoadRoot(argument, Heap::kempty_stringRootIndex);
257   __ Drop(1);
258   __ Branch(&argument_is_string);
259
260   // At this point the argument is already a string. Call runtime to
261   // create a string wrapper.
262   __ bind(&gc_required);
263   __ IncrementCounter(counters->string_ctor_gc_required(), 1, a3, a4);
264   {
265     FrameScope scope(masm, StackFrame::INTERNAL);
266     __ push(argument);
267     __ CallRuntime(Runtime::kNewStringWrapper, 1);
268   }
269   __ Ret();
270 }
271
272
273 static void CallRuntimePassFunction(
274     MacroAssembler* masm, Runtime::FunctionId function_id) {
275   FrameScope scope(masm, StackFrame::INTERNAL);
276   // Push a copy of the function onto the stack.
277   // Push call kind information and function as parameter to the runtime call.
278   __ Push(a1, a1);
279
280   __ CallRuntime(function_id, 1);
281   // Restore call kind information and receiver.
282   __ Pop(a1);
283 }
284
285
286 static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
287   __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
288   __ ld(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset));
289   __ Daddu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag));
290   __ Jump(at);
291 }
292
293
294 static void GenerateTailCallToReturnedCode(MacroAssembler* masm) {
295   __ Daddu(at, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
296   __ Jump(at);
297 }
298
299
300 void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
301   // Checking whether the queued function is ready for install is optional,
302   // since we come across interrupts and stack checks elsewhere.  However,
303   // not checking may delay installing ready functions, and always checking
304   // would be quite expensive.  A good compromise is to first check against
305   // stack limit as a cue for an interrupt signal.
306   Label ok;
307   __ LoadRoot(a4, Heap::kStackLimitRootIndex);
308   __ Branch(&ok, hs, sp, Operand(a4));
309
310   CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode);
311   GenerateTailCallToReturnedCode(masm);
312
313   __ bind(&ok);
314   GenerateTailCallToSharedCode(masm);
315 }
316
317
318 static void Generate_Runtime_NewObject(MacroAssembler* masm,
319                                        bool create_memento,
320                                        Register original_constructor,
321                                        Label* count_incremented,
322                                        Label* allocated) {
323   if (create_memento) {
324     // Get the cell or allocation site.
325     __ ld(a2, MemOperand(sp, 2 * kPointerSize));
326     __ push(a2);
327   }
328
329   __ push(a1);                    // argument for Runtime_NewObject
330   __ push(original_constructor);  // original constructor
331   if (create_memento) {
332     __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
333   } else {
334     __ CallRuntime(Runtime::kNewObject, 2);
335   }
336   __ mov(t0, v0);
337
338   // Runtime_NewObjectWithAllocationSite increments allocation count.
339   // Skip the increment.
340   if (create_memento) {
341     __ jmp(count_incremented);
342   } else {
343     __ jmp(allocated);
344   }
345 }
346
347
348 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
349                                            bool is_api_function,
350                                            bool create_memento) {
351   // ----------- S t a t e -------------
352   //  -- a0     : number of arguments
353   //  -- a1     : constructor function
354   //  -- a2     : allocation site or undefined
355   //  -- a3     : original constructor
356   //  -- ra     : return address
357   //  -- sp[...]: constructor arguments
358   // -----------------------------------
359
360   // Should never create mementos for api functions.
361   DCHECK(!is_api_function || !create_memento);
362
363   Isolate* isolate = masm->isolate();
364
365   // ----------- S t a t e -------------
366   //  -- a0     : number of arguments
367   //  -- a1     : constructor function
368   //  -- ra     : return address
369   //  -- sp[...]: constructor arguments
370   // -----------------------------------
371
372   // Enter a construct frame.
373   {
374     FrameScope scope(masm, StackFrame::CONSTRUCT);
375
376     if (create_memento) {
377       __ AssertUndefinedOrAllocationSite(a2, t0);
378       __ push(a2);
379     }
380
381     // Preserve the two incoming parameters on the stack.
382     // Tag arguments count.
383     __ dsll32(a0, a0, 0);
384     __ MultiPushReversed(a0.bit() | a1.bit());
385
386     Label rt_call, allocated, normal_new, count_incremented;
387     __ Branch(&normal_new, eq, a1, Operand(a3));
388
389     // Original constructor and function are different.
390     Generate_Runtime_NewObject(masm, create_memento, a3, &count_incremented,
391                                &allocated);
392     __ bind(&normal_new);
393
394     // Try to allocate the object without transitioning into C code. If any of
395     // the preconditions is not met, the code bails out to the runtime call.
396     if (FLAG_inline_new) {
397       Label undo_allocation;
398       ExternalReference debug_step_in_fp =
399           ExternalReference::debug_step_in_fp_address(isolate);
400       __ li(a2, Operand(debug_step_in_fp));
401       __ ld(a2, MemOperand(a2));
402       __ Branch(&rt_call, ne, a2, Operand(zero_reg));
403
404       // Load the initial map and verify that it is in fact a map.
405       // a1: constructor function
406       __ ld(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
407       __ JumpIfSmi(a2, &rt_call);
408       __ GetObjectType(a2, a3, t0);
409       __ Branch(&rt_call, ne, t0, Operand(MAP_TYPE));
410
411       // Check that the constructor is not constructing a JSFunction (see
412       // comments in Runtime_NewObject in runtime.cc). In which case the
413       // initial map's instance type would be JS_FUNCTION_TYPE.
414       // a1: constructor function
415       // a2: initial map
416       __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
417       __ Branch(&rt_call, eq, a3, Operand(JS_FUNCTION_TYPE));
418
419       if (!is_api_function) {
420         Label allocate;
421         MemOperand bit_field3 = FieldMemOperand(a2, Map::kBitField3Offset);
422         // Check if slack tracking is enabled.
423         __ lwu(a4, bit_field3);
424         __ DecodeField<Map::Counter>(a6, a4);
425         __ Branch(&allocate, lt, a6,
426                   Operand(static_cast<int64_t>(Map::kSlackTrackingCounterEnd)));
427         // Decrease generous allocation count.
428         __ Dsubu(a4, a4, Operand(1 << Map::Counter::kShift));
429         __ Branch(USE_DELAY_SLOT, &allocate, ne, a6,
430                   Operand(Map::kSlackTrackingCounterEnd));
431         __ sw(a4, bit_field3);  // In delay slot.
432
433         __ Push(a1, a2, a1);  // a1 = Constructor.
434         __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
435
436         __ Pop(a1, a2);
437         // Slack tracking counter is Map::kSlackTrackingCounterEnd after runtime
438         // call.
439         __ li(a6, Map::kSlackTrackingCounterEnd);
440
441         __ bind(&allocate);
442       }
443
444       // Now allocate the JSObject on the heap.
445       // a1: constructor function
446       // a2: initial map
447       __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
448       if (create_memento) {
449         __ Daddu(a3, a3, Operand(AllocationMemento::kSize / kPointerSize));
450       }
451
452       __ Allocate(a3, t0, t1, t2, &rt_call, SIZE_IN_WORDS);
453
454       // Allocated the JSObject, now initialize the fields. Map is set to
455       // initial map and properties and elements are set to empty fixed array.
456       // a1: constructor function
457       // a2: initial map
458       // a3: object size (not including memento if create_memento)
459       // t0: JSObject (not tagged)
460       __ LoadRoot(t2, Heap::kEmptyFixedArrayRootIndex);
461       __ mov(t1, t0);
462       __ sd(a2, MemOperand(t1, JSObject::kMapOffset));
463       __ sd(t2, MemOperand(t1, JSObject::kPropertiesOffset));
464       __ sd(t2, MemOperand(t1, JSObject::kElementsOffset));
465       __ Daddu(t1, t1, Operand(3*kPointerSize));
466       DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
467       DCHECK_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
468       DCHECK_EQ(2 * kPointerSize, JSObject::kElementsOffset);
469
470       // Fill all the in-object properties with appropriate filler.
471       // a1: constructor function
472       // a2: initial map
473       // a3: object size (in words, including memento if create_memento)
474       // t0: JSObject (not tagged)
475       // t1: First in-object property of JSObject (not tagged)
476       // a6: slack tracking counter (non-API function case)
477       DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize);
478
479       // Use t3 to hold undefined, which is used in several places below.
480       __ LoadRoot(t3, Heap::kUndefinedValueRootIndex);
481
482       if (!is_api_function) {
483         Label no_inobject_slack_tracking;
484
485         // Check if slack tracking is enabled.
486         __ Branch(&no_inobject_slack_tracking, lt, a6,
487                   Operand(static_cast<int64_t>(Map::kSlackTrackingCounterEnd)));
488
489         // Allocate object with a slack.
490         __ lwu(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
491         __ Ext(a0, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
492                 kBitsPerByte);
493         __ dsll(at, a0, kPointerSizeLog2);
494         __ daddu(a0, t1, at);
495         // a0: offset of first field after pre-allocated fields
496         if (FLAG_debug_code) {
497           __ dsll(at, a3, kPointerSizeLog2);
498           __ Daddu(t2, t0, Operand(at));   // End of object.
499           __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields,
500               a0, Operand(t2));
501         }
502         __ InitializeFieldsWithFiller(t1, a0, t3);
503         // To allow for truncation.
504         __ LoadRoot(t3, Heap::kOnePointerFillerMapRootIndex);
505         // Fill the remaining fields with one pointer filler map.
506
507         __ bind(&no_inobject_slack_tracking);
508       }
509
510       if (create_memento) {
511         __ Dsubu(a0, a3, Operand(AllocationMemento::kSize / kPointerSize));
512         __ dsll(a0, a0, kPointerSizeLog2);
513         __ Daddu(a0, t0, Operand(a0));  // End of object.
514         __ InitializeFieldsWithFiller(t1, a0, t3);
515
516         // Fill in memento fields.
517         // t1: points to the allocated but uninitialized memento.
518         __ LoadRoot(t3, Heap::kAllocationMementoMapRootIndex);
519         DCHECK_EQ(0 * kPointerSize, AllocationMemento::kMapOffset);
520         __ sd(t3, MemOperand(t1));
521         __ Daddu(t1, t1, kPointerSize);
522         // Load the AllocationSite.
523         __ ld(t3, MemOperand(sp, 2 * kPointerSize));
524         DCHECK_EQ(1 * kPointerSize, AllocationMemento::kAllocationSiteOffset);
525         __ sd(t3, MemOperand(t1));
526         __ Daddu(t1, t1, kPointerSize);
527       } else {
528         __ dsll(at, a3, kPointerSizeLog2);
529         __ Daddu(a0, t0, Operand(at));  // End of object.
530         __ InitializeFieldsWithFiller(t1, a0, t3);
531       }
532
533       // Add the object tag to make the JSObject real, so that we can continue
534       // and jump into the continuation code at any time from now on. Any
535       // failures need to undo the allocation, so that the heap is in a
536       // consistent state and verifiable.
537       __ Daddu(t0, t0, Operand(kHeapObjectTag));
538
539       // Check if a non-empty properties array is needed. Continue with
540       // allocated object if not fall through to runtime call if it is.
541       // a1: constructor function
542       // t0: JSObject
543       // t1: start of next object (not tagged)
544       __ lbu(a3, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
545       // The field instance sizes contains both pre-allocated property fields
546       // and in-object properties.
547       __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
548       __ Ext(t2, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
549              kBitsPerByte);
550       __ Daddu(a3, a3, Operand(t2));
551       __ Ext(t2, a0, Map::kInObjectPropertiesByte * kBitsPerByte,
552               kBitsPerByte);
553       __ dsubu(a3, a3, t2);
554
555       // Done if no extra properties are to be allocated.
556       __ Branch(&allocated, eq, a3, Operand(zero_reg));
557       __ Assert(greater_equal, kPropertyAllocationCountFailed,
558           a3, Operand(zero_reg));
559
560       // Scale the number of elements by pointer size and add the header for
561       // FixedArrays to the start of the next object calculation from above.
562       // a1: constructor
563       // a3: number of elements in properties array
564       // t0: JSObject
565       // t1: start of next object
566       __ Daddu(a0, a3, Operand(FixedArray::kHeaderSize / kPointerSize));
567       __ Allocate(
568           a0,
569           t1,
570           t2,
571           a2,
572           &undo_allocation,
573           static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
574
575       // Initialize the FixedArray.
576       // a1: constructor
577       // a3: number of elements in properties array (untagged)
578       // t0: JSObject
579       // t1: start of next object
580       __ LoadRoot(t2, Heap::kFixedArrayMapRootIndex);
581       __ mov(a2, t1);
582       __ sd(t2, MemOperand(a2, JSObject::kMapOffset));
583       // Tag number of elements.
584       __ dsll32(a0, a3, 0);
585       __ sd(a0, MemOperand(a2, FixedArray::kLengthOffset));
586       __ Daddu(a2, a2, Operand(2 * kPointerSize));
587
588       DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
589       DCHECK_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
590
591       // Initialize the fields to undefined.
592       // a1: constructor
593       // a2: First element of FixedArray (not tagged)
594       // a3: number of elements in properties array
595       // t0: JSObject
596       // t1: FixedArray (not tagged)
597       __ dsll(a7, a3, kPointerSizeLog2);
598       __ daddu(t2, a2, a7);  // End of object.
599       DCHECK_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
600       { Label loop, entry;
601         if (!is_api_function || create_memento) {
602           __ LoadRoot(t3, Heap::kUndefinedValueRootIndex);
603         } else if (FLAG_debug_code) {
604           __ LoadRoot(a6, Heap::kUndefinedValueRootIndex);
605           __ Assert(eq, kUndefinedValueNotLoaded, t3, Operand(a6));
606         }
607         __ jmp(&entry);
608         __ bind(&loop);
609         __ sd(t3, MemOperand(a2));
610         __ daddiu(a2, a2, kPointerSize);
611         __ bind(&entry);
612         __ Branch(&loop, less, a2, Operand(t2));
613       }
614
615       // Store the initialized FixedArray into the properties field of
616       // the JSObject.
617       // a1: constructor function
618       // t0: JSObject
619       // t1: FixedArray (not tagged)
620       __ Daddu(t1, t1, Operand(kHeapObjectTag));  // Add the heap tag.
621       __ sd(t1, FieldMemOperand(t0, JSObject::kPropertiesOffset));
622
623       // Continue with JSObject being successfully allocated.
624       // a1: constructor function
625       // a4: JSObject
626       __ jmp(&allocated);
627
628       // Undo the setting of the new top so that the heap is verifiable. For
629       // example, the map's unused properties potentially do not match the
630       // allocated objects unused properties.
631       // t0: JSObject (previous new top)
632       __ bind(&undo_allocation);
633       __ UndoAllocationInNewSpace(t0, t1);
634     }
635
636     // Allocate the new receiver object using the runtime call.
637     // a1: constructor function
638     __ bind(&rt_call);
639     Generate_Runtime_NewObject(masm, create_memento, a1, &count_incremented,
640                                &allocated);
641
642
643     // Receiver for constructor call allocated.
644     // t0: JSObject
645     __ bind(&allocated);
646
647     if (create_memento) {
648       __ ld(a2, MemOperand(sp, kPointerSize * 2));
649       __ LoadRoot(t1, Heap::kUndefinedValueRootIndex);
650       __ Branch(&count_incremented, eq, a2, Operand(t1));
651       // a2 is an AllocationSite. We are creating a memento from it, so we
652       // need to increment the memento create count.
653       __ ld(a3, FieldMemOperand(a2,
654                                 AllocationSite::kPretenureCreateCountOffset));
655       __ Daddu(a3, a3, Operand(Smi::FromInt(1)));
656       __ sd(a3, FieldMemOperand(a2,
657                                 AllocationSite::kPretenureCreateCountOffset));
658       __ bind(&count_incremented);
659     }
660
661     __ Push(t0, t0);
662
663     // Reload the number of arguments from the stack.
664     // sp[0]: receiver
665     // sp[1]: receiver
666     // sp[2]: constructor function
667     // sp[3]: number of arguments (smi-tagged)
668     __ ld(a1, MemOperand(sp, 2 * kPointerSize));
669     __ ld(a3, MemOperand(sp, 3 * kPointerSize));
670
671     // Set up pointer to last argument.
672     __ Daddu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
673
674     // Set up number of arguments for function call below.
675     __ SmiUntag(a0, a3);
676
677     // Copy arguments and receiver to the expression stack.
678     // a0: number of arguments
679     // a1: constructor function
680     // a2: address of last argument (caller sp)
681     // a3: number of arguments (smi-tagged)
682     // sp[0]: receiver
683     // sp[1]: receiver
684     // sp[2]: constructor function
685     // sp[3]: number of arguments (smi-tagged)
686     Label loop, entry;
687     __ SmiUntag(a3);
688     __ jmp(&entry);
689     __ bind(&loop);
690     __ dsll(a4, a3, kPointerSizeLog2);
691     __ Daddu(a4, a2, Operand(a4));
692     __ ld(a5, MemOperand(a4));
693     __ push(a5);
694     __ bind(&entry);
695     __ Daddu(a3, a3, Operand(-1));
696     __ Branch(&loop, greater_equal, a3, Operand(zero_reg));
697
698     // Call the function.
699     // a0: number of arguments
700     // a1: constructor function
701     if (is_api_function) {
702       __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
703       Handle<Code> code =
704           masm->isolate()->builtins()->HandleApiCallConstruct();
705       __ Call(code, RelocInfo::CODE_TARGET);
706     } else {
707       ParameterCount actual(a0);
708       __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
709     }
710
711     // Store offset of return address for deoptimizer.
712     if (!is_api_function) {
713       masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
714     }
715
716     // Restore context from the frame.
717     __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
718
719     // If the result is an object (in the ECMA sense), we should get rid
720     // of the receiver and use the result; see ECMA-262 section 13.2.2-7
721     // on page 74.
722     Label use_receiver, exit;
723
724     // If the result is a smi, it is *not* an object in the ECMA sense.
725     // v0: result
726     // sp[0]: receiver (newly allocated object)
727     // sp[1]: constructor function
728     // sp[2]: number of arguments (smi-tagged)
729     __ JumpIfSmi(v0, &use_receiver);
730
731     // If the type of the result (stored in its map) is less than
732     // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
733     __ GetObjectType(v0, a1, a3);
734     __ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
735
736     // Throw away the result of the constructor invocation and use the
737     // on-stack receiver as the result.
738     __ bind(&use_receiver);
739     __ ld(v0, MemOperand(sp));
740
741     // Remove receiver from the stack, remove caller arguments, and
742     // return.
743     __ bind(&exit);
744     // v0: result
745     // sp[0]: receiver (newly allocated object)
746     // sp[1]: constructor function
747     // sp[2]: number of arguments (smi-tagged)
748     __ ld(a1, MemOperand(sp, 2 * kPointerSize));
749
750     // Leave construct frame.
751   }
752
753   __ SmiScale(a4, a1, kPointerSizeLog2);
754   __ Daddu(sp, sp, a4);
755   __ Daddu(sp, sp, kPointerSize);
756   __ IncrementCounter(isolate->counters()->constructed_objects(), 1, a1, a2);
757   __ Ret();
758 }
759
760
761 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
762   Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new);
763 }
764
765
766 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
767   Generate_JSConstructStubHelper(masm, true, false);
768 }
769
770
771 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
772   // ----------- S t a t e -------------
773   //  -- a0     : number of arguments
774   //  -- a1     : constructor function
775   //  -- a2     : allocation site or undefined
776   //  -- a3     : original constructor
777   //  -- ra     : return address
778   //  -- sp[...]: constructor arguments
779   // -----------------------------------
780
781   // TODO(dslomov): support pretenuring
782   CHECK(!FLAG_pretenuring_call_new);
783
784   {
785     FrameScope frame_scope(masm, StackFrame::CONSTRUCT);
786
787     __ mov(a4, a0);
788     __ SmiTag(a4);
789     __ push(a4);  // Smi-tagged arguments count.
790
791     // Push new.target.
792     __ push(a3);
793
794     // receiver is the hole.
795     __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
796     __ push(at);
797
798     // Set up pointer to last argument.
799     __ Daddu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
800
801     // Copy arguments and receiver to the expression stack.
802     // a0: number of arguments
803     // a1: constructor function
804     // a2: address of last argument (caller sp)
805     // a4: number of arguments (smi-tagged)
806     // sp[0]: receiver
807     // sp[1]: new.target
808     // sp[2]: number of arguments (smi-tagged)
809     Label loop, entry;
810     __ SmiUntag(a4);
811     __ jmp(&entry);
812     __ bind(&loop);
813     __ dsll(at, a4, kPointerSizeLog2);
814     __ Daddu(at, a2, Operand(at));
815     __ ld(at, MemOperand(at));
816     __ push(at);
817     __ bind(&entry);
818     __ Daddu(a4, a4, Operand(-1));
819     __ Branch(&loop, ge, a4, Operand(zero_reg));
820
821     __ Daddu(a0, a0, Operand(1));
822
823     // Handle step in.
824     Label skip_step_in;
825     ExternalReference debug_step_in_fp =
826         ExternalReference::debug_step_in_fp_address(masm->isolate());
827     __ li(a2, Operand(debug_step_in_fp));
828     __ ld(a2, MemOperand(a2));
829     __ Branch(&skip_step_in, eq, a2, Operand(zero_reg));
830
831     __ Push(a0, a1, a1);
832     __ CallRuntime(Runtime::kHandleStepInForDerivedConstructors, 1);
833     __ Pop(a0, a1);
834
835     __ bind(&skip_step_in);
836
837
838     // Call the function.
839     // a0: number of arguments
840     // a1: constructor function
841     ParameterCount actual(a0);
842     __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
843
844     // Restore context from the frame.
845     // v0: result
846     // sp[0]: number of arguments (smi-tagged)
847     __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
848     __ ld(a1, MemOperand(sp, 0));
849
850     // Leave construct frame.
851   }
852
853   __ SmiScale(at, a1, kPointerSizeLog2);
854   __ Daddu(sp, sp, Operand(at));
855   __ Daddu(sp, sp, Operand(kPointerSize));
856   __ Jump(ra);
857 }
858
859
860 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
861                                              bool is_construct) {
862   // Called from JSEntryStub::GenerateBody
863
864   // ----------- S t a t e -------------
865   //  -- a0: code entry
866   //  -- a1: function
867   //  -- a2: receiver_pointer
868   //  -- a3: argc
869   //  -- s0: argv
870   // -----------------------------------
871   ProfileEntryHookStub::MaybeCallEntryHook(masm);
872   // Clear the context before we push it when entering the JS frame.
873   __ mov(cp, zero_reg);
874
875   // Enter an internal frame.
876   {
877     FrameScope scope(masm, StackFrame::INTERNAL);
878
879     // Set up the context from the function argument.
880     __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
881
882     // Push the function and the receiver onto the stack.
883     __ Push(a1, a2);
884
885     // Copy arguments to the stack in a loop.
886     // a3: argc
887     // s0: argv, i.e. points to first arg
888     Label loop, entry;
889     __ dsll(a4, a3, kPointerSizeLog2);
890     __ daddu(a6, s0, a4);
891     __ b(&entry);
892     __ nop();   // Branch delay slot nop.
893     // a6 points past last arg.
894     __ bind(&loop);
895     __ ld(a4, MemOperand(s0));  // Read next parameter.
896     __ daddiu(s0, s0, kPointerSize);
897     __ ld(a4, MemOperand(a4));  // Dereference handle.
898     __ push(a4);  // Push parameter.
899     __ bind(&entry);
900     __ Branch(&loop, ne, s0, Operand(a6));
901
902     // Initialize all JavaScript callee-saved registers, since they will be seen
903     // by the garbage collector as part of handlers.
904     __ LoadRoot(a4, Heap::kUndefinedValueRootIndex);
905     __ mov(s1, a4);
906     __ mov(s2, a4);
907     __ mov(s3, a4);
908     __ mov(s4, a4);
909     __ mov(s5, a4);
910     // s6 holds the root address. Do not clobber.
911     // s7 is cp. Do not init.
912
913     // Invoke the code and pass argc as a0.
914     __ mov(a0, a3);
915     if (is_construct) {
916       // No type feedback cell is available
917       __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
918       CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
919       __ CallStub(&stub);
920     } else {
921       ParameterCount actual(a0);
922       __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
923     }
924
925     // Leave internal frame.
926   }
927   __ Jump(ra);
928 }
929
930
931 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
932   Generate_JSEntryTrampolineHelper(masm, false);
933 }
934
935
936 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
937   Generate_JSEntryTrampolineHelper(masm, true);
938 }
939
940
941 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
942   CallRuntimePassFunction(masm, Runtime::kCompileLazy);
943   GenerateTailCallToReturnedCode(masm);
944 }
945
946
947 static void CallCompileOptimized(MacroAssembler* masm, bool concurrent) {
948   FrameScope scope(masm, StackFrame::INTERNAL);
949   // Push a copy of the function onto the stack.
950   // Push function as parameter to the runtime call.
951   __ Push(a1, a1);
952   // Whether to compile in a background thread.
953   __ LoadRoot(
954       at, concurrent ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex);
955   __ push(at);
956
957   __ CallRuntime(Runtime::kCompileOptimized, 2);
958   // Restore receiver.
959   __ Pop(a1);
960 }
961
962
963 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
964   CallCompileOptimized(masm, false);
965   GenerateTailCallToReturnedCode(masm);
966 }
967
968
969 void Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) {
970   CallCompileOptimized(masm, true);
971   GenerateTailCallToReturnedCode(masm);
972 }
973
974
975 static void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) {
976   // For now, we are relying on the fact that make_code_young doesn't do any
977   // garbage collection which allows us to save/restore the registers without
978   // worrying about which of them contain pointers. We also don't build an
979   // internal frame to make the code faster, since we shouldn't have to do stack
980   // crawls in MakeCodeYoung. This seems a bit fragile.
981
982   // Set a0 to point to the head of the PlatformCodeAge sequence.
983   __ Dsubu(a0, a0,
984       Operand(kNoCodeAgeSequenceLength - Assembler::kInstrSize));
985
986   // The following registers must be saved and restored when calling through to
987   // the runtime:
988   //   a0 - contains return address (beginning of patch sequence)
989   //   a1 - isolate
990   RegList saved_regs =
991       (a0.bit() | a1.bit() | ra.bit() | fp.bit()) & ~sp.bit();
992   FrameScope scope(masm, StackFrame::MANUAL);
993   __ MultiPush(saved_regs);
994   __ PrepareCallCFunction(2, 0, a2);
995   __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
996   __ CallCFunction(
997       ExternalReference::get_make_code_young_function(masm->isolate()), 2);
998   __ MultiPop(saved_regs);
999   __ Jump(a0);
1000 }
1001
1002 #define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C)                 \
1003 void Builtins::Generate_Make##C##CodeYoungAgainEvenMarking(  \
1004     MacroAssembler* masm) {                                  \
1005   GenerateMakeCodeYoungAgainCommon(masm);                    \
1006 }                                                            \
1007 void Builtins::Generate_Make##C##CodeYoungAgainOddMarking(   \
1008     MacroAssembler* masm) {                                  \
1009   GenerateMakeCodeYoungAgainCommon(masm);                    \
1010 }
1011 CODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR)
1012 #undef DEFINE_CODE_AGE_BUILTIN_GENERATOR
1013
1014
1015 void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
1016   // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact
1017   // that make_code_young doesn't do any garbage collection which allows us to
1018   // save/restore the registers without worrying about which of them contain
1019   // pointers.
1020
1021   // Set a0 to point to the head of the PlatformCodeAge sequence.
1022   __ Dsubu(a0, a0,
1023       Operand(kNoCodeAgeSequenceLength - Assembler::kInstrSize));
1024
1025   // The following registers must be saved and restored when calling through to
1026   // the runtime:
1027   //   a0 - contains return address (beginning of patch sequence)
1028   //   a1 - isolate
1029   RegList saved_regs =
1030       (a0.bit() | a1.bit() | ra.bit() | fp.bit()) & ~sp.bit();
1031   FrameScope scope(masm, StackFrame::MANUAL);
1032   __ MultiPush(saved_regs);
1033   __ PrepareCallCFunction(2, 0, a2);
1034   __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
1035   __ CallCFunction(
1036       ExternalReference::get_mark_code_as_executed_function(masm->isolate()),
1037       2);
1038   __ MultiPop(saved_regs);
1039
1040   // Perform prologue operations usually performed by the young code stub.
1041   __ Push(ra, fp, cp, a1);
1042   __ Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
1043
1044   // Jump to point after the code-age stub.
1045   __ Daddu(a0, a0, Operand((kNoCodeAgeSequenceLength)));
1046   __ Jump(a0);
1047 }
1048
1049
1050 void Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) {
1051   GenerateMakeCodeYoungAgainCommon(masm);
1052 }
1053
1054
1055 static void Generate_NotifyStubFailureHelper(MacroAssembler* masm,
1056                                              SaveFPRegsMode save_doubles) {
1057   {
1058     FrameScope scope(masm, StackFrame::INTERNAL);
1059
1060     // Preserve registers across notification, this is important for compiled
1061     // stubs that tail call the runtime on deopts passing their parameters in
1062     // registers.
1063     __ MultiPush(kJSCallerSaved | kCalleeSaved);
1064     // Pass the function and deoptimization type to the runtime system.
1065     __ CallRuntime(Runtime::kNotifyStubFailure, 0, save_doubles);
1066     __ MultiPop(kJSCallerSaved | kCalleeSaved);
1067   }
1068
1069   __ Daddu(sp, sp, Operand(kPointerSize));  // Ignore state
1070   __ Jump(ra);  // Jump to miss handler
1071 }
1072
1073
1074 void Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) {
1075   Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs);
1076 }
1077
1078
1079 void Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) {
1080   Generate_NotifyStubFailureHelper(masm, kSaveFPRegs);
1081 }
1082
1083
1084 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
1085                                              Deoptimizer::BailoutType type) {
1086   {
1087     FrameScope scope(masm, StackFrame::INTERNAL);
1088     // Pass the function and deoptimization type to the runtime system.
1089     __ li(a0, Operand(Smi::FromInt(static_cast<int>(type))));
1090     __ push(a0);
1091     __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
1092   }
1093
1094   // Get the full codegen state from the stack and untag it -> a6.
1095   __ ld(a6, MemOperand(sp, 0 * kPointerSize));
1096   __ SmiUntag(a6);
1097   // Switch on the state.
1098   Label with_tos_register, unknown_state;
1099   __ Branch(&with_tos_register,
1100             ne, a6, Operand(FullCodeGenerator::NO_REGISTERS));
1101   __ Ret(USE_DELAY_SLOT);
1102   // Safe to fill delay slot Addu will emit one instruction.
1103   __ Daddu(sp, sp, Operand(1 * kPointerSize));  // Remove state.
1104
1105   __ bind(&with_tos_register);
1106   __ ld(v0, MemOperand(sp, 1 * kPointerSize));
1107   __ Branch(&unknown_state, ne, a6, Operand(FullCodeGenerator::TOS_REG));
1108
1109   __ Ret(USE_DELAY_SLOT);
1110   // Safe to fill delay slot Addu will emit one instruction.
1111   __ Daddu(sp, sp, Operand(2 * kPointerSize));  // Remove state.
1112
1113   __ bind(&unknown_state);
1114   __ stop("no cases left");
1115 }
1116
1117
1118 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
1119   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
1120 }
1121
1122
1123 void Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) {
1124   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
1125 }
1126
1127
1128 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
1129   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
1130 }
1131
1132
1133 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1134   // Lookup the function in the JavaScript frame.
1135   __ ld(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1136   {
1137     FrameScope scope(masm, StackFrame::INTERNAL);
1138     // Pass function as argument.
1139     __ push(a0);
1140     __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1141   }
1142
1143   // If the code object is null, just return to the unoptimized code.
1144   __ Ret(eq, v0, Operand(Smi::FromInt(0)));
1145
1146   // Load deoptimization data from the code object.
1147   // <deopt_data> = <code>[#deoptimization_data_offset]
1148   __ ld(a1, MemOperand(v0, Code::kDeoptimizationDataOffset - kHeapObjectTag));
1149
1150   // Load the OSR entrypoint offset from the deoptimization data.
1151   // <osr_offset> = <deopt_data>[#header_size + #osr_pc_offset]
1152   __ ld(a1, MemOperand(a1, FixedArray::OffsetOfElementAt(
1153       DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag));
1154   __ SmiUntag(a1);
1155
1156   // Compute the target address = code_obj + header_size + osr_offset
1157   // <entry_addr> = <code_obj> + #header_size + <osr_offset>
1158   __ daddu(v0, v0, a1);
1159   __ daddiu(ra, v0, Code::kHeaderSize - kHeapObjectTag);
1160
1161   // And "return" to the OSR entry point of the function.
1162   __ Ret();
1163 }
1164
1165
1166 void Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
1167   // We check the stack limit as indicator that recompilation might be done.
1168   Label ok;
1169   __ LoadRoot(at, Heap::kStackLimitRootIndex);
1170   __ Branch(&ok, hs, sp, Operand(at));
1171   {
1172     FrameScope scope(masm, StackFrame::INTERNAL);
1173     __ CallRuntime(Runtime::kStackGuard, 0);
1174   }
1175   __ Jump(masm->isolate()->builtins()->OnStackReplacement(),
1176           RelocInfo::CODE_TARGET);
1177
1178   __ bind(&ok);
1179   __ Ret();
1180 }
1181
1182
1183 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
1184   // 1. Make sure we have at least one argument.
1185   // a0: actual number of arguments
1186   { Label done;
1187     __ Branch(&done, ne, a0, Operand(zero_reg));
1188     __ LoadRoot(a6, Heap::kUndefinedValueRootIndex);
1189     __ push(a6);
1190     __ Daddu(a0, a0, Operand(1));
1191     __ bind(&done);
1192   }
1193
1194   // 2. Get the function to call (passed as receiver) from the stack, check
1195   //    if it is a function.
1196   // a0: actual number of arguments
1197   Label slow, non_function;
1198   __ dsll(at, a0, kPointerSizeLog2);
1199   __ daddu(at, sp, at);
1200   __ ld(a1, MemOperand(at));
1201   __ JumpIfSmi(a1, &non_function);
1202   __ GetObjectType(a1, a2, a2);
1203   __ Branch(&slow, ne, a2, Operand(JS_FUNCTION_TYPE));
1204
1205   // 3a. Patch the first argument if necessary when calling a function.
1206   // a0: actual number of arguments
1207   // a1: function
1208   Label shift_arguments;
1209   __ li(a4, Operand(0, RelocInfo::NONE32));  // Indicate regular JS_FUNCTION.
1210   { Label convert_to_object, use_global_proxy, patch_receiver;
1211     // Change context eagerly in case we need the global receiver.
1212     __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
1213
1214     // Do not transform the receiver for strict mode functions.
1215     __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1216     __ lbu(a3, FieldMemOperand(a2, SharedFunctionInfo::kStrictModeByteOffset));
1217     __ And(a7, a3, Operand(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
1218     __ Branch(&shift_arguments, ne, a7, Operand(zero_reg));
1219
1220     // Do not transform the receiver for native (Compilerhints already in a3).
1221     __ lbu(a3, FieldMemOperand(a2, SharedFunctionInfo::kNativeByteOffset));
1222     __ And(a7, a3, Operand(1 << SharedFunctionInfo::kNativeBitWithinByte));
1223     __ Branch(&shift_arguments, ne, a7, Operand(zero_reg));
1224
1225     // Compute the receiver in sloppy mode.
1226     // Load first argument in a2. a2 = -kPointerSize(sp + n_args << 2).
1227     __ dsll(at, a0, kPointerSizeLog2);
1228     __ daddu(a2, sp, at);
1229     __ ld(a2, MemOperand(a2, -kPointerSize));
1230     // a0: actual number of arguments
1231     // a1: function
1232     // a2: first argument
1233     __ JumpIfSmi(a2, &convert_to_object, a6);
1234
1235     __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
1236     __ Branch(&use_global_proxy, eq, a2, Operand(a3));
1237     __ LoadRoot(a3, Heap::kNullValueRootIndex);
1238     __ Branch(&use_global_proxy, eq, a2, Operand(a3));
1239
1240     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1241     __ GetObjectType(a2, a3, a3);
1242     __ Branch(&shift_arguments, ge, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
1243
1244     __ bind(&convert_to_object);
1245     // Enter an internal frame in order to preserve argument count.
1246     {
1247       FrameScope scope(masm, StackFrame::INTERNAL);
1248       __ SmiTag(a0);
1249       __ Push(a0, a2);
1250       __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1251       __ mov(a2, v0);
1252
1253       __ pop(a0);
1254       __ SmiUntag(a0);
1255       // Leave internal frame.
1256     }
1257     // Restore the function to a1, and the flag to a4.
1258     __ dsll(at, a0, kPointerSizeLog2);
1259     __ daddu(at, sp, at);
1260     __ ld(a1, MemOperand(at));
1261     __ Branch(USE_DELAY_SLOT, &patch_receiver);
1262     __ li(a4, Operand(0, RelocInfo::NONE32));
1263
1264     __ bind(&use_global_proxy);
1265     __ ld(a2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
1266     __ ld(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset));
1267
1268     __ bind(&patch_receiver);
1269     __ dsll(at, a0, kPointerSizeLog2);
1270     __ daddu(a3, sp, at);
1271     __ sd(a2, MemOperand(a3, -kPointerSize));
1272
1273     __ Branch(&shift_arguments);
1274   }
1275
1276   // 3b. Check for function proxy.
1277   __ bind(&slow);
1278   __ li(a4, Operand(1, RelocInfo::NONE32));  // Indicate function proxy.
1279   __ Branch(&shift_arguments, eq, a2, Operand(JS_FUNCTION_PROXY_TYPE));
1280
1281   __ bind(&non_function);
1282   __ li(a4, Operand(2, RelocInfo::NONE32));  // Indicate non-function.
1283
1284   // 3c. Patch the first argument when calling a non-function.  The
1285   //     CALL_NON_FUNCTION builtin expects the non-function callee as
1286   //     receiver, so overwrite the first argument which will ultimately
1287   //     become the receiver.
1288   // a0: actual number of arguments
1289   // a1: function
1290   // a4: call type (0: JS function, 1: function proxy, 2: non-function)
1291   __ dsll(at, a0, kPointerSizeLog2);
1292   __ daddu(a2, sp, at);
1293   __ sd(a1, MemOperand(a2, -kPointerSize));
1294
1295   // 4. Shift arguments and return address one slot down on the stack
1296   //    (overwriting the original receiver).  Adjust argument count to make
1297   //    the original first argument the new receiver.
1298   // a0: actual number of arguments
1299   // a1: function
1300   // a4: call type (0: JS function, 1: function proxy, 2: non-function)
1301   __ bind(&shift_arguments);
1302   { Label loop;
1303     // Calculate the copy start address (destination). Copy end address is sp.
1304     __ dsll(at, a0, kPointerSizeLog2);
1305     __ daddu(a2, sp, at);
1306
1307     __ bind(&loop);
1308     __ ld(at, MemOperand(a2, -kPointerSize));
1309     __ sd(at, MemOperand(a2));
1310     __ Dsubu(a2, a2, Operand(kPointerSize));
1311     __ Branch(&loop, ne, a2, Operand(sp));
1312     // Adjust the actual number of arguments and remove the top element
1313     // (which is a copy of the last argument).
1314     __ Dsubu(a0, a0, Operand(1));
1315     __ Pop();
1316   }
1317
1318   // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
1319   //     or a function proxy via CALL_FUNCTION_PROXY.
1320   // a0: actual number of arguments
1321   // a1: function
1322   // a4: call type (0: JS function, 1: function proxy, 2: non-function)
1323   { Label function, non_proxy;
1324     __ Branch(&function, eq, a4, Operand(zero_reg));
1325     // Expected number of arguments is 0 for CALL_NON_FUNCTION.
1326     __ mov(a2, zero_reg);
1327     __ Branch(&non_proxy, ne, a4, Operand(1));
1328
1329     __ push(a1);  // Re-add proxy object as additional argument.
1330     __ Daddu(a0, a0, Operand(1));
1331     __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY);
1332     __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1333             RelocInfo::CODE_TARGET);
1334
1335     __ bind(&non_proxy);
1336     __ GetBuiltinFunction(a1, Builtins::CALL_NON_FUNCTION);
1337     __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1338             RelocInfo::CODE_TARGET);
1339     __ bind(&function);
1340   }
1341
1342   // 5b. Get the code to call from the function and check that the number of
1343   //     expected arguments matches what we're providing.  If so, jump
1344   //     (tail-call) to the code in register edx without checking arguments.
1345   // a0: actual number of arguments
1346   // a1: function
1347   __ ld(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1348   // The argument count is stored as int32_t on 64-bit platforms.
1349   // TODO(plind): Smi on 32-bit platforms.
1350   __ lw(a2,
1351          FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
1352   // Check formal and actual parameter counts.
1353   __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1354           RelocInfo::CODE_TARGET, ne, a2, Operand(a0));
1355
1356   __ ld(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
1357   ParameterCount expected(0);
1358   __ InvokeCode(a3, expected, expected, JUMP_FUNCTION, NullCallWrapper());
1359 }
1360
1361
1362 static void Generate_CheckStackOverflow(MacroAssembler* masm,
1363                                         const int calleeOffset) {
1364   // Check the stack for overflow. We are not trying to catch
1365   // interruptions (e.g. debug break and preemption) here, so the "real stack
1366   // limit" is checked.
1367   Label okay;
1368   __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
1369   // Make a2 the space we have left. The stack might already be overflowed
1370   // here which will cause a2 to become negative.
1371   __ dsubu(a2, sp, a2);
1372   // Check if the arguments will overflow the stack.
1373   __ SmiScale(a7, v0, kPointerSizeLog2);
1374   __ Branch(&okay, gt, a2, Operand(a7));  // Signed comparison.
1375
1376   // Out of stack space.
1377   __ ld(a1, MemOperand(fp, calleeOffset));
1378   __ Push(a1, v0);
1379   __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1380
1381   __ bind(&okay);
1382 }
1383
1384
1385 static void Generate_PushAppliedArguments(MacroAssembler* masm,
1386                                           const int argumentsOffset,
1387                                           const int indexOffset,
1388                                           const int limitOffset) {
1389   Label entry, loop;
1390   __ ld(a0, MemOperand(fp, indexOffset));
1391   __ Branch(&entry);
1392
1393   // Load the current argument from the arguments array and push it to the
1394   // stack.
1395   // a0: current argument index
1396   __ bind(&loop);
1397   __ ld(a1, MemOperand(fp, argumentsOffset));
1398   __ Push(a1, a0);
1399
1400   // Call the runtime to access the property in the arguments array.
1401   __ CallRuntime(Runtime::kGetProperty, 2);
1402   __ push(v0);
1403
1404   // Use inline caching to access the arguments.
1405   __ ld(a0, MemOperand(fp, indexOffset));
1406   __ Daddu(a0, a0, Operand(Smi::FromInt(1)));
1407   __ sd(a0, MemOperand(fp, indexOffset));
1408
1409   // Test if the copy loop has finished copying all the elements from the
1410   // arguments object.
1411   __ bind(&entry);
1412   __ ld(a1, MemOperand(fp, limitOffset));
1413   __ Branch(&loop, ne, a0, Operand(a1));
1414
1415   // On exit, the pushed arguments count is in a0, untagged
1416   __ SmiUntag(a0);
1417 }
1418
1419
1420 // Used by FunctionApply and ReflectApply
1421 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
1422   const int kFormalParameters = targetIsArgument ? 3 : 2;
1423   const int kStackSize = kFormalParameters + 1;
1424
1425   {
1426     FrameScope frame_scope(masm, StackFrame::INTERNAL);
1427     const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
1428     const int kReceiverOffset = kArgumentsOffset + kPointerSize;
1429     const int kFunctionOffset = kReceiverOffset + kPointerSize;
1430
1431     __ ld(a0, MemOperand(fp, kFunctionOffset));  // Get the function.
1432     __ push(a0);
1433     __ ld(a0, MemOperand(fp, kArgumentsOffset));  // Get the args array.
1434     __ push(a0);
1435
1436     // Returns (in v0) number of arguments to copy to stack as Smi.
1437     if (targetIsArgument) {
1438       __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION);
1439     } else {
1440       __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1441     }
1442
1443     // Returns the result in v0.
1444     Generate_CheckStackOverflow(masm, kFunctionOffset);
1445
1446     // Push current limit and index.
1447     const int kIndexOffset =
1448         StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
1449     const int kLimitOffset =
1450         StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
1451     __ mov(a1, zero_reg);
1452     __ Push(v0, a1);  // Limit and initial index.
1453
1454     // Get the receiver.
1455     __ ld(a0, MemOperand(fp, kReceiverOffset));
1456
1457     // Check that the function is a JS function (otherwise it must be a proxy).
1458     Label push_receiver;
1459     __ ld(a1, MemOperand(fp, kFunctionOffset));
1460     __ GetObjectType(a1, a2, a2);
1461     __ Branch(&push_receiver, ne, a2, Operand(JS_FUNCTION_TYPE));
1462
1463     // Change context eagerly to get the right global object if necessary.
1464     __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
1465     // Load the shared function info while the function is still in a1.
1466     __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1467
1468     // Compute the receiver.
1469     // Do not transform the receiver for strict mode functions.
1470     Label call_to_object, use_global_proxy;
1471     __ lbu(a7, FieldMemOperand(a2, SharedFunctionInfo::kStrictModeByteOffset));
1472     __ And(a7, a7, Operand(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
1473     __ Branch(&push_receiver, ne, a7, Operand(zero_reg));
1474
1475     // Do not transform the receiver for native (Compilerhints already in a2).
1476     __ lbu(a7, FieldMemOperand(a2, SharedFunctionInfo::kNativeByteOffset));
1477     __ And(a7, a7, Operand(1 << SharedFunctionInfo::kNativeBitWithinByte));
1478     __ Branch(&push_receiver, ne, a7, Operand(zero_reg));
1479
1480     // Compute the receiver in sloppy mode.
1481     __ JumpIfSmi(a0, &call_to_object);
1482     __ LoadRoot(a1, Heap::kNullValueRootIndex);
1483     __ Branch(&use_global_proxy, eq, a0, Operand(a1));
1484     __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
1485     __ Branch(&use_global_proxy, eq, a0, Operand(a2));
1486
1487     // Check if the receiver is already a JavaScript object.
1488     // a0: receiver
1489     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1490     __ GetObjectType(a0, a1, a1);
1491     __ Branch(&push_receiver, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
1492
1493     // Convert the receiver to a regular object.
1494     // a0: receiver
1495     __ bind(&call_to_object);
1496     __ push(a0);
1497     __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1498     __ mov(a0, v0);  // Put object in a0 to match other paths to push_receiver.
1499     __ Branch(&push_receiver);
1500
1501     __ bind(&use_global_proxy);
1502     __ ld(a0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
1503     __ ld(a0, FieldMemOperand(a0, GlobalObject::kGlobalProxyOffset));
1504
1505     // Push the receiver.
1506     // a0: receiver
1507     __ bind(&push_receiver);
1508     __ push(a0);
1509
1510     // Copy all arguments from the array to the stack.
1511     Generate_PushAppliedArguments(
1512         masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
1513
1514     // Call the function.
1515     Label call_proxy;
1516     ParameterCount actual(a0);
1517     __ ld(a1, MemOperand(fp, kFunctionOffset));
1518     __ GetObjectType(a1, a2, a2);
1519     __ Branch(&call_proxy, ne, a2, Operand(JS_FUNCTION_TYPE));
1520
1521     __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
1522
1523     frame_scope.GenerateLeaveFrame();
1524     __ Ret(USE_DELAY_SLOT);
1525     __ Daddu(sp, sp, Operand(kStackSize * kPointerSize));  // In delay slot.
1526
1527     // Call the function proxy.
1528     __ bind(&call_proxy);
1529     __ push(a1);  // Add function proxy as last argument.
1530     __ Daddu(a0, a0, Operand(1));
1531     __ li(a2, Operand(0, RelocInfo::NONE32));
1532     __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY);
1533     __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1534             RelocInfo::CODE_TARGET);
1535     // Tear down the internal frame and remove function, receiver and args.
1536   }
1537
1538   __ Ret(USE_DELAY_SLOT);
1539   __ Daddu(sp, sp, Operand(kStackSize * kPointerSize));  // In delay slot.
1540 }
1541
1542
1543 static void Generate_ConstructHelper(MacroAssembler* masm) {
1544   const int kFormalParameters = 3;
1545   const int kStackSize = kFormalParameters + 1;
1546
1547   {
1548     FrameScope frame_scope(masm, StackFrame::INTERNAL);
1549     const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize;
1550     const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
1551     const int kFunctionOffset = kArgumentsOffset + kPointerSize;
1552
1553     // If newTarget is not supplied, set it to constructor
1554     Label validate_arguments;
1555     __ ld(a0, MemOperand(fp, kNewTargetOffset));
1556     __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
1557     __ Branch(&validate_arguments, ne, a0, Operand(at));
1558     __ ld(a0, MemOperand(fp, kFunctionOffset));
1559     __ sd(a0, MemOperand(fp, kNewTargetOffset));
1560
1561     // Validate arguments
1562     __ bind(&validate_arguments);
1563     __ ld(a0, MemOperand(fp, kFunctionOffset));  // get the function
1564     __ push(a0);
1565     __ ld(a0, MemOperand(fp, kArgumentsOffset));  // get the args array
1566     __ push(a0);
1567     __ ld(a0, MemOperand(fp, kNewTargetOffset));  // get the new.target
1568     __ push(a0);
1569     // Returns argument count in v0.
1570     __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION);
1571
1572     // Returns result in v0.
1573     Generate_CheckStackOverflow(masm, kFunctionOffset);
1574
1575     // Push current limit and index.
1576     const int kIndexOffset =
1577         StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
1578     const int kLimitOffset =
1579         StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
1580     __ push(v0);  // limit
1581     __ mov(a1, zero_reg);  // initial index
1582     __ push(a1);
1583     // Push newTarget and callee functions
1584     __ ld(a0, MemOperand(fp, kNewTargetOffset));
1585     __ push(a0);
1586     __ ld(a0, MemOperand(fp, kFunctionOffset));
1587     __ push(a0);
1588
1589     // Copy all arguments from the array to the stack.
1590     Generate_PushAppliedArguments(
1591         masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
1592
1593     // Use undefined feedback vector
1594     __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
1595     __ ld(a1, MemOperand(fp, kFunctionOffset));
1596
1597     // Call the function.
1598     CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL);
1599     __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
1600
1601     __ Drop(1);
1602
1603     // Leave internal frame.
1604   }
1605   __ jr(ra);
1606   __ Daddu(sp, sp, Operand(kStackSize * kPointerSize));  // In delay slot.
1607 }
1608
1609
1610 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
1611   Generate_ApplyHelper(masm, false);
1612 }
1613
1614
1615 void Builtins::Generate_ReflectApply(MacroAssembler* masm) {
1616   Generate_ApplyHelper(masm, true);
1617 }
1618
1619
1620 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) {
1621   Generate_ConstructHelper(masm);
1622 }
1623
1624
1625 static void ArgumentAdaptorStackCheck(MacroAssembler* masm,
1626                                       Label* stack_overflow) {
1627   // ----------- S t a t e -------------
1628   //  -- a0 : actual number of arguments
1629   //  -- a1 : function (passed through to callee)
1630   //  -- a2 : expected number of arguments
1631   // -----------------------------------
1632   // Check the stack for overflow. We are not trying to catch
1633   // interruptions (e.g. debug break and preemption) here, so the "real stack
1634   // limit" is checked.
1635   __ LoadRoot(a5, Heap::kRealStackLimitRootIndex);
1636   // Make a5 the space we have left. The stack might already be overflowed
1637   // here which will cause a5 to become negative.
1638   __ dsubu(a5, sp, a5);
1639   // Check if the arguments will overflow the stack.
1640   __ dsll(at, a2, kPointerSizeLog2);
1641   // Signed comparison.
1642   __ Branch(stack_overflow, le, a5, Operand(at));
1643 }
1644
1645
1646 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1647   // __ sll(a0, a0, kSmiTagSize);
1648   __ dsll32(a0, a0, 0);
1649   __ li(a4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1650   __ MultiPush(a0.bit() | a1.bit() | a4.bit() | fp.bit() | ra.bit());
1651   __ Daddu(fp, sp,
1652       Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize));
1653 }
1654
1655
1656 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1657   // ----------- S t a t e -------------
1658   //  -- v0 : result being passed through
1659   // -----------------------------------
1660   // Get the number of arguments passed (as a smi), tear down the frame and
1661   // then tear down the parameters.
1662   __ ld(a1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp +
1663                              kPointerSize)));
1664   __ mov(sp, fp);
1665   __ MultiPop(fp.bit() | ra.bit());
1666   __ SmiScale(a4, a1, kPointerSizeLog2);
1667   __ Daddu(sp, sp, a4);
1668   // Adjust for the receiver.
1669   __ Daddu(sp, sp, Operand(kPointerSize));
1670 }
1671
1672
1673 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1674   // State setup as expected by MacroAssembler::InvokePrologue.
1675   // ----------- S t a t e -------------
1676   //  -- a0: actual arguments count
1677   //  -- a1: function (passed through to callee)
1678   //  -- a2: expected arguments count
1679   // -----------------------------------
1680
1681   Label stack_overflow;
1682   ArgumentAdaptorStackCheck(masm, &stack_overflow);
1683   Label invoke, dont_adapt_arguments;
1684
1685   Label enough, too_few;
1686   __ ld(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
1687   __ Branch(&dont_adapt_arguments, eq,
1688       a2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
1689   // We use Uless as the number of argument should always be greater than 0.
1690   __ Branch(&too_few, Uless, a0, Operand(a2));
1691
1692   {  // Enough parameters: actual >= expected.
1693     // a0: actual number of arguments as a smi
1694     // a1: function
1695     // a2: expected number of arguments
1696     // a3: code entry to call
1697     __ bind(&enough);
1698     EnterArgumentsAdaptorFrame(masm);
1699
1700     // Calculate copy start address into a0 and copy end address into a2.
1701     __ SmiScale(a0, a0, kPointerSizeLog2);
1702     __ Daddu(a0, fp, a0);
1703     // Adjust for return address and receiver.
1704     __ Daddu(a0, a0, Operand(2 * kPointerSize));
1705     // Compute copy end address.
1706     __ dsll(a2, a2, kPointerSizeLog2);
1707     __ dsubu(a2, a0, a2);
1708
1709     // Copy the arguments (including the receiver) to the new stack frame.
1710     // a0: copy start address
1711     // a1: function
1712     // a2: copy end address
1713     // a3: code entry to call
1714
1715     Label copy;
1716     __ bind(&copy);
1717     __ ld(a4, MemOperand(a0));
1718     __ push(a4);
1719     __ Branch(USE_DELAY_SLOT, &copy, ne, a0, Operand(a2));
1720     __ daddiu(a0, a0, -kPointerSize);  // In delay slot.
1721
1722     __ jmp(&invoke);
1723   }
1724
1725   {  // Too few parameters: Actual < expected.
1726     __ bind(&too_few);
1727     EnterArgumentsAdaptorFrame(masm);
1728
1729     // Calculate copy start address into a0 and copy end address is fp.
1730     // a0: actual number of arguments as a smi
1731     // a1: function
1732     // a2: expected number of arguments
1733     // a3: code entry to call
1734     __ SmiScale(a0, a0, kPointerSizeLog2);
1735     __ Daddu(a0, fp, a0);
1736     // Adjust for return address and receiver.
1737     __ Daddu(a0, a0, Operand(2 * kPointerSize));
1738     // Compute copy end address. Also adjust for return address.
1739     __ Daddu(a7, fp, kPointerSize);
1740
1741     // Copy the arguments (including the receiver) to the new stack frame.
1742     // a0: copy start address
1743     // a1: function
1744     // a2: expected number of arguments
1745     // a3: code entry to call
1746     // a7: copy end address
1747     Label copy;
1748     __ bind(&copy);
1749     __ ld(a4, MemOperand(a0));  // Adjusted above for return addr and receiver.
1750     __ Dsubu(sp, sp, kPointerSize);
1751     __ Dsubu(a0, a0, kPointerSize);
1752     __ Branch(USE_DELAY_SLOT, &copy, ne, a0, Operand(a7));
1753     __ sd(a4, MemOperand(sp));  // In the delay slot.
1754
1755     // Fill the remaining expected arguments with undefined.
1756     // a1: function
1757     // a2: expected number of arguments
1758     // a3: code entry to call
1759     __ LoadRoot(a4, Heap::kUndefinedValueRootIndex);
1760     __ dsll(a6, a2, kPointerSizeLog2);
1761     __ Dsubu(a2, fp, Operand(a6));
1762     // Adjust for frame.
1763     __ Dsubu(a2, a2, Operand(StandardFrameConstants::kFixedFrameSizeFromFp +
1764                             2 * kPointerSize));
1765
1766     Label fill;
1767     __ bind(&fill);
1768     __ Dsubu(sp, sp, kPointerSize);
1769     __ Branch(USE_DELAY_SLOT, &fill, ne, sp, Operand(a2));
1770     __ sd(a4, MemOperand(sp));
1771   }
1772
1773   // Call the entry point.
1774   __ bind(&invoke);
1775
1776   __ Call(a3);
1777
1778   // Store offset of return address for deoptimizer.
1779   masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
1780
1781   // Exit frame and return.
1782   LeaveArgumentsAdaptorFrame(masm);
1783   __ Ret();
1784
1785
1786   // -------------------------------------------
1787   // Don't adapt arguments.
1788   // -------------------------------------------
1789   __ bind(&dont_adapt_arguments);
1790   __ Jump(a3);
1791
1792   __ bind(&stack_overflow);
1793   {
1794     FrameScope frame(masm, StackFrame::MANUAL);
1795     EnterArgumentsAdaptorFrame(masm);
1796     __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1797     __ break_(0xCC);
1798   }
1799 }
1800
1801
1802 #undef __
1803
1804 } }  // namespace v8::internal
1805
1806 #endif  // V8_TARGET_ARCH_MIPS64