~yolanda.robla/ubuntu/trusty/nodejs/add_distribution

« back to all changes in this revision

Viewing changes to deps/v8/src/mips/builtins-mips.cc

  • Committer: Package Import Robot
  • Author(s): Jérémy Lal
  • Date: 2013-08-14 00:16:46 UTC
  • mfrom: (7.1.40 sid)
  • Revision ID: package-import@ubuntu.com-20130814001646-bzlysfh8sd6mukbo
Tags: 0.10.15~dfsg1-4
* Update 2005 patch, adding a handful of tests that can fail on
  slow platforms.
* Add 1004 patch to fix test failures when writing NaN to buffer
  on mipsel.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright 2011 the V8 project authors. All rights reserved.
 
1
// Copyright 2012 the V8 project authors. All rights reserved.
2
2
// Redistribution and use in source and binary forms, with or without
3
3
// modification, are permitted provided that the following conditions are
4
4
// met:
67
67
    ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
68
68
  }
69
69
 
70
 
  // JumpToExternalReference expects a0 to contain the number of arguments
 
70
  // JumpToExternalReference expects s0 to contain the number of arguments
71
71
  // including the receiver and the extra arguments.
72
 
  __ Addu(a0, a0, Operand(num_extra_args + 1));
 
72
  __ Addu(s0, a0, num_extra_args + 1);
 
73
  __ sll(s1, s0, kPointerSizeLog2);
 
74
  __ Subu(s1, s1, kPointerSize);
73
75
  __ JumpToExternalReference(ExternalReference(id, masm->isolate()));
74
76
}
75
77
 
76
78
 
 
79
// Load the built-in InternalArray function from the current context.
 
80
static void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
 
81
                                              Register result) {
 
82
  // Load the native context.
 
83
 
 
84
  __ lw(result,
 
85
        MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
 
86
  __ lw(result,
 
87
        FieldMemOperand(result, GlobalObject::kNativeContextOffset));
 
88
  // Load the InternalArray function from the native context.
 
89
  __ lw(result,
 
90
         MemOperand(result,
 
91
                    Context::SlotOffset(
 
92
                        Context::INTERNAL_ARRAY_FUNCTION_INDEX)));
 
93
}
 
94
 
 
95
 
77
96
// Load the built-in Array function from the current context.
78
97
static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
79
 
  // Load the global context.
 
98
  // Load the native context.
80
99
 
81
 
  __ lw(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
82
 
  __ lw(result,
83
 
         FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
84
 
  // Load the Array function from the global context.
85
 
  __ lw(result,
86
 
         MemOperand(result,
87
 
                    Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
 
100
  __ lw(result,
 
101
        MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
 
102
  __ lw(result,
 
103
        FieldMemOperand(result, GlobalObject::kNativeContextOffset));
 
104
  // Load the Array function from the native context.
 
105
  __ lw(result,
 
106
        MemOperand(result,
 
107
                   Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
88
108
}
89
109
 
90
110
 
91
 
// This constant has the same value as JSArray::kPreallocatedArrayElements and
92
 
// if JSArray::kPreallocatedArrayElements is changed handling of loop unfolding
93
 
// below should be reconsidered.
94
 
static const int kLoopUnfoldLimit = 4;
95
 
 
96
 
 
97
111
// Allocate an empty JSArray. The allocated array is put into the result
98
112
// register. An elements backing store is allocated with size initial_capacity
99
113
// and filled with the hole values.
103
117
                                 Register scratch1,
104
118
                                 Register scratch2,
105
119
                                 Register scratch3,
106
 
                                 int initial_capacity,
107
120
                                 Label* gc_required) {
108
 
  ASSERT(initial_capacity > 0);
109
 
  // Load the initial map from the array function.
110
 
  __ lw(scratch1, FieldMemOperand(array_function,
111
 
                                  JSFunction::kPrototypeOrInitialMapOffset));
 
121
  const int initial_capacity = JSArray::kPreallocatedArrayElements;
 
122
  STATIC_ASSERT(initial_capacity >= 0);
 
123
  __ LoadInitialArrayMap(array_function, scratch2, scratch1, false);
112
124
 
113
125
  // Allocate the JSArray object together with space for a fixed array with the
114
126
  // requested elements.
115
 
  int size = JSArray::kSize + FixedArray::SizeFor(initial_capacity);
 
127
  int size = JSArray::kSize;
 
128
  if (initial_capacity > 0) {
 
129
    size += FixedArray::SizeFor(initial_capacity);
 
130
  }
116
131
  __ AllocateInNewSpace(size,
117
132
                        result,
118
133
                        scratch2,
131
146
  __ mov(scratch3,  zero_reg);
132
147
  __ sw(scratch3, FieldMemOperand(result, JSArray::kLengthOffset));
133
148
 
 
149
  if (initial_capacity == 0) {
 
150
    __ sw(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
 
151
    return;
 
152
  }
 
153
 
134
154
  // Calculate the location of the elements array and set elements array member
135
155
  // of the JSArray.
136
156
  // result: JSObject
147
167
  // scratch1: elements array (untagged)
148
168
  // scratch2: start of next object
149
169
  __ LoadRoot(scratch3, Heap::kFixedArrayMapRootIndex);
150
 
  ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset);
 
170
  STATIC_ASSERT(0 * kPointerSize == FixedArray::kMapOffset);
151
171
  __ sw(scratch3, MemOperand(scratch1));
152
172
  __ Addu(scratch1, scratch1, kPointerSize);
153
173
  __ li(scratch3,  Operand(Smi::FromInt(initial_capacity)));
154
 
  ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
 
174
  STATIC_ASSERT(1 * kPointerSize == FixedArray::kLengthOffset);
155
175
  __ sw(scratch3, MemOperand(scratch1));
156
176
  __ Addu(scratch1, scratch1, kPointerSize);
157
177
 
158
 
  // Fill the FixedArray with the hole value.
159
 
  ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
160
 
  ASSERT(initial_capacity <= kLoopUnfoldLimit);
 
178
  // Fill the FixedArray with the hole value. Inline the code if short.
 
179
  STATIC_ASSERT(2 * kPointerSize == FixedArray::kHeaderSize);
161
180
  __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex);
162
 
  for (int i = 0; i < initial_capacity; i++) {
 
181
  static const int kLoopUnfoldLimit = 4;
 
182
  if (initial_capacity <= kLoopUnfoldLimit) {
 
183
    for (int i = 0; i < initial_capacity; i++) {
 
184
      __ sw(scratch3, MemOperand(scratch1, i * kPointerSize));
 
185
    }
 
186
  } else {
 
187
    Label loop, entry;
 
188
    __ Addu(scratch2, scratch1, Operand(initial_capacity * kPointerSize));
 
189
    __ Branch(&entry);
 
190
    __ bind(&loop);
163
191
    __ sw(scratch3, MemOperand(scratch1));
164
192
    __ Addu(scratch1, scratch1, kPointerSize);
 
193
    __ bind(&entry);
 
194
    __ Branch(&loop, lt, scratch1, Operand(scratch2));
165
195
  }
166
196
}
167
197
 
177
207
// register elements_array_storage is scratched.
178
208
static void AllocateJSArray(MacroAssembler* masm,
179
209
                            Register array_function,  // Array function.
180
 
                            Register array_size,  // As a smi.
 
210
                            Register array_size,  // As a smi, cannot be 0.
181
211
                            Register result,
182
212
                            Register elements_array_storage,
183
213
                            Register elements_array_end,
185
215
                            Register scratch2,
186
216
                            bool fill_with_hole,
187
217
                            Label* gc_required) {
188
 
  Label not_empty, allocated;
189
 
 
190
218
  // Load the initial map from the array function.
191
 
  __ lw(elements_array_storage,
192
 
         FieldMemOperand(array_function,
193
 
                         JSFunction::kPrototypeOrInitialMapOffset));
194
 
 
195
 
  // Check whether an empty sized array is requested.
196
 
  __ Branch(&not_empty, ne, array_size, Operand(zero_reg));
197
 
 
198
 
  // If an empty array is requested allocate a small elements array anyway. This
199
 
  // keeps the code below free of special casing for the empty array.
200
 
  int size = JSArray::kSize +
201
 
             FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
202
 
  __ AllocateInNewSpace(size,
203
 
                        result,
204
 
                        elements_array_end,
205
 
                        scratch1,
206
 
                        gc_required,
207
 
                        TAG_OBJECT);
208
 
  __ Branch(&allocated);
 
219
  __ LoadInitialArrayMap(array_function, scratch2,
 
220
                         elements_array_storage, fill_with_hole);
 
221
 
 
222
  if (FLAG_debug_code) {  // Assert that array size is not zero.
 
223
    __ Assert(
 
224
        ne, "array size is unexpectedly 0", array_size, Operand(zero_reg));
 
225
  }
209
226
 
210
227
  // Allocate the JSArray object together with space for a FixedArray with the
211
228
  // requested number of elements.
212
 
  __ bind(&not_empty);
213
229
  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
214
230
  __ li(elements_array_end,
215
231
        (JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize);
228
244
  // result: JSObject
229
245
  // elements_array_storage: initial map
230
246
  // array_size: size of array (smi)
231
 
  __ bind(&allocated);
232
247
  __ sw(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset));
233
248
  __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex);
234
249
  __ sw(elements_array_storage,
262
277
  // the actual JSArray has length 0 and the size of the JSArray for non-empty
263
278
  // JSArrays. The length of a FixedArray is stored as a smi.
264
279
  STATIC_ASSERT(kSmiTag == 0);
265
 
  __ li(at, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
266
 
  __ movz(array_size, at, array_size);
267
280
 
268
281
  ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
269
282
  __ sw(array_size, MemOperand(elements_array_storage));
312
325
static void ArrayNativeCode(MacroAssembler* masm,
313
326
                            Label* call_generic_code) {
314
327
  Counters* counters = masm->isolate()->counters();
315
 
  Label argc_one_or_more, argc_two_or_more;
 
328
  Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array,
 
329
      has_non_smi_element, finish, cant_transition_map, not_double;
316
330
 
317
331
  // Check for array construction with zero arguments or one.
318
332
  __ Branch(&argc_one_or_more, ne, a0, Operand(zero_reg));
319
333
  // Handle construction of an empty array.
 
334
  __ bind(&empty_array);
320
335
  AllocateEmptyJSArray(masm,
321
336
                       a1,
322
337
                       a2,
323
338
                       a3,
324
339
                       t0,
325
340
                       t1,
326
 
                       JSArray::kPreallocatedArrayElements,
327
341
                       call_generic_code);
328
342
  __ IncrementCounter(counters->array_function_native(), 1, a3, t0);
329
 
  // Setup return value, remove receiver from stack and return.
 
343
  // Set up return value, remove receiver from stack and return.
330
344
  __ mov(v0, a2);
331
345
  __ Addu(sp, sp, Operand(kPointerSize));
332
346
  __ Ret();
338
352
 
339
353
  STATIC_ASSERT(kSmiTag == 0);
340
354
  __ lw(a2, MemOperand(sp));  // Get the argument from the stack.
 
355
  __ Branch(&not_empty_array, ne, a2, Operand(zero_reg));
 
356
  __ Drop(1);  // Adjust stack.
 
357
  __ mov(a0, zero_reg);  // Treat this as a call with argc of zero.
 
358
  __ Branch(&empty_array);
 
359
 
 
360
  __ bind(&not_empty_array);
341
361
  __ And(a3, a2, Operand(kIntptrSignBit | kSmiTagMask));
342
362
  __ Branch(call_generic_code, eq, a3, Operand(zero_reg));
343
363
 
363
383
                  call_generic_code);
364
384
  __ IncrementCounter(counters->array_function_native(), 1, a2, t0);
365
385
 
366
 
  // Setup return value, remove receiver and argument from stack and return.
 
386
  // Set up return value, remove receiver and argument from stack and return.
367
387
  __ mov(v0, a3);
368
388
  __ Addu(sp, sp, Operand(2 * kPointerSize));
369
389
  __ Ret();
398
418
  // sp[0]: last argument
399
419
 
400
420
  Label loop, entry;
401
 
  __ Branch(&entry);
 
421
  __ Branch(USE_DELAY_SLOT, &entry);
 
422
  __ mov(t3, sp);
402
423
  __ bind(&loop);
403
 
  __ pop(a2);
 
424
  __ lw(a2, MemOperand(t3));
 
425
  if (FLAG_smi_only_arrays) {
 
426
    __ JumpIfNotSmi(a2, &has_non_smi_element);
 
427
  }
 
428
  __ Addu(t3, t3, kPointerSize);
404
429
  __ Addu(t1, t1, -kPointerSize);
405
430
  __ sw(a2, MemOperand(t1));
406
431
  __ bind(&entry);
407
432
  __ Branch(&loop, lt, t0, Operand(t1));
408
433
 
 
434
  __ bind(&finish);
 
435
  __ mov(sp, t3);
 
436
 
409
437
  // Remove caller arguments and receiver from the stack, setup return value and
410
438
  // return.
411
439
  // a0: argc
414
442
  __ Addu(sp, sp, Operand(kPointerSize));
415
443
  __ mov(v0, a3);
416
444
  __ Ret();
 
445
 
 
446
  __ bind(&has_non_smi_element);
 
447
  // Double values are handled by the runtime.
 
448
  __ CheckMap(
 
449
      a2, t5, Heap::kHeapNumberMapRootIndex, &not_double, DONT_DO_SMI_CHECK);
 
450
  __ bind(&cant_transition_map);
 
451
  __ UndoAllocationInNewSpace(a3, t0);
 
452
  __ Branch(call_generic_code);
 
453
 
 
454
  __ bind(&not_double);
 
455
  // Transition FAST_SMI_ELEMENTS to FAST_ELEMENTS.
 
456
  // a3: JSArray
 
457
  __ lw(a2, FieldMemOperand(a3, HeapObject::kMapOffset));
 
458
  __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
 
459
                                         FAST_ELEMENTS,
 
460
                                         a2,
 
461
                                         t5,
 
462
                                         &cant_transition_map);
 
463
  __ sw(a2, FieldMemOperand(a3, HeapObject::kMapOffset));
 
464
  __ RecordWriteField(a3,
 
465
                      HeapObject::kMapOffset,
 
466
                      a2,
 
467
                      t5,
 
468
                      kRAHasNotBeenSaved,
 
469
                      kDontSaveFPRegs,
 
470
                      EMIT_REMEMBERED_SET,
 
471
                      OMIT_SMI_CHECK);
 
472
  Label loop2;
 
473
  __ bind(&loop2);
 
474
  __ lw(a2, MemOperand(t3));
 
475
  __ Addu(t3, t3, kPointerSize);
 
476
  __ Subu(t1, t1, kPointerSize);
 
477
  __ sw(a2, MemOperand(t1));
 
478
  __ Branch(&loop2, lt, t0, Operand(t1));
 
479
  __ Branch(&finish);
 
480
}
 
481
 
 
482
 
 
483
void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
 
484
  // ----------- S t a t e -------------
 
485
  //  -- a0     : number of arguments
 
486
  //  -- ra     : return address
 
487
  //  -- sp[...]: constructor arguments
 
488
  // -----------------------------------
 
489
  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
 
490
 
 
491
  // Get the InternalArray function.
 
492
  GenerateLoadInternalArrayFunction(masm, a1);
 
493
 
 
494
  if (FLAG_debug_code) {
 
495
    // Initial map for the builtin InternalArray functions should be maps.
 
496
    __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
 
497
    __ And(t0, a2, Operand(kSmiTagMask));
 
498
    __ Assert(ne, "Unexpected initial map for InternalArray function",
 
499
              t0, Operand(zero_reg));
 
500
    __ GetObjectType(a2, a3, t0);
 
501
    __ Assert(eq, "Unexpected initial map for InternalArray function",
 
502
              t0, Operand(MAP_TYPE));
 
503
  }
 
504
 
 
505
  // Run the native code for the InternalArray function called as a normal
 
506
  // function.
 
507
  ArrayNativeCode(masm, &generic_array_code);
 
508
 
 
509
  // Jump to the generic array code if the specialized code cannot handle the
 
510
  // construction.
 
511
  __ bind(&generic_array_code);
 
512
 
 
513
  Handle<Code> array_code =
 
514
      masm->isolate()->builtins()->InternalArrayCodeGeneric();
 
515
  __ Jump(array_code, RelocInfo::CODE_TARGET);
417
516
}
418
517
 
419
518
 
587
686
  __ bind(&convert_argument);
588
687
  __ push(function);  // Preserve the function.
589
688
  __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, t0);
590
 
  __ EnterInternalFrame();
591
 
  __ push(v0);
592
 
  __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
593
 
  __ LeaveInternalFrame();
 
689
  {
 
690
    FrameScope scope(masm, StackFrame::INTERNAL);
 
691
    __ push(v0);
 
692
    __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
 
693
  }
594
694
  __ pop(function);
595
695
  __ mov(argument, v0);
596
696
  __ Branch(&argument_is_string);
606
706
  // create a string wrapper.
607
707
  __ bind(&gc_required);
608
708
  __ IncrementCounter(counters->string_ctor_gc_required(), 1, a3, t0);
609
 
  __ EnterInternalFrame();
610
 
  __ push(argument);
611
 
  __ CallRuntime(Runtime::kNewStringWrapper, 1);
612
 
  __ LeaveInternalFrame();
 
709
  {
 
710
    FrameScope scope(masm, StackFrame::INTERNAL);
 
711
    __ push(argument);
 
712
    __ CallRuntime(Runtime::kNewStringWrapper, 1);
 
713
  }
613
714
  __ Ret();
614
715
}
615
716
 
616
717
 
617
 
void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
618
 
  // ----------- S t a t e -------------
619
 
  //  -- a0     : number of arguments
620
 
  //  -- a1     : constructor function
621
 
  //  -- ra     : return address
622
 
  //  -- sp[...]: constructor arguments
623
 
  // -----------------------------------
624
 
 
625
 
  Label non_function_call;
626
 
  // Check that the function is not a smi.
627
 
  __ And(t0, a1, Operand(kSmiTagMask));
628
 
  __ Branch(&non_function_call, eq, t0, Operand(zero_reg));
629
 
  // Check that the function is a JSFunction.
630
 
  __ GetObjectType(a1, a2, a2);
631
 
  __ Branch(&non_function_call, ne, a2, Operand(JS_FUNCTION_TYPE));
632
 
 
633
 
  // Jump to the function-specific construct stub.
 
718
static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
634
719
  __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
635
 
  __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kConstructStubOffset));
636
 
  __ Addu(t9, a2, Operand(Code::kHeaderSize - kHeapObjectTag));
637
 
  __ Jump(t9);
638
 
 
639
 
  // a0: number of arguments
640
 
  // a1: called object
641
 
  __ bind(&non_function_call);
642
 
  // CALL_NON_FUNCTION expects the non-function constructor as receiver
643
 
  // (instead of the original receiver from the call site). The receiver is
644
 
  // stack element argc.
645
 
  // Set expected number of arguments to zero (not changing a0).
646
 
  __ mov(a2, zero_reg);
647
 
  __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
648
 
  __ SetCallKind(t1, CALL_AS_METHOD);
649
 
  __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
650
 
          RelocInfo::CODE_TARGET);
 
720
  __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset));
 
721
  __ Addu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag));
 
722
  __ Jump(at);
 
723
}
 
724
 
 
725
 
 
726
void Builtins::Generate_InRecompileQueue(MacroAssembler* masm) {
 
727
  GenerateTailCallToSharedCode(masm);
 
728
}
 
729
 
 
730
 
 
731
void Builtins::Generate_ParallelRecompile(MacroAssembler* masm) {
 
732
  {
 
733
    FrameScope scope(masm, StackFrame::INTERNAL);
 
734
 
 
735
    // Push a copy of the function onto the stack.
 
736
    __ push(a1);
 
737
    // Push call kind information.
 
738
    __ push(t1);
 
739
 
 
740
    __ push(a1);  // Function is also the parameter to the runtime call.
 
741
    __ CallRuntime(Runtime::kParallelRecompile, 1);
 
742
 
 
743
    // Restore call kind information.
 
744
    __ pop(t1);
 
745
    // Restore receiver.
 
746
    __ pop(a1);
 
747
 
 
748
    // Tear down internal frame.
 
749
  }
 
750
 
 
751
  GenerateTailCallToSharedCode(masm);
651
752
}
652
753
 
653
754
 
654
755
static void Generate_JSConstructStubHelper(MacroAssembler* masm,
655
756
                                           bool is_api_function,
656
757
                                           bool count_constructions) {
 
758
  // ----------- S t a t e -------------
 
759
  //  -- a0     : number of arguments
 
760
  //  -- a1     : constructor function
 
761
  //  -- ra     : return address
 
762
  //  -- sp[...]: constructor arguments
 
763
  // -----------------------------------
 
764
 
657
765
  // Should never count constructions for api objects.
658
766
  ASSERT(!is_api_function || !count_constructions);
659
767
 
667
775
  // -----------------------------------
668
776
 
669
777
  // Enter a construct frame.
670
 
  __ EnterConstructFrame();
671
 
 
672
 
  // Preserve the two incoming parameters on the stack.
673
 
  __ sll(a0, a0, kSmiTagSize);  // Tag arguments count.
674
 
  __ MultiPushReversed(a0.bit() | a1.bit());
675
 
 
676
 
  // Use t7 to hold undefined, which is used in several places below.
677
 
  __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
678
 
 
679
 
  Label rt_call, allocated;
680
 
  // Try to allocate the object without transitioning into C code. If any of the
681
 
  // preconditions is not met, the code bails out to the runtime call.
682
 
  if (FLAG_inline_new) {
683
 
    Label undo_allocation;
 
778
  {
 
779
    FrameScope scope(masm, StackFrame::CONSTRUCT);
 
780
 
 
781
    // Preserve the two incoming parameters on the stack.
 
782
    __ sll(a0, a0, kSmiTagSize);  // Tag arguments count.
 
783
    __ MultiPushReversed(a0.bit() | a1.bit());
 
784
 
 
785
    // Use t7 to hold undefined, which is used in several places below.
 
786
    __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
 
787
 
 
788
    Label rt_call, allocated;
 
789
    // Try to allocate the object without transitioning into C code. If any of
 
790
    // the preconditions is not met, the code bails out to the runtime call.
 
791
    if (FLAG_inline_new) {
 
792
      Label undo_allocation;
684
793
#ifdef ENABLE_DEBUGGER_SUPPORT
685
 
    ExternalReference debug_step_in_fp =
686
 
        ExternalReference::debug_step_in_fp_address(isolate);
687
 
    __ li(a2, Operand(debug_step_in_fp));
688
 
    __ lw(a2, MemOperand(a2));
689
 
    __ Branch(&rt_call, ne, a2, Operand(zero_reg));
 
794
      ExternalReference debug_step_in_fp =
 
795
          ExternalReference::debug_step_in_fp_address(isolate);
 
796
      __ li(a2, Operand(debug_step_in_fp));
 
797
      __ lw(a2, MemOperand(a2));
 
798
      __ Branch(&rt_call, ne, a2, Operand(zero_reg));
690
799
#endif
691
800
 
692
 
    // Load the initial map and verify that it is in fact a map.
693
 
    // a1: constructor function
694
 
    __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
695
 
    __ And(t0, a2, Operand(kSmiTagMask));
696
 
    __ Branch(&rt_call, eq, t0, Operand(zero_reg));
697
 
    __ GetObjectType(a2, a3, t4);
698
 
    __ Branch(&rt_call, ne, t4, Operand(MAP_TYPE));
699
 
 
700
 
    // Check that the constructor is not constructing a JSFunction (see comments
701
 
    // in Runtime_NewObject in runtime.cc). In which case the initial map's
702
 
    // instance type would be JS_FUNCTION_TYPE.
703
 
    // a1: constructor function
704
 
    // a2: initial map
705
 
    __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
706
 
    __ Branch(&rt_call, eq, a3, Operand(JS_FUNCTION_TYPE));
707
 
 
708
 
    if (count_constructions) {
709
 
      Label allocate;
710
 
      // Decrease generous allocation count.
711
 
      __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
712
 
      MemOperand constructor_count =
713
 
         FieldMemOperand(a3, SharedFunctionInfo::kConstructionCountOffset);
714
 
      __ lbu(t0, constructor_count);
715
 
      __ Subu(t0, t0, Operand(1));
716
 
      __ sb(t0, constructor_count);
717
 
      __ Branch(&allocate, ne, t0, Operand(zero_reg));
718
 
 
719
 
      __ Push(a1, a2);
720
 
 
721
 
      __ push(a1);  // Constructor.
722
 
      // The call will replace the stub, so the countdown is only done once.
723
 
      __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
724
 
 
725
 
      __ pop(a2);
726
 
      __ pop(a1);
727
 
 
728
 
      __ bind(&allocate);
729
 
    }
730
 
 
731
 
    // Now allocate the JSObject on the heap.
732
 
    // a1: constructor function
733
 
    // a2: initial map
734
 
    __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
735
 
    __ AllocateInNewSpace(a3, t4, t5, t6, &rt_call, SIZE_IN_WORDS);
736
 
 
737
 
    // Allocated the JSObject, now initialize the fields. Map is set to initial
738
 
    // map and properties and elements are set to empty fixed array.
739
 
    // a1: constructor function
740
 
    // a2: initial map
741
 
    // a3: object size
742
 
    // t4: JSObject (not tagged)
743
 
    __ LoadRoot(t6, Heap::kEmptyFixedArrayRootIndex);
744
 
    __ mov(t5, t4);
745
 
    __ sw(a2, MemOperand(t5, JSObject::kMapOffset));
746
 
    __ sw(t6, MemOperand(t5, JSObject::kPropertiesOffset));
747
 
    __ sw(t6, MemOperand(t5, JSObject::kElementsOffset));
748
 
    __ Addu(t5, t5, Operand(3*kPointerSize));
749
 
    ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
750
 
    ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
751
 
    ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
752
 
 
753
 
    // Fill all the in-object properties with appropriate filler.
754
 
    // a1: constructor function
755
 
    // a2: initial map
756
 
    // a3: object size (in words)
757
 
    // t4: JSObject (not tagged)
758
 
    // t5: First in-object property of JSObject (not tagged)
759
 
    __ sll(t0, a3, kPointerSizeLog2);
760
 
    __ addu(t6, t4, t0);   // End of object.
761
 
    ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
762
 
    { Label loop, entry;
763
 
      if (count_constructions) {
 
801
      // Load the initial map and verify that it is in fact a map.
 
802
      // a1: constructor function
 
803
      __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
 
804
      __ JumpIfSmi(a2, &rt_call);
 
805
      __ GetObjectType(a2, a3, t4);
 
806
      __ Branch(&rt_call, ne, t4, Operand(MAP_TYPE));
 
807
 
 
808
      // Check that the constructor is not constructing a JSFunction (see
 
809
      // comments in Runtime_NewObject in runtime.cc). In which case the
 
810
      // initial map's instance type would be JS_FUNCTION_TYPE.
 
811
      // a1: constructor function
 
812
      // a2: initial map
 
813
      __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
 
814
      __ Branch(&rt_call, eq, a3, Operand(JS_FUNCTION_TYPE));
 
815
 
 
816
      if (count_constructions) {
 
817
        Label allocate;
 
818
        // Decrease generous allocation count.
 
819
        __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
 
820
        MemOperand constructor_count =
 
821
           FieldMemOperand(a3, SharedFunctionInfo::kConstructionCountOffset);
 
822
        __ lbu(t0, constructor_count);
 
823
        __ Subu(t0, t0, Operand(1));
 
824
        __ sb(t0, constructor_count);
 
825
        __ Branch(&allocate, ne, t0, Operand(zero_reg));
 
826
 
 
827
        __ Push(a1, a2);
 
828
 
 
829
        __ push(a1);  // Constructor.
 
830
        // The call will replace the stub, so the countdown is only done once.
 
831
        __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
 
832
 
 
833
        __ pop(a2);
 
834
        __ pop(a1);
 
835
 
 
836
        __ bind(&allocate);
 
837
      }
 
838
 
 
839
      // Now allocate the JSObject on the heap.
 
840
      // a1: constructor function
 
841
      // a2: initial map
 
842
      __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
 
843
      __ AllocateInNewSpace(a3, t4, t5, t6, &rt_call, SIZE_IN_WORDS);
 
844
 
 
845
      // Allocated the JSObject, now initialize the fields. Map is set to
 
846
      // initial map and properties and elements are set to empty fixed array.
 
847
      // a1: constructor function
 
848
      // a2: initial map
 
849
      // a3: object size
 
850
      // t4: JSObject (not tagged)
 
851
      __ LoadRoot(t6, Heap::kEmptyFixedArrayRootIndex);
 
852
      __ mov(t5, t4);
 
853
      __ sw(a2, MemOperand(t5, JSObject::kMapOffset));
 
854
      __ sw(t6, MemOperand(t5, JSObject::kPropertiesOffset));
 
855
      __ sw(t6, MemOperand(t5, JSObject::kElementsOffset));
 
856
      __ Addu(t5, t5, Operand(3*kPointerSize));
 
857
      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
 
858
      ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
 
859
      ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
 
860
 
 
861
      // Fill all the in-object properties with appropriate filler.
 
862
      // a1: constructor function
 
863
      // a2: initial map
 
864
      // a3: object size (in words)
 
865
      // t4: JSObject (not tagged)
 
866
      // t5: First in-object property of JSObject (not tagged)
 
867
      __ sll(t0, a3, kPointerSizeLog2);
 
868
      __ addu(t6, t4, t0);   // End of object.
 
869
      ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
 
870
      __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
 
871
      if (count_constructions) {
 
872
        __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
 
873
        __ Ext(a0, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
 
874
                kBitsPerByte);
 
875
        __ sll(t0, a0, kPointerSizeLog2);
 
876
        __ addu(a0, t5, t0);
 
877
        // a0: offset of first field after pre-allocated fields
 
878
        if (FLAG_debug_code) {
 
879
          __ Assert(le, "Unexpected number of pre-allocated property fields.",
 
880
              a0, Operand(t6));
 
881
        }
 
882
        __ InitializeFieldsWithFiller(t5, a0, t7);
764
883
        // To allow for truncation.
765
884
        __ LoadRoot(t7, Heap::kOnePointerFillerMapRootIndex);
766
 
      } else {
767
 
        __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
768
 
      }
769
 
      __ jmp(&entry);
770
 
      __ bind(&loop);
771
 
      __ sw(t7, MemOperand(t5, 0));
772
 
      __ addiu(t5, t5, kPointerSize);
773
 
      __ bind(&entry);
774
 
      __ Branch(&loop, Uless, t5, Operand(t6));
775
 
    }
776
 
 
777
 
    // Add the object tag to make the JSObject real, so that we can continue and
778
 
    // jump into the continuation code at any time from now on. Any failures
779
 
    // need to undo the allocation, so that the heap is in a consistent state
780
 
    // and verifiable.
781
 
    __ Addu(t4, t4, Operand(kHeapObjectTag));
782
 
 
783
 
    // Check if a non-empty properties array is needed. Continue with allocated
784
 
    // object if not fall through to runtime call if it is.
785
 
    // a1: constructor function
786
 
    // t4: JSObject
787
 
    // t5: start of next object (not tagged)
788
 
    __ lbu(a3, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
789
 
    // The field instance sizes contains both pre-allocated property fields and
790
 
    // in-object properties.
791
 
    __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
792
 
    __ And(t6,
793
 
           a0,
794
 
           Operand(0x000000FF << Map::kPreAllocatedPropertyFieldsByte * 8));
795
 
    __ srl(t0, t6, Map::kPreAllocatedPropertyFieldsByte * 8);
796
 
    __ Addu(a3, a3, Operand(t0));
797
 
    __ And(t6, a0, Operand(0x000000FF << Map::kInObjectPropertiesByte * 8));
798
 
    __ srl(t0, t6, Map::kInObjectPropertiesByte * 8);
799
 
    __ subu(a3, a3, t0);
800
 
 
801
 
    // Done if no extra properties are to be allocated.
802
 
    __ Branch(&allocated, eq, a3, Operand(zero_reg));
803
 
    __ Assert(greater_equal, "Property allocation count failed.",
804
 
        a3, Operand(zero_reg));
805
 
 
806
 
    // Scale the number of elements by pointer size and add the header for
807
 
    // FixedArrays to the start of the next object calculation from above.
808
 
    // a1: constructor
809
 
    // a3: number of elements in properties array
810
 
    // t4: JSObject
811
 
    // t5: start of next object
812
 
    __ Addu(a0, a3, Operand(FixedArray::kHeaderSize / kPointerSize));
813
 
    __ AllocateInNewSpace(
814
 
        a0,
815
 
        t5,
816
 
        t6,
817
 
        a2,
818
 
        &undo_allocation,
819
 
        static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
820
 
 
821
 
    // Initialize the FixedArray.
822
 
    // a1: constructor
823
 
    // a3: number of elements in properties array (un-tagged)
824
 
    // t4: JSObject
825
 
    // t5: start of next object
826
 
    __ LoadRoot(t6, Heap::kFixedArrayMapRootIndex);
827
 
    __ mov(a2, t5);
828
 
    __ sw(t6, MemOperand(a2, JSObject::kMapOffset));
829
 
    __ sll(a0, a3, kSmiTagSize);
830
 
    __ sw(a0, MemOperand(a2, FixedArray::kLengthOffset));
831
 
    __ Addu(a2, a2, Operand(2 * kPointerSize));
832
 
 
833
 
    ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
834
 
    ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
835
 
 
836
 
    // Initialize the fields to undefined.
837
 
    // a1: constructor
838
 
    // a2: First element of FixedArray (not tagged)
839
 
    // a3: number of elements in properties array
840
 
    // t4: JSObject
841
 
    // t5: FixedArray (not tagged)
842
 
    __ sll(t3, a3, kPointerSizeLog2);
843
 
    __ addu(t6, a2, t3);  // End of object.
844
 
    ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
845
 
    { Label loop, entry;
846
 
      if (count_constructions) {
847
 
        __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
848
 
      } else if (FLAG_debug_code) {
849
 
        __ LoadRoot(t8, Heap::kUndefinedValueRootIndex);
850
 
        __ Assert(eq, "Undefined value not loaded.", t7, Operand(t8));
851
 
      }
852
 
      __ jmp(&entry);
853
 
      __ bind(&loop);
854
 
      __ sw(t7, MemOperand(a2));
855
 
      __ addiu(a2, a2, kPointerSize);
856
 
      __ bind(&entry);
857
 
      __ Branch(&loop, less, a2, Operand(t6));
858
 
    }
859
 
 
860
 
    // Store the initialized FixedArray into the properties field of
861
 
    // the JSObject.
862
 
    // a1: constructor function
863
 
    // t4: JSObject
864
 
    // t5: FixedArray (not tagged)
865
 
    __ Addu(t5, t5, Operand(kHeapObjectTag));  // Add the heap tag.
866
 
    __ sw(t5, FieldMemOperand(t4, JSObject::kPropertiesOffset));
867
 
 
868
 
    // Continue with JSObject being successfully allocated.
869
 
    // a1: constructor function
870
 
    // a4: JSObject
871
 
    __ jmp(&allocated);
872
 
 
873
 
    // Undo the setting of the new top so that the heap is verifiable. For
874
 
    // example, the map's unused properties potentially do not match the
875
 
    // allocated objects unused properties.
876
 
    // t4: JSObject (previous new top)
877
 
    __ bind(&undo_allocation);
878
 
    __ UndoAllocationInNewSpace(t4, t5);
879
 
  }
880
 
 
881
 
  __ bind(&rt_call);
882
 
  // Allocate the new receiver object using the runtime call.
883
 
  // a1: constructor function
884
 
  __ push(a1);  // Argument for Runtime_NewObject.
885
 
  __ CallRuntime(Runtime::kNewObject, 1);
886
 
  __ mov(t4, v0);
887
 
 
888
 
  // Receiver for constructor call allocated.
889
 
  // t4: JSObject
890
 
  __ bind(&allocated);
891
 
  __ push(t4);
892
 
 
893
 
  // Push the function and the allocated receiver from the stack.
894
 
  // sp[0]: receiver (newly allocated object)
895
 
  // sp[1]: constructor function
896
 
  // sp[2]: number of arguments (smi-tagged)
897
 
  __ lw(a1, MemOperand(sp, kPointerSize));
898
 
  __ MultiPushReversed(a1.bit() | t4.bit());
899
 
 
900
 
  // Reload the number of arguments from the stack.
901
 
  // a1: constructor function
902
 
  // sp[0]: receiver
903
 
  // sp[1]: constructor function
904
 
  // sp[2]: receiver
905
 
  // sp[3]: constructor function
906
 
  // sp[4]: number of arguments (smi-tagged)
907
 
  __ lw(a3, MemOperand(sp, 4 * kPointerSize));
908
 
 
909
 
  // Setup pointer to last argument.
910
 
  __ Addu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
911
 
 
912
 
  // Setup number of arguments for function call below.
913
 
  __ srl(a0, a3, kSmiTagSize);
914
 
 
915
 
  // Copy arguments and receiver to the expression stack.
916
 
  // a0: number of arguments
917
 
  // a1: constructor function
918
 
  // a2: address of last argument (caller sp)
919
 
  // a3: number of arguments (smi-tagged)
920
 
  // sp[0]: receiver
921
 
  // sp[1]: constructor function
922
 
  // sp[2]: receiver
923
 
  // sp[3]: constructor function
924
 
  // sp[4]: number of arguments (smi-tagged)
925
 
  Label loop, entry;
926
 
  __ jmp(&entry);
927
 
  __ bind(&loop);
928
 
  __ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize);
929
 
  __ Addu(t0, a2, Operand(t0));
930
 
  __ lw(t1, MemOperand(t0));
931
 
  __ push(t1);
932
 
  __ bind(&entry);
933
 
  __ Addu(a3, a3, Operand(-2));
934
 
  __ Branch(&loop, greater_equal, a3, Operand(zero_reg));
935
 
 
936
 
  // Call the function.
937
 
  // a0: number of arguments
938
 
  // a1: constructor function
939
 
  if (is_api_function) {
940
 
    __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
941
 
    Handle<Code> code =
942
 
        masm->isolate()->builtins()->HandleApiCallConstruct();
943
 
    ParameterCount expected(0);
944
 
    __ InvokeCode(code, expected, expected,
945
 
                  RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD);
946
 
  } else {
947
 
    ParameterCount actual(a0);
948
 
    __ InvokeFunction(a1, actual, CALL_FUNCTION,
949
 
                      NullCallWrapper(), CALL_AS_METHOD);
950
 
  }
951
 
 
952
 
  // Pop the function from the stack.
953
 
  // v0: result
954
 
  // sp[0]: constructor function
955
 
  // sp[2]: receiver
956
 
  // sp[3]: constructor function
957
 
  // sp[4]: number of arguments (smi-tagged)
958
 
  __ Pop();
959
 
 
960
 
  // Restore context from the frame.
961
 
  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
962
 
 
963
 
  // If the result is an object (in the ECMA sense), we should get rid
964
 
  // of the receiver and use the result; see ECMA-262 section 13.2.2-7
965
 
  // on page 74.
966
 
  Label use_receiver, exit;
967
 
 
968
 
  // If the result is a smi, it is *not* an object in the ECMA sense.
969
 
  // v0: result
970
 
  // sp[0]: receiver (newly allocated object)
971
 
  // sp[1]: constructor function
972
 
  // sp[2]: number of arguments (smi-tagged)
973
 
  __ And(t0, v0, Operand(kSmiTagMask));
974
 
  __ Branch(&use_receiver, eq, t0, Operand(zero_reg));
975
 
 
976
 
  // If the type of the result (stored in its map) is less than
977
 
  // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
978
 
  __ GetObjectType(v0, a3, a3);
979
 
  __ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
980
 
 
981
 
  // Throw away the result of the constructor invocation and use the
982
 
  // on-stack receiver as the result.
983
 
  __ bind(&use_receiver);
984
 
  __ lw(v0, MemOperand(sp));
985
 
 
986
 
  // Remove receiver from the stack, remove caller arguments, and
987
 
  // return.
988
 
  __ bind(&exit);
989
 
  // v0: result
990
 
  // sp[0]: receiver (newly allocated object)
991
 
  // sp[1]: constructor function
992
 
  // sp[2]: number of arguments (smi-tagged)
993
 
  __ lw(a1, MemOperand(sp, 2 * kPointerSize));
994
 
  __ LeaveConstructFrame();
 
885
      }
 
886
      __ InitializeFieldsWithFiller(t5, t6, t7);
 
887
 
 
888
      // Add the object tag to make the JSObject real, so that we can continue
 
889
      // and jump into the continuation code at any time from now on. Any
 
890
      // failures need to undo the allocation, so that the heap is in a
 
891
      // consistent state and verifiable.
 
892
      __ Addu(t4, t4, Operand(kHeapObjectTag));
 
893
 
 
894
      // Check if a non-empty properties array is needed. Continue with
 
895
      // allocated object if not fall through to runtime call if it is.
 
896
      // a1: constructor function
 
897
      // t4: JSObject
 
898
      // t5: start of next object (not tagged)
 
899
      __ lbu(a3, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset));
 
900
      // The field instance sizes contains both pre-allocated property fields
 
901
      // and in-object properties.
 
902
      __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset));
 
903
      __ Ext(t6, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
 
904
             kBitsPerByte);
 
905
      __ Addu(a3, a3, Operand(t6));
 
906
      __ Ext(t6, a0, Map::kInObjectPropertiesByte * kBitsPerByte,
 
907
              kBitsPerByte);
 
908
      __ subu(a3, a3, t6);
 
909
 
 
910
      // Done if no extra properties are to be allocated.
 
911
      __ Branch(&allocated, eq, a3, Operand(zero_reg));
 
912
      __ Assert(greater_equal, "Property allocation count failed.",
 
913
          a3, Operand(zero_reg));
 
914
 
 
915
      // Scale the number of elements by pointer size and add the header for
 
916
      // FixedArrays to the start of the next object calculation from above.
 
917
      // a1: constructor
 
918
      // a3: number of elements in properties array
 
919
      // t4: JSObject
 
920
      // t5: start of next object
 
921
      __ Addu(a0, a3, Operand(FixedArray::kHeaderSize / kPointerSize));
 
922
      __ AllocateInNewSpace(
 
923
          a0,
 
924
          t5,
 
925
          t6,
 
926
          a2,
 
927
          &undo_allocation,
 
928
          static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS));
 
929
 
 
930
      // Initialize the FixedArray.
 
931
      // a1: constructor
 
932
      // a3: number of elements in properties array (untagged)
 
933
      // t4: JSObject
 
934
      // t5: start of next object
 
935
      __ LoadRoot(t6, Heap::kFixedArrayMapRootIndex);
 
936
      __ mov(a2, t5);
 
937
      __ sw(t6, MemOperand(a2, JSObject::kMapOffset));
 
938
      __ sll(a0, a3, kSmiTagSize);
 
939
      __ sw(a0, MemOperand(a2, FixedArray::kLengthOffset));
 
940
      __ Addu(a2, a2, Operand(2 * kPointerSize));
 
941
 
 
942
      ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
 
943
      ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset);
 
944
 
 
945
      // Initialize the fields to undefined.
 
946
      // a1: constructor
 
947
      // a2: First element of FixedArray (not tagged)
 
948
      // a3: number of elements in properties array
 
949
      // t4: JSObject
 
950
      // t5: FixedArray (not tagged)
 
951
      __ sll(t3, a3, kPointerSizeLog2);
 
952
      __ addu(t6, a2, t3);  // End of object.
 
953
      ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
 
954
      { Label loop, entry;
 
955
        if (count_constructions) {
 
956
          __ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
 
957
        } else if (FLAG_debug_code) {
 
958
          __ LoadRoot(t8, Heap::kUndefinedValueRootIndex);
 
959
          __ Assert(eq, "Undefined value not loaded.", t7, Operand(t8));
 
960
        }
 
961
        __ jmp(&entry);
 
962
        __ bind(&loop);
 
963
        __ sw(t7, MemOperand(a2));
 
964
        __ addiu(a2, a2, kPointerSize);
 
965
        __ bind(&entry);
 
966
        __ Branch(&loop, less, a2, Operand(t6));
 
967
      }
 
968
 
 
969
      // Store the initialized FixedArray into the properties field of
 
970
      // the JSObject.
 
971
      // a1: constructor function
 
972
      // t4: JSObject
 
973
      // t5: FixedArray (not tagged)
 
974
      __ Addu(t5, t5, Operand(kHeapObjectTag));  // Add the heap tag.
 
975
      __ sw(t5, FieldMemOperand(t4, JSObject::kPropertiesOffset));
 
976
 
 
977
      // Continue with JSObject being successfully allocated.
 
978
      // a1: constructor function
 
979
      // a4: JSObject
 
980
      __ jmp(&allocated);
 
981
 
 
982
      // Undo the setting of the new top so that the heap is verifiable. For
 
983
      // example, the map's unused properties potentially do not match the
 
984
      // allocated objects unused properties.
 
985
      // t4: JSObject (previous new top)
 
986
      __ bind(&undo_allocation);
 
987
      __ UndoAllocationInNewSpace(t4, t5);
 
988
    }
 
989
 
 
990
    __ bind(&rt_call);
 
991
    // Allocate the new receiver object using the runtime call.
 
992
    // a1: constructor function
 
993
    __ push(a1);  // Argument for Runtime_NewObject.
 
994
    __ CallRuntime(Runtime::kNewObject, 1);
 
995
    __ mov(t4, v0);
 
996
 
 
997
    // Receiver for constructor call allocated.
 
998
    // t4: JSObject
 
999
    __ bind(&allocated);
 
1000
    __ push(t4);
 
1001
    __ push(t4);
 
1002
 
 
1003
    // Reload the number of arguments from the stack.
 
1004
    // sp[0]: receiver
 
1005
    // sp[1]: receiver
 
1006
    // sp[2]: constructor function
 
1007
    // sp[3]: number of arguments (smi-tagged)
 
1008
    __ lw(a1, MemOperand(sp, 2 * kPointerSize));
 
1009
    __ lw(a3, MemOperand(sp, 3 * kPointerSize));
 
1010
 
 
1011
    // Set up pointer to last argument.
 
1012
    __ Addu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
 
1013
 
 
1014
    // Set up number of arguments for function call below.
 
1015
    __ srl(a0, a3, kSmiTagSize);
 
1016
 
 
1017
    // Copy arguments and receiver to the expression stack.
 
1018
    // a0: number of arguments
 
1019
    // a1: constructor function
 
1020
    // a2: address of last argument (caller sp)
 
1021
    // a3: number of arguments (smi-tagged)
 
1022
    // sp[0]: receiver
 
1023
    // sp[1]: receiver
 
1024
    // sp[2]: constructor function
 
1025
    // sp[3]: number of arguments (smi-tagged)
 
1026
    Label loop, entry;
 
1027
    __ jmp(&entry);
 
1028
    __ bind(&loop);
 
1029
    __ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize);
 
1030
    __ Addu(t0, a2, Operand(t0));
 
1031
    __ lw(t1, MemOperand(t0));
 
1032
    __ push(t1);
 
1033
    __ bind(&entry);
 
1034
    __ Addu(a3, a3, Operand(-2));
 
1035
    __ Branch(&loop, greater_equal, a3, Operand(zero_reg));
 
1036
 
 
1037
    // Call the function.
 
1038
    // a0: number of arguments
 
1039
    // a1: constructor function
 
1040
    if (is_api_function) {
 
1041
      __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
 
1042
      Handle<Code> code =
 
1043
          masm->isolate()->builtins()->HandleApiCallConstruct();
 
1044
      ParameterCount expected(0);
 
1045
      __ InvokeCode(code, expected, expected,
 
1046
                    RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD);
 
1047
    } else {
 
1048
      ParameterCount actual(a0);
 
1049
      __ InvokeFunction(a1, actual, CALL_FUNCTION,
 
1050
                        NullCallWrapper(), CALL_AS_METHOD);
 
1051
    }
 
1052
 
 
1053
    // Store offset of return address for deoptimizer.
 
1054
    if (!is_api_function && !count_constructions) {
 
1055
      masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
 
1056
    }
 
1057
 
 
1058
    // Restore context from the frame.
 
1059
    __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
 
1060
 
 
1061
    // If the result is an object (in the ECMA sense), we should get rid
 
1062
    // of the receiver and use the result; see ECMA-262 section 13.2.2-7
 
1063
    // on page 74.
 
1064
    Label use_receiver, exit;
 
1065
 
 
1066
    // If the result is a smi, it is *not* an object in the ECMA sense.
 
1067
    // v0: result
 
1068
    // sp[0]: receiver (newly allocated object)
 
1069
    // sp[1]: constructor function
 
1070
    // sp[2]: number of arguments (smi-tagged)
 
1071
    __ JumpIfSmi(v0, &use_receiver);
 
1072
 
 
1073
    // If the type of the result (stored in its map) is less than
 
1074
    // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
 
1075
    __ GetObjectType(v0, a3, a3);
 
1076
    __ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
 
1077
 
 
1078
    // Throw away the result of the constructor invocation and use the
 
1079
    // on-stack receiver as the result.
 
1080
    __ bind(&use_receiver);
 
1081
    __ lw(v0, MemOperand(sp));
 
1082
 
 
1083
    // Remove receiver from the stack, remove caller arguments, and
 
1084
    // return.
 
1085
    __ bind(&exit);
 
1086
    // v0: result
 
1087
    // sp[0]: receiver (newly allocated object)
 
1088
    // sp[1]: constructor function
 
1089
    // sp[2]: number of arguments (smi-tagged)
 
1090
    __ lw(a1, MemOperand(sp, 2 * kPointerSize));
 
1091
 
 
1092
    // Leave construct frame.
 
1093
  }
 
1094
 
995
1095
  __ sll(t0, a1, kPointerSizeLog2 - 1);
996
1096
  __ Addu(sp, sp, t0);
997
1097
  __ Addu(sp, sp, kPointerSize);
1022
1122
  // ----------- S t a t e -------------
1023
1123
  //  -- a0: code entry
1024
1124
  //  -- a1: function
1025
 
  //  -- a2: reveiver_pointer
 
1125
  //  -- a2: receiver_pointer
1026
1126
  //  -- a3: argc
1027
1127
  //  -- s0: argv
1028
1128
  // -----------------------------------
1031
1131
  __ mov(cp, zero_reg);
1032
1132
 
1033
1133
  // Enter an internal frame.
1034
 
  __ EnterInternalFrame();
1035
 
 
1036
 
  // Set up the context from the function argument.
1037
 
  __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
1038
 
 
1039
 
  // Set up the roots register.
1040
 
  ExternalReference roots_address =
1041
 
      ExternalReference::roots_address(masm->isolate());
1042
 
  __ li(s6, Operand(roots_address));
1043
 
 
1044
 
  // Push the function and the receiver onto the stack.
1045
 
  __ Push(a1, a2);
1046
 
 
1047
 
  // Copy arguments to the stack in a loop.
1048
 
  // a3: argc
1049
 
  // s0: argv, ie points to first arg
1050
 
  Label loop, entry;
1051
 
  __ sll(t0, a3, kPointerSizeLog2);
1052
 
  __ addu(t2, s0, t0);
1053
 
  __ b(&entry);
1054
 
  __ nop();   // Branch delay slot nop.
1055
 
  // t2 points past last arg.
1056
 
  __ bind(&loop);
1057
 
  __ lw(t0, MemOperand(s0));  // Read next parameter.
1058
 
  __ addiu(s0, s0, kPointerSize);
1059
 
  __ lw(t0, MemOperand(t0));  // Dereference handle.
1060
 
  __ push(t0);  // Push parameter.
1061
 
  __ bind(&entry);
1062
 
  __ Branch(&loop, ne, s0, Operand(t2));
1063
 
 
1064
 
  // Initialize all JavaScript callee-saved registers, since they will be seen
1065
 
  // by the garbage collector as part of handlers.
1066
 
  __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
1067
 
  __ mov(s1, t0);
1068
 
  __ mov(s2, t0);
1069
 
  __ mov(s3, t0);
1070
 
  __ mov(s4, t0);
1071
 
  __ mov(s5, t0);
1072
 
  // s6 holds the root address. Do not clobber.
1073
 
  // s7 is cp. Do not init.
1074
 
 
1075
 
  // Invoke the code and pass argc as a0.
1076
 
  __ mov(a0, a3);
1077
 
  if (is_construct) {
1078
 
    __ Call(masm->isolate()->builtins()->JSConstructCall());
1079
 
  } else {
1080
 
    ParameterCount actual(a0);
1081
 
    __ InvokeFunction(a1, actual, CALL_FUNCTION,
1082
 
                      NullCallWrapper(), CALL_AS_METHOD);
 
1134
  {
 
1135
    FrameScope scope(masm, StackFrame::INTERNAL);
 
1136
 
 
1137
    // Set up the context from the function argument.
 
1138
    __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
 
1139
 
 
1140
    // Push the function and the receiver onto the stack.
 
1141
    __ Push(a1, a2);
 
1142
 
 
1143
    // Copy arguments to the stack in a loop.
 
1144
    // a3: argc
 
1145
    // s0: argv, i.e. points to first arg
 
1146
    Label loop, entry;
 
1147
    __ sll(t0, a3, kPointerSizeLog2);
 
1148
    __ addu(t2, s0, t0);
 
1149
    __ b(&entry);
 
1150
    __ nop();   // Branch delay slot nop.
 
1151
    // t2 points past last arg.
 
1152
    __ bind(&loop);
 
1153
    __ lw(t0, MemOperand(s0));  // Read next parameter.
 
1154
    __ addiu(s0, s0, kPointerSize);
 
1155
    __ lw(t0, MemOperand(t0));  // Dereference handle.
 
1156
    __ push(t0);  // Push parameter.
 
1157
    __ bind(&entry);
 
1158
    __ Branch(&loop, ne, s0, Operand(t2));
 
1159
 
 
1160
    // Initialize all JavaScript callee-saved registers, since they will be seen
 
1161
    // by the garbage collector as part of handlers.
 
1162
    __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
 
1163
    __ mov(s1, t0);
 
1164
    __ mov(s2, t0);
 
1165
    __ mov(s3, t0);
 
1166
    __ mov(s4, t0);
 
1167
    __ mov(s5, t0);
 
1168
    // s6 holds the root address. Do not clobber.
 
1169
    // s7 is cp. Do not init.
 
1170
 
 
1171
    // Invoke the code and pass argc as a0.
 
1172
    __ mov(a0, a3);
 
1173
    if (is_construct) {
 
1174
      CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
 
1175
      __ CallStub(&stub);
 
1176
    } else {
 
1177
      ParameterCount actual(a0);
 
1178
      __ InvokeFunction(a1, actual, CALL_FUNCTION,
 
1179
                        NullCallWrapper(), CALL_AS_METHOD);
 
1180
    }
 
1181
 
 
1182
    // Leave internal frame.
1083
1183
  }
1084
1184
 
1085
 
  __ LeaveInternalFrame();
1086
 
 
1087
1185
  __ Jump(ra);
1088
1186
}
1089
1187
 
1100
1198
 
1101
1199
void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
1102
1200
  // Enter an internal frame.
1103
 
  __ EnterInternalFrame();
1104
 
 
1105
 
  // Preserve the function.
1106
 
  __ push(a1);
1107
 
  // Push call kind information.
1108
 
  __ push(t1);
1109
 
 
1110
 
  // Push the function on the stack as the argument to the runtime function.
1111
 
  __ push(a1);
1112
 
  // Call the runtime function.
1113
 
  __ CallRuntime(Runtime::kLazyCompile, 1);
1114
 
  // Calculate the entry point.
1115
 
  __ addiu(t9, v0, Code::kHeaderSize - kHeapObjectTag);
1116
 
 
1117
 
  // Restore call kind information.
1118
 
  __ pop(t1);
1119
 
  // Restore saved function.
1120
 
  __ pop(a1);
1121
 
 
1122
 
  // Tear down temporary frame.
1123
 
  __ LeaveInternalFrame();
 
1201
  {
 
1202
    FrameScope scope(masm, StackFrame::INTERNAL);
 
1203
 
 
1204
    // Preserve the function.
 
1205
    __ push(a1);
 
1206
    // Push call kind information.
 
1207
    __ push(t1);
 
1208
 
 
1209
    // Push the function on the stack as the argument to the runtime function.
 
1210
    __ push(a1);
 
1211
    // Call the runtime function.
 
1212
    __ CallRuntime(Runtime::kLazyCompile, 1);
 
1213
    // Calculate the entry point.
 
1214
    __ addiu(t9, v0, Code::kHeaderSize - kHeapObjectTag);
 
1215
 
 
1216
    // Restore call kind information.
 
1217
    __ pop(t1);
 
1218
    // Restore saved function.
 
1219
    __ pop(a1);
 
1220
 
 
1221
    // Tear down temporary frame.
 
1222
  }
1124
1223
 
1125
1224
  // Do a tail-call of the compiled function.
1126
1225
  __ Jump(t9);
1129
1228
 
1130
1229
void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
1131
1230
  // Enter an internal frame.
1132
 
  __ EnterInternalFrame();
1133
 
 
1134
 
  // Preserve the function.
1135
 
  __ push(a1);
1136
 
  // Push call kind information.
1137
 
  __ push(t1);
1138
 
 
1139
 
  // Push the function on the stack as the argument to the runtime function.
1140
 
  __ push(a1);
1141
 
  __ CallRuntime(Runtime::kLazyRecompile, 1);
1142
 
  // Calculate the entry point.
1143
 
  __ Addu(t9, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
1144
 
 
1145
 
  // Restore call kind information.
1146
 
  __ pop(t1);
1147
 
  // Restore saved function.
1148
 
  __ pop(a1);
1149
 
 
1150
 
  // Tear down temporary frame.
1151
 
  __ LeaveInternalFrame();
 
1231
  {
 
1232
    FrameScope scope(masm, StackFrame::INTERNAL);
 
1233
 
 
1234
    // Preserve the function.
 
1235
    __ push(a1);
 
1236
    // Push call kind information.
 
1237
    __ push(t1);
 
1238
 
 
1239
    // Push the function on the stack as the argument to the runtime function.
 
1240
    __ push(a1);
 
1241
    __ CallRuntime(Runtime::kLazyRecompile, 1);
 
1242
    // Calculate the entry point.
 
1243
    __ Addu(t9, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
 
1244
 
 
1245
    // Restore call kind information.
 
1246
    __ pop(t1);
 
1247
    // Restore saved function.
 
1248
    __ pop(a1);
 
1249
 
 
1250
    // Tear down temporary frame.
 
1251
  }
1152
1252
 
1153
1253
  // Do a tail-call of the compiled function.
1154
1254
  __ Jump(t9);
1155
1255
}
1156
1256
 
1157
1257
 
1158
 
// These functions are called from C++ but cannot be used in live code.
 
1258
static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
 
1259
                                             Deoptimizer::BailoutType type) {
 
1260
  {
 
1261
    FrameScope scope(masm, StackFrame::INTERNAL);
 
1262
    // Pass the function and deoptimization type to the runtime system.
 
1263
    __ li(a0, Operand(Smi::FromInt(static_cast<int>(type))));
 
1264
    __ push(a0);
 
1265
    __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
 
1266
  }
 
1267
 
 
1268
  // Get the full codegen state from the stack and untag it -> t2.
 
1269
  __ lw(t2, MemOperand(sp, 0 * kPointerSize));
 
1270
  __ SmiUntag(t2);
 
1271
  // Switch on the state.
 
1272
  Label with_tos_register, unknown_state;
 
1273
  __ Branch(&with_tos_register,
 
1274
            ne, t2, Operand(FullCodeGenerator::NO_REGISTERS));
 
1275
  __ Addu(sp, sp, Operand(1 * kPointerSize));  // Remove state.
 
1276
  __ Ret();
 
1277
 
 
1278
  __ bind(&with_tos_register);
 
1279
  __ lw(v0, MemOperand(sp, 1 * kPointerSize));
 
1280
  __ Branch(&unknown_state, ne, t2, Operand(FullCodeGenerator::TOS_REG));
 
1281
 
 
1282
  __ Addu(sp, sp, Operand(2 * kPointerSize));  // Remove state.
 
1283
  __ Ret();
 
1284
 
 
1285
  __ bind(&unknown_state);
 
1286
  __ stop("no cases left");
 
1287
}
 
1288
 
 
1289
 
1159
1290
void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
1160
 
  __ Abort("Call to unimplemented function in builtins-mips.cc");
 
1291
  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
1161
1292
}
1162
1293
 
1163
1294
 
1164
1295
void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
1165
 
  __ Abort("Call to unimplemented function in builtins-mips.cc");
 
1296
  Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
1166
1297
}
1167
1298
 
1168
1299
 
1169
1300
void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
1170
 
  __ Abort("Call to unimplemented function in builtins-mips.cc");
 
1301
  // For now, we are relying on the fact that Runtime::NotifyOSR
 
1302
  // doesn't do any garbage collection which allows us to save/restore
 
1303
  // the registers without worrying about which of them contain
 
1304
  // pointers. This seems a bit fragile.
 
1305
  RegList saved_regs =
 
1306
      (kJSCallerSaved | kCalleeSaved | ra.bit() | fp.bit()) & ~sp.bit();
 
1307
  __ MultiPush(saved_regs);
 
1308
  {
 
1309
    FrameScope scope(masm, StackFrame::INTERNAL);
 
1310
    __ CallRuntime(Runtime::kNotifyOSR, 0);
 
1311
  }
 
1312
  __ MultiPop(saved_regs);
 
1313
  __ Ret();
1171
1314
}
1172
1315
 
1173
1316
 
1174
1317
void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1175
 
  __ Abort("Call to unimplemented function in builtins-mips.cc");
 
1318
  CpuFeatures::TryForceFeatureScope scope(VFP3);
 
1319
  if (!CpuFeatures::IsSupported(FPU)) {
 
1320
    __ Abort("Unreachable code: Cannot optimize without FPU support.");
 
1321
    return;
 
1322
  }
 
1323
 
 
1324
  // Lookup the function in the JavaScript frame and push it as an
 
1325
  // argument to the on-stack replacement function.
 
1326
  __ lw(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
 
1327
  {
 
1328
    FrameScope scope(masm, StackFrame::INTERNAL);
 
1329
    __ push(a0);
 
1330
    __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
 
1331
  }
 
1332
 
 
1333
  // If the result was -1 it means that we couldn't optimize the
 
1334
  // function. Just return and continue in the unoptimized version.
 
1335
  __ Ret(eq, v0, Operand(Smi::FromInt(-1)));
 
1336
 
 
1337
  // Untag the AST id and push it on the stack.
 
1338
  __ SmiUntag(v0);
 
1339
  __ push(v0);
 
1340
 
 
1341
  // Generate the code for doing the frame-to-frame translation using
 
1342
  // the deoptimizer infrastructure.
 
1343
  Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR);
 
1344
  generator.Generate();
1176
1345
}
1177
1346
 
1178
1347
 
1190
1359
  // 2. Get the function to call (passed as receiver) from the stack, check
1191
1360
  //    if it is a function.
1192
1361
  // a0: actual number of arguments
1193
 
  Label non_function;
 
1362
  Label slow, non_function;
1194
1363
  __ sll(at, a0, kPointerSizeLog2);
1195
1364
  __ addu(at, sp, at);
1196
1365
  __ lw(a1, MemOperand(at));
1197
 
  __ And(at, a1, Operand(kSmiTagMask));
1198
 
  __ Branch(&non_function, eq, at, Operand(zero_reg));
 
1366
  __ JumpIfSmi(a1, &non_function);
1199
1367
  __ GetObjectType(a1, a2, a2);
1200
 
  __ Branch(&non_function, ne, a2, Operand(JS_FUNCTION_TYPE));
 
1368
  __ Branch(&slow, ne, a2, Operand(JS_FUNCTION_TYPE));
1201
1369
 
1202
1370
  // 3a. Patch the first argument if necessary when calling a function.
1203
1371
  // a0: actual number of arguments
1204
1372
  // a1: function
1205
1373
  Label shift_arguments;
 
1374
  __ li(t0, Operand(0, RelocInfo::NONE));  // Indicate regular JS_FUNCTION.
1206
1375
  { Label convert_to_object, use_global_receiver, patch_receiver;
1207
1376
    // Change context eagerly in case we need the global receiver.
1208
1377
    __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
1210
1379
    // Do not transform the receiver for strict mode functions.
1211
1380
    __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
1212
1381
    __ lw(a3, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset));
1213
 
    __ And(t0, a3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
 
1382
    __ And(t3, a3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1214
1383
                                 kSmiTagSize)));
1215
 
    __ Branch(&shift_arguments, ne, t0, Operand(zero_reg));
 
1384
    __ Branch(&shift_arguments, ne, t3, Operand(zero_reg));
1216
1385
 
1217
1386
    // Do not transform the receiver for native (Compilerhints already in a3).
1218
 
    __ And(t0, a3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1219
 
    __ Branch(&shift_arguments, ne, t0, Operand(zero_reg));
 
1387
    __ And(t3, a3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
 
1388
    __ Branch(&shift_arguments, ne, t3, Operand(zero_reg));
1220
1389
 
1221
1390
    // Compute the receiver in non-strict mode.
1222
1391
    // Load first argument in a2. a2 = -kPointerSize(sp + n_args << 2).
1238
1407
    __ Branch(&shift_arguments, ge, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
1239
1408
 
1240
1409
    __ bind(&convert_to_object);
1241
 
    __ EnterInternalFrame();  // In order to preserve argument count.
1242
 
    __ sll(a0, a0, kSmiTagSize);  // Smi tagged.
1243
 
    __ push(a0);
1244
 
 
1245
 
    __ push(a2);
1246
 
    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1247
 
    __ mov(a2, v0);
1248
 
 
1249
 
    __ pop(a0);
1250
 
    __ sra(a0, a0, kSmiTagSize);  // Un-tag.
1251
 
    __ LeaveInternalFrame();
1252
 
    // Restore the function to a1.
 
1410
    // Enter an internal frame in order to preserve argument count.
 
1411
    {
 
1412
      FrameScope scope(masm, StackFrame::INTERNAL);
 
1413
      __ sll(a0, a0, kSmiTagSize);  // Smi tagged.
 
1414
      __ push(a0);
 
1415
 
 
1416
      __ push(a2);
 
1417
      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
 
1418
      __ mov(a2, v0);
 
1419
 
 
1420
      __ pop(a0);
 
1421
      __ sra(a0, a0, kSmiTagSize);  // Un-tag.
 
1422
      // Leave internal frame.
 
1423
    }
 
1424
    // Restore the function to a1, and the flag to t0.
1253
1425
    __ sll(at, a0, kPointerSizeLog2);
1254
1426
    __ addu(at, sp, at);
1255
1427
    __ lw(a1, MemOperand(at));
 
1428
    __ li(t0, Operand(0, RelocInfo::NONE));
1256
1429
    __ Branch(&patch_receiver);
1257
1430
 
1258
1431
    // Use the global receiver object from the called function as the
1259
1432
    // receiver.
1260
1433
    __ bind(&use_global_receiver);
1261
1434
    const int kGlobalIndex =
1262
 
        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
 
1435
        Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
1263
1436
    __ lw(a2, FieldMemOperand(cp, kGlobalIndex));
1264
 
    __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalContextOffset));
 
1437
    __ lw(a2, FieldMemOperand(a2, GlobalObject::kNativeContextOffset));
1265
1438
    __ lw(a2, FieldMemOperand(a2, kGlobalIndex));
1266
1439
    __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset));
1267
1440
 
1273
1446
    __ Branch(&shift_arguments);
1274
1447
  }
1275
1448
 
1276
 
  // 3b. Patch the first argument when calling a non-function.  The
 
1449
  // 3b. Check for function proxy.
 
1450
  __ bind(&slow);
 
1451
  __ li(t0, Operand(1, RelocInfo::NONE));  // Indicate function proxy.
 
1452
  __ Branch(&shift_arguments, eq, a2, Operand(JS_FUNCTION_PROXY_TYPE));
 
1453
 
 
1454
  __ bind(&non_function);
 
1455
  __ li(t0, Operand(2, RelocInfo::NONE));  // Indicate non-function.
 
1456
 
 
1457
  // 3c. Patch the first argument when calling a non-function.  The
1277
1458
  //     CALL_NON_FUNCTION builtin expects the non-function callee as
1278
1459
  //     receiver, so overwrite the first argument which will ultimately
1279
1460
  //     become the receiver.
1280
1461
  // a0: actual number of arguments
1281
1462
  // a1: function
1282
 
  __ bind(&non_function);
1283
 
  // Restore the function in case it has been modified.
 
1463
  // t0: call type (0: JS function, 1: function proxy, 2: non-function)
1284
1464
  __ sll(at, a0, kPointerSizeLog2);
1285
1465
  __ addu(a2, sp, at);
1286
1466
  __ sw(a1, MemOperand(a2, -kPointerSize));
1287
 
  // Clear a1 to indicate a non-function being called.
1288
 
  __ mov(a1, zero_reg);
1289
1467
 
1290
1468
  // 4. Shift arguments and return address one slot down on the stack
1291
1469
  //    (overwriting the original receiver).  Adjust argument count to make
1292
1470
  //    the original first argument the new receiver.
1293
1471
  // a0: actual number of arguments
1294
1472
  // a1: function
 
1473
  // t0: call type (0: JS function, 1: function proxy, 2: non-function)
1295
1474
  __ bind(&shift_arguments);
1296
1475
  { Label loop;
1297
1476
    // Calculate the copy start address (destination). Copy end address is sp.
1309
1488
    __ Pop();
1310
1489
  }
1311
1490
 
1312
 
  // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin.
 
1491
  // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin,
 
1492
  //     or a function proxy via CALL_FUNCTION_PROXY.
1313
1493
  // a0: actual number of arguments
1314
1494
  // a1: function
1315
 
  { Label function;
1316
 
    __ Branch(&function, ne, a1, Operand(zero_reg));
1317
 
    __ mov(a2, zero_reg);  // expected arguments is 0 for CALL_NON_FUNCTION
 
1495
  // t0: call type (0: JS function, 1: function proxy, 2: non-function)
 
1496
  { Label function, non_proxy;
 
1497
    __ Branch(&function, eq, t0, Operand(zero_reg));
 
1498
    // Expected number of arguments is 0 for CALL_NON_FUNCTION.
 
1499
    __ mov(a2, zero_reg);
 
1500
    __ SetCallKind(t1, CALL_AS_METHOD);
 
1501
    __ Branch(&non_proxy, ne, t0, Operand(1));
 
1502
 
 
1503
    __ push(a1);  // Re-add proxy object as additional argument.
 
1504
    __ Addu(a0, a0, Operand(1));
 
1505
    __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY);
 
1506
    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
 
1507
            RelocInfo::CODE_TARGET);
 
1508
 
 
1509
    __ bind(&non_proxy);
1318
1510
    __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION);
1319
 
    __ SetCallKind(t1, CALL_AS_METHOD);
1320
1511
    __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
1321
1512
            RelocInfo::CODE_TARGET);
1322
1513
    __ bind(&function);
1350
1541
  const int kRecvOffset     =  3 * kPointerSize;
1351
1542
  const int kFunctionOffset =  4 * kPointerSize;
1352
1543
 
1353
 
  __ EnterInternalFrame();
1354
 
 
1355
 
  __ lw(a0, MemOperand(fp, kFunctionOffset));  // Get the function.
1356
 
  __ push(a0);
1357
 
  __ lw(a0, MemOperand(fp, kArgsOffset));  // Get the args array.
1358
 
  __ push(a0);
1359
 
  // Returns (in v0) number of arguments to copy to stack as Smi.
1360
 
  __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
1361
 
 
1362
 
  // Check the stack for overflow. We are not trying need to catch
1363
 
  // interruptions (e.g. debug break and preemption) here, so the "real stack
1364
 
  // limit" is checked.
1365
 
  Label okay;
1366
 
  __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
1367
 
  // Make a2 the space we have left. The stack might already be overflowed
1368
 
  // here which will cause a2 to become negative.
1369
 
  __ subu(a2, sp, a2);
1370
 
  // Check if the arguments will overflow the stack.
1371
 
  __ sll(t0, v0, kPointerSizeLog2 - kSmiTagSize);
1372
 
  __ Branch(&okay, gt, a2, Operand(t0));  // Signed comparison.
1373
 
 
1374
 
  // Out of stack space.
1375
 
  __ lw(a1, MemOperand(fp, kFunctionOffset));
1376
 
  __ push(a1);
1377
 
  __ push(v0);
1378
 
  __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
1379
 
  // End of stack check.
1380
 
 
1381
 
  // Push current limit and index.
1382
 
  __ bind(&okay);
1383
 
  __ push(v0);  // Limit.
1384
 
  __ mov(a1, zero_reg);  // Initial index.
1385
 
  __ push(a1);
1386
 
 
1387
 
  // Change context eagerly to get the right global object if necessary.
1388
 
  __ lw(a0, MemOperand(fp, kFunctionOffset));
1389
 
  __ lw(cp, FieldMemOperand(a0, JSFunction::kContextOffset));
1390
 
  // Load the shared function info while the function is still in a0.
1391
 
  __ lw(a1, FieldMemOperand(a0, JSFunction::kSharedFunctionInfoOffset));
1392
 
 
1393
 
  // Compute the receiver.
1394
 
  Label call_to_object, use_global_receiver, push_receiver;
1395
 
  __ lw(a0, MemOperand(fp, kRecvOffset));
1396
 
 
1397
 
  // Do not transform the receiver for strict mode functions.
1398
 
  __ lw(a2, FieldMemOperand(a1, SharedFunctionInfo::kCompilerHintsOffset));
1399
 
  __ And(t0, a2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
1400
 
                               kSmiTagSize)));
1401
 
  __ Branch(&push_receiver, ne, t0, Operand(zero_reg));
1402
 
 
1403
 
  // Do not transform the receiver for native (Compilerhints already in a2).
1404
 
  __ And(t0, a2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
1405
 
  __ Branch(&push_receiver, ne, t0, Operand(zero_reg));
1406
 
 
1407
 
  // Compute the receiver in non-strict mode.
1408
 
  __ And(t0, a0, Operand(kSmiTagMask));
1409
 
  __ Branch(&call_to_object, eq, t0, Operand(zero_reg));
1410
 
  __ LoadRoot(a1, Heap::kNullValueRootIndex);
1411
 
  __ Branch(&use_global_receiver, eq, a0, Operand(a1));
1412
 
  __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
1413
 
  __ Branch(&use_global_receiver, eq, a0, Operand(a2));
1414
 
 
1415
 
  // Check if the receiver is already a JavaScript object.
1416
 
  // a0: receiver
1417
 
  STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
1418
 
  __ GetObjectType(a0, a1, a1);
1419
 
  __ Branch(&push_receiver, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
1420
 
 
1421
 
  // Convert the receiver to a regular object.
1422
 
  // a0: receiver
1423
 
  __ bind(&call_to_object);
1424
 
  __ push(a0);
1425
 
  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1426
 
  __ mov(a0, v0);  // Put object in a0 to match other paths to push_receiver.
1427
 
  __ Branch(&push_receiver);
1428
 
 
1429
 
  // Use the current global receiver object as the receiver.
1430
 
  __ bind(&use_global_receiver);
1431
 
  const int kGlobalOffset =
1432
 
      Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1433
 
  __ lw(a0, FieldMemOperand(cp, kGlobalOffset));
1434
 
  __ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalContextOffset));
1435
 
  __ lw(a0, FieldMemOperand(a0, kGlobalOffset));
1436
 
  __ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset));
1437
 
 
1438
 
  // Push the receiver.
1439
 
  // a0: receiver
1440
 
  __ bind(&push_receiver);
1441
 
  __ push(a0);
1442
 
 
1443
 
  // Copy all arguments from the array to the stack.
1444
 
  Label entry, loop;
1445
 
  __ lw(a0, MemOperand(fp, kIndexOffset));
1446
 
  __ Branch(&entry);
1447
 
 
1448
 
  // Load the current argument from the arguments array and push it to the
1449
 
  // stack.
1450
 
  // a0: current argument index
1451
 
  __ bind(&loop);
1452
 
  __ lw(a1, MemOperand(fp, kArgsOffset));
1453
 
  __ push(a1);
1454
 
  __ push(a0);
1455
 
 
1456
 
  // Call the runtime to access the property in the arguments array.
1457
 
  __ CallRuntime(Runtime::kGetProperty, 2);
1458
 
  __ push(v0);
1459
 
 
1460
 
  // Use inline caching to access the arguments.
1461
 
  __ lw(a0, MemOperand(fp, kIndexOffset));
1462
 
  __ Addu(a0, a0, Operand(1 << kSmiTagSize));
1463
 
  __ sw(a0, MemOperand(fp, kIndexOffset));
1464
 
 
1465
 
  // Test if the copy loop has finished copying all the elements from the
1466
 
  // arguments object.
1467
 
  __ bind(&entry);
1468
 
  __ lw(a1, MemOperand(fp, kLimitOffset));
1469
 
  __ Branch(&loop, ne, a0, Operand(a1));
1470
 
  // Invoke the function.
1471
 
  ParameterCount actual(a0);
1472
 
  __ sra(a0, a0, kSmiTagSize);
1473
 
  __ lw(a1, MemOperand(fp, kFunctionOffset));
1474
 
  __ InvokeFunction(a1, actual, CALL_FUNCTION,
1475
 
                    NullCallWrapper(), CALL_AS_METHOD);
1476
 
 
1477
 
  // Tear down the internal frame and remove function, receiver and args.
1478
 
  __ LeaveInternalFrame();
1479
 
  __ Addu(sp, sp, Operand(3 * kPointerSize));
1480
 
  __ Ret();
 
1544
  {
 
1545
    FrameScope frame_scope(masm, StackFrame::INTERNAL);
 
1546
    __ lw(a0, MemOperand(fp, kFunctionOffset));  // Get the function.
 
1547
    __ push(a0);
 
1548
    __ lw(a0, MemOperand(fp, kArgsOffset));  // Get the args array.
 
1549
    __ push(a0);
 
1550
    // Returns (in v0) number of arguments to copy to stack as Smi.
 
1551
    __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);
 
1552
 
 
1553
    // Check the stack for overflow. We are not trying to catch
 
1554
    // interruptions (e.g. debug break and preemption) here, so the "real stack
 
1555
    // limit" is checked.
 
1556
    Label okay;
 
1557
    __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
 
1558
    // Make a2 the space we have left. The stack might already be overflowed
 
1559
    // here which will cause a2 to become negative.
 
1560
    __ subu(a2, sp, a2);
 
1561
    // Check if the arguments will overflow the stack.
 
1562
    __ sll(t3, v0, kPointerSizeLog2 - kSmiTagSize);
 
1563
    __ Branch(&okay, gt, a2, Operand(t3));  // Signed comparison.
 
1564
 
 
1565
    // Out of stack space.
 
1566
    __ lw(a1, MemOperand(fp, kFunctionOffset));
 
1567
    __ push(a1);
 
1568
    __ push(v0);
 
1569
    __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);
 
1570
    // End of stack check.
 
1571
 
 
1572
    // Push current limit and index.
 
1573
    __ bind(&okay);
 
1574
    __ push(v0);  // Limit.
 
1575
    __ mov(a1, zero_reg);  // Initial index.
 
1576
    __ push(a1);
 
1577
 
 
1578
    // Get the receiver.
 
1579
    __ lw(a0, MemOperand(fp, kRecvOffset));
 
1580
 
 
1581
    // Check that the function is a JS function (otherwise it must be a proxy).
 
1582
    Label push_receiver;
 
1583
    __ lw(a1, MemOperand(fp, kFunctionOffset));
 
1584
    __ GetObjectType(a1, a2, a2);
 
1585
    __ Branch(&push_receiver, ne, a2, Operand(JS_FUNCTION_TYPE));
 
1586
 
 
1587
    // Change context eagerly to get the right global object if necessary.
 
1588
    __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
 
1589
    // Load the shared function info while the function is still in a1.
 
1590
    __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
 
1591
 
 
1592
    // Compute the receiver.
 
1593
    // Do not transform the receiver for strict mode functions.
 
1594
    Label call_to_object, use_global_receiver;
 
1595
    __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset));
 
1596
    __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
 
1597
                                 kSmiTagSize)));
 
1598
    __ Branch(&push_receiver, ne, t3, Operand(zero_reg));
 
1599
 
 
1600
    // Do not transform the receiver for native (Compilerhints already in a2).
 
1601
    __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
 
1602
    __ Branch(&push_receiver, ne, t3, Operand(zero_reg));
 
1603
 
 
1604
    // Compute the receiver in non-strict mode.
 
1605
    __ JumpIfSmi(a0, &call_to_object);
 
1606
    __ LoadRoot(a1, Heap::kNullValueRootIndex);
 
1607
    __ Branch(&use_global_receiver, eq, a0, Operand(a1));
 
1608
    __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
 
1609
    __ Branch(&use_global_receiver, eq, a0, Operand(a2));
 
1610
 
 
1611
    // Check if the receiver is already a JavaScript object.
 
1612
    // a0: receiver
 
1613
    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
 
1614
    __ GetObjectType(a0, a1, a1);
 
1615
    __ Branch(&push_receiver, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
 
1616
 
 
1617
    // Convert the receiver to a regular object.
 
1618
    // a0: receiver
 
1619
    __ bind(&call_to_object);
 
1620
    __ push(a0);
 
1621
    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
 
1622
    __ mov(a0, v0);  // Put object in a0 to match other paths to push_receiver.
 
1623
    __ Branch(&push_receiver);
 
1624
 
 
1625
    // Use the current global receiver object as the receiver.
 
1626
    __ bind(&use_global_receiver);
 
1627
    const int kGlobalOffset =
 
1628
        Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize;
 
1629
    __ lw(a0, FieldMemOperand(cp, kGlobalOffset));
 
1630
    __ lw(a0, FieldMemOperand(a0, GlobalObject::kNativeContextOffset));
 
1631
    __ lw(a0, FieldMemOperand(a0, kGlobalOffset));
 
1632
    __ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset));
 
1633
 
 
1634
    // Push the receiver.
 
1635
    // a0: receiver
 
1636
    __ bind(&push_receiver);
 
1637
    __ push(a0);
 
1638
 
 
1639
    // Copy all arguments from the array to the stack.
 
1640
    Label entry, loop;
 
1641
    __ lw(a0, MemOperand(fp, kIndexOffset));
 
1642
    __ Branch(&entry);
 
1643
 
 
1644
    // Load the current argument from the arguments array and push it to the
 
1645
    // stack.
 
1646
    // a0: current argument index
 
1647
    __ bind(&loop);
 
1648
    __ lw(a1, MemOperand(fp, kArgsOffset));
 
1649
    __ push(a1);
 
1650
    __ push(a0);
 
1651
 
 
1652
    // Call the runtime to access the property in the arguments array.
 
1653
    __ CallRuntime(Runtime::kGetProperty, 2);
 
1654
    __ push(v0);
 
1655
 
 
1656
    // Use inline caching to access the arguments.
 
1657
    __ lw(a0, MemOperand(fp, kIndexOffset));
 
1658
    __ Addu(a0, a0, Operand(1 << kSmiTagSize));
 
1659
    __ sw(a0, MemOperand(fp, kIndexOffset));
 
1660
 
 
1661
    // Test if the copy loop has finished copying all the elements from the
 
1662
    // arguments object.
 
1663
    __ bind(&entry);
 
1664
    __ lw(a1, MemOperand(fp, kLimitOffset));
 
1665
    __ Branch(&loop, ne, a0, Operand(a1));
 
1666
 
 
1667
    // Invoke the function.
 
1668
    Label call_proxy;
 
1669
    ParameterCount actual(a0);
 
1670
    __ sra(a0, a0, kSmiTagSize);
 
1671
    __ lw(a1, MemOperand(fp, kFunctionOffset));
 
1672
    __ GetObjectType(a1, a2, a2);
 
1673
    __ Branch(&call_proxy, ne, a2, Operand(JS_FUNCTION_TYPE));
 
1674
 
 
1675
    __ InvokeFunction(a1, actual, CALL_FUNCTION,
 
1676
                      NullCallWrapper(), CALL_AS_METHOD);
 
1677
 
 
1678
    frame_scope.GenerateLeaveFrame();
 
1679
    __ Ret(USE_DELAY_SLOT);
 
1680
    __ Addu(sp, sp, Operand(3 * kPointerSize));  // In delay slot.
 
1681
 
 
1682
    // Invoke the function proxy.
 
1683
    __ bind(&call_proxy);
 
1684
    __ push(a1);  // Add function proxy as last argument.
 
1685
    __ Addu(a0, a0, Operand(1));
 
1686
    __ li(a2, Operand(0, RelocInfo::NONE));
 
1687
    __ SetCallKind(t1, CALL_AS_METHOD);
 
1688
    __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY);
 
1689
    __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
 
1690
            RelocInfo::CODE_TARGET);
 
1691
    // Tear down the internal frame and remove function, receiver and args.
 
1692
  }
 
1693
 
 
1694
  __ Ret(USE_DELAY_SLOT);
 
1695
  __ Addu(sp, sp, Operand(3 * kPointerSize));  // In delay slot.
1481
1696
}
1482
1697
 
1483
1698
 
1560
1775
    __ bind(&too_few);
1561
1776
    EnterArgumentsAdaptorFrame(masm);
1562
1777
 
1563
 
    // TODO(MIPS): Optimize these loops.
1564
 
 
1565
1778
    // Calculate copy start address into a0 and copy end address is fp.
1566
1779
    // a0: actual number of arguments as a smi
1567
1780
    // a1: function
1583
1796
    Label copy;
1584
1797
    __ bind(&copy);
1585
1798
    __ lw(t0, MemOperand(a0));  // Adjusted above for return addr and receiver.
1586
 
    __ push(t0);
 
1799
    __ Subu(sp, sp, kPointerSize);
1587
1800
    __ Subu(a0, a0, kPointerSize);
1588
 
    __ Branch(&copy, ne, a0, Operand(t3));
 
1801
    __ Branch(USE_DELAY_SLOT, &copy, ne, a0, Operand(t3));
 
1802
    __ sw(t0, MemOperand(sp));  // In the delay slot.
1589
1803
 
1590
1804
    // Fill the remaining expected arguments with undefined.
1591
1805
    // a1: function
1598
1812
 
1599
1813
    Label fill;
1600
1814
    __ bind(&fill);
1601
 
    __ push(t0);
1602
 
    __ Branch(&fill, ne, sp, Operand(a2));
 
1815
    __ Subu(sp, sp, kPointerSize);
 
1816
    __ Branch(USE_DELAY_SLOT, &fill, ne, sp, Operand(a2));
 
1817
    __ sw(t0, MemOperand(sp));
1603
1818
  }
1604
1819
 
1605
1820
  // Call the entry point.
1607
1822
 
1608
1823
  __ Call(a3);
1609
1824
 
 
1825
  // Store offset of return address for deoptimizer.
 
1826
  masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
 
1827
 
1610
1828
  // Exit frame and return.
1611
1829
  LeaveArgumentsAdaptorFrame(masm);
1612
1830
  __ Ret();