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