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