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