mips: Fix the global compare routines for mips
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / src / mips / code-stubs-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 #include "v8.h"
29
30 #if defined(V8_TARGET_ARCH_MIPS)
31
32 #include "bootstrapper.h"
33 #include "code-stubs.h"
34 #include "codegen.h"
35 #include "regexp-macro-assembler.h"
36
37 namespace v8 {
38 namespace internal {
39
40
41 #define __ ACCESS_MASM(masm)
42
43 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
44                                           Label* slow,
45                                           Condition cc,
46                                           bool never_nan_nan);
47 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
48                                     Register lhs,
49                                     Register rhs,
50                                     Label* rhs_not_nan,
51                                     Label* slow,
52                                     bool strict);
53 static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc);
54 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
55                                            Register lhs,
56                                            Register rhs);
57
58
59 // Check if the operand is a heap number.
60 static void EmitCheckForHeapNumber(MacroAssembler* masm, Register operand,
61                                    Register scratch1, Register scratch2,
62                                    Label* not_a_heap_number) {
63   __ lw(scratch1, FieldMemOperand(operand, HeapObject::kMapOffset));
64   __ LoadRoot(scratch2, Heap::kHeapNumberMapRootIndex);
65   __ Branch(not_a_heap_number, ne, scratch1, Operand(scratch2));
66 }
67
68
69 void ToNumberStub::Generate(MacroAssembler* masm) {
70   // The ToNumber stub takes one argument in a0.
71   Label check_heap_number, call_builtin;
72   __ JumpIfNotSmi(a0, &check_heap_number);
73   __ Ret(USE_DELAY_SLOT);
74   __ mov(v0, a0);
75
76   __ bind(&check_heap_number);
77   EmitCheckForHeapNumber(masm, a0, a1, t0, &call_builtin);
78   __ Ret(USE_DELAY_SLOT);
79   __ mov(v0, a0);
80
81   __ bind(&call_builtin);
82   __ push(a0);
83   __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
84 }
85
86
87 void FastNewClosureStub::Generate(MacroAssembler* masm) {
88   // Create a new closure from the given function info in new
89   // space. Set the context to the current context in cp.
90   Label gc;
91
92   // Pop the function info from the stack.
93   __ pop(a3);
94
95   // Attempt to allocate new JSFunction in new space.
96   __ AllocateInNewSpace(JSFunction::kSize,
97                         v0,
98                         a1,
99                         a2,
100                         &gc,
101                         TAG_OBJECT);
102
103   int map_index = (language_mode_ == CLASSIC_MODE)
104       ? Context::FUNCTION_MAP_INDEX
105       : Context::STRICT_MODE_FUNCTION_MAP_INDEX;
106
107   // Compute the function map in the current global context and set that
108   // as the map of the allocated object.
109   __ lw(a2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
110   __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalContextOffset));
111   __ lw(a2, MemOperand(a2, Context::SlotOffset(map_index)));
112   __ sw(a2, FieldMemOperand(v0, HeapObject::kMapOffset));
113
114   // Initialize the rest of the function. We don't have to update the
115   // write barrier because the allocated object is in new space.
116   __ LoadRoot(a1, Heap::kEmptyFixedArrayRootIndex);
117   __ LoadRoot(a2, Heap::kTheHoleValueRootIndex);
118   __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
119   __ sw(a1, FieldMemOperand(v0, JSObject::kPropertiesOffset));
120   __ sw(a1, FieldMemOperand(v0, JSObject::kElementsOffset));
121   __ sw(a2, FieldMemOperand(v0, JSFunction::kPrototypeOrInitialMapOffset));
122   __ sw(a3, FieldMemOperand(v0, JSFunction::kSharedFunctionInfoOffset));
123   __ sw(cp, FieldMemOperand(v0, JSFunction::kContextOffset));
124   __ sw(a1, FieldMemOperand(v0, JSFunction::kLiteralsOffset));
125   __ sw(t0, FieldMemOperand(v0, JSFunction::kNextFunctionLinkOffset));
126
127   // Initialize the code pointer in the function to be the one
128   // found in the shared function info object.
129   __ lw(a3, FieldMemOperand(a3, SharedFunctionInfo::kCodeOffset));
130   __ Addu(a3, a3, Operand(Code::kHeaderSize - kHeapObjectTag));
131
132   // Return result. The argument function info has been popped already.
133   __ sw(a3, FieldMemOperand(v0, JSFunction::kCodeEntryOffset));
134   __ Ret();
135
136   // Create a new closure through the slower runtime call.
137   __ bind(&gc);
138   __ LoadRoot(t0, Heap::kFalseValueRootIndex);
139   __ Push(cp, a3, t0);
140   __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
141 }
142
143
144 void FastNewContextStub::Generate(MacroAssembler* masm) {
145   // Try to allocate the context in new space.
146   Label gc;
147   int length = slots_ + Context::MIN_CONTEXT_SLOTS;
148
149   // Attempt to allocate the context in new space.
150   __ AllocateInNewSpace(FixedArray::SizeFor(length),
151                         v0,
152                         a1,
153                         a2,
154                         &gc,
155                         TAG_OBJECT);
156
157   // Load the function from the stack.
158   __ lw(a3, MemOperand(sp, 0));
159
160   // Set up the object header.
161   __ LoadRoot(a1, Heap::kFunctionContextMapRootIndex);
162   __ li(a2, Operand(Smi::FromInt(length)));
163   __ sw(a2, FieldMemOperand(v0, FixedArray::kLengthOffset));
164   __ sw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
165
166   // Set up the fixed slots, copy the global object from the previous context.
167   __ lw(a2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
168   __ li(a1, Operand(Smi::FromInt(0)));
169   __ sw(a3, MemOperand(v0, Context::SlotOffset(Context::CLOSURE_INDEX)));
170   __ sw(cp, MemOperand(v0, Context::SlotOffset(Context::PREVIOUS_INDEX)));
171   __ sw(a1, MemOperand(v0, Context::SlotOffset(Context::EXTENSION_INDEX)));
172   __ sw(a2, MemOperand(v0, Context::SlotOffset(Context::GLOBAL_INDEX)));
173
174   // Copy the qml global object from the surrounding context.
175   __ lw(a1, MemOperand(cp, Context::SlotOffset(Context::QML_GLOBAL_INDEX)));
176   __ sw(a1, MemOperand(v0, Context::SlotOffset(Context::QML_GLOBAL_INDEX)));
177
178
179   // Initialize the rest of the slots to undefined.
180   __ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
181   for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
182     __ sw(a1, MemOperand(v0, Context::SlotOffset(i)));
183   }
184
185   // Remove the on-stack argument and return.
186   __ mov(cp, v0);
187   __ DropAndRet(1);
188
189   // Need to collect. Call into runtime system.
190   __ bind(&gc);
191   __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
192 }
193
194
195 void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
196   // Stack layout on entry:
197   //
198   // [sp]: function.
199   // [sp + kPointerSize]: serialized scope info
200
201   // Try to allocate the context in new space.
202   Label gc;
203   int length = slots_ + Context::MIN_CONTEXT_SLOTS;
204   __ AllocateInNewSpace(FixedArray::SizeFor(length),
205                         v0, a1, a2, &gc, TAG_OBJECT);
206
207   // Load the function from the stack.
208   __ lw(a3, MemOperand(sp, 0));
209
210   // Load the serialized scope info from the stack.
211   __ lw(a1, MemOperand(sp, 1 * kPointerSize));
212
213   // Set up the object header.
214   __ LoadRoot(a2, Heap::kBlockContextMapRootIndex);
215   __ sw(a2, FieldMemOperand(v0, HeapObject::kMapOffset));
216   __ li(a2, Operand(Smi::FromInt(length)));
217   __ sw(a2, FieldMemOperand(v0, FixedArray::kLengthOffset));
218
219   // If this block context is nested in the global context we get a smi
220   // sentinel instead of a function. The block context should get the
221   // canonical empty function of the global context as its closure which
222   // we still have to look up.
223   Label after_sentinel;
224   __ JumpIfNotSmi(a3, &after_sentinel);
225   if (FLAG_debug_code) {
226     const char* message = "Expected 0 as a Smi sentinel";
227     __ Assert(eq, message, a3, Operand(zero_reg));
228   }
229   __ lw(a3, GlobalObjectOperand());
230   __ lw(a3, FieldMemOperand(a3, GlobalObject::kGlobalContextOffset));
231   __ lw(a3, ContextOperand(a3, Context::CLOSURE_INDEX));
232   __ bind(&after_sentinel);
233
234   // Set up the fixed slots, copy the global object from the previous context.
235   __ lw(a2, ContextOperand(cp, Context::GLOBAL_INDEX));
236   __ sw(a3, ContextOperand(v0, Context::CLOSURE_INDEX));
237   __ sw(cp, ContextOperand(v0, Context::PREVIOUS_INDEX));
238   __ sw(a1, ContextOperand(v0, Context::EXTENSION_INDEX));
239   __ sw(a2, ContextOperand(v0, Context::GLOBAL_INDEX));
240
241   // Copy the qml global object from the surrounding context.
242   __ lw(a1, ContextOperand(cp, Context::QML_GLOBAL_INDEX));
243   __ sw(a1, ContextOperand(v0, Context::QML_GLOBAL_INDEX));
244
245   // Initialize the rest of the slots to the hole value.
246   __ LoadRoot(a1, Heap::kTheHoleValueRootIndex);
247   for (int i = 0; i < slots_; i++) {
248     __ sw(a1, ContextOperand(v0, i + Context::MIN_CONTEXT_SLOTS));
249   }
250
251   // Remove the on-stack argument and return.
252   __ mov(cp, v0);
253   __ DropAndRet(2);
254
255   // Need to collect. Call into runtime system.
256   __ bind(&gc);
257   __ TailCallRuntime(Runtime::kPushBlockContext, 2, 1);
258 }
259
260
261 static void GenerateFastCloneShallowArrayCommon(
262     MacroAssembler* masm,
263     int length,
264     FastCloneShallowArrayStub::Mode mode,
265     Label* fail) {
266   // Registers on entry:
267   // a3: boilerplate literal array.
268   ASSERT(mode != FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS);
269
270   // All sizes here are multiples of kPointerSize.
271   int elements_size = 0;
272   if (length > 0) {
273     elements_size = mode == FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
274         ? FixedDoubleArray::SizeFor(length)
275         : FixedArray::SizeFor(length);
276   }
277   int size = JSArray::kSize + elements_size;
278
279   // Allocate both the JS array and the elements array in one big
280   // allocation. This avoids multiple limit checks.
281   __ AllocateInNewSpace(size,
282                         v0,
283                         a1,
284                         a2,
285                         fail,
286                         TAG_OBJECT);
287
288   // Copy the JS array part.
289   for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
290     if ((i != JSArray::kElementsOffset) || (length == 0)) {
291       __ lw(a1, FieldMemOperand(a3, i));
292       __ sw(a1, FieldMemOperand(v0, i));
293     }
294   }
295
296   if (length > 0) {
297     // Get hold of the elements array of the boilerplate and setup the
298     // elements pointer in the resulting object.
299     __ lw(a3, FieldMemOperand(a3, JSArray::kElementsOffset));
300     __ Addu(a2, v0, Operand(JSArray::kSize));
301     __ sw(a2, FieldMemOperand(v0, JSArray::kElementsOffset));
302
303     // Copy the elements array.
304     ASSERT((elements_size % kPointerSize) == 0);
305     __ CopyFields(a2, a3, a1.bit(), elements_size / kPointerSize);
306   }
307 }
308
309 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
310   // Stack layout on entry:
311   //
312   // [sp]: constant elements.
313   // [sp + kPointerSize]: literal index.
314   // [sp + (2 * kPointerSize)]: literals array.
315
316   // Load boilerplate object into r3 and check if we need to create a
317   // boilerplate.
318   Label slow_case;
319   __ lw(a3, MemOperand(sp, 2 * kPointerSize));
320   __ lw(a0, MemOperand(sp, 1 * kPointerSize));
321   __ Addu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
322   __ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize);
323   __ Addu(t0, a3, t0);
324   __ lw(a3, MemOperand(t0));
325   __ LoadRoot(t1, Heap::kUndefinedValueRootIndex);
326   __ Branch(&slow_case, eq, a3, Operand(t1));
327
328   FastCloneShallowArrayStub::Mode mode = mode_;
329   if (mode == CLONE_ANY_ELEMENTS) {
330     Label double_elements, check_fast_elements;
331     __ lw(v0, FieldMemOperand(a3, JSArray::kElementsOffset));
332     __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
333     __ LoadRoot(t1, Heap::kFixedCOWArrayMapRootIndex);
334     __ Branch(&check_fast_elements, ne, v0, Operand(t1));
335     GenerateFastCloneShallowArrayCommon(masm, 0,
336                                         COPY_ON_WRITE_ELEMENTS, &slow_case);
337     // Return and remove the on-stack parameters.
338     __ DropAndRet(3);
339
340     __ bind(&check_fast_elements);
341     __ LoadRoot(t1, Heap::kFixedArrayMapRootIndex);
342     __ Branch(&double_elements, ne, v0, Operand(t1));
343     GenerateFastCloneShallowArrayCommon(masm, length_,
344                                         CLONE_ELEMENTS, &slow_case);
345     // Return and remove the on-stack parameters.
346     __ DropAndRet(3);
347
348     __ bind(&double_elements);
349     mode = CLONE_DOUBLE_ELEMENTS;
350     // Fall through to generate the code to handle double elements.
351   }
352
353   if (FLAG_debug_code) {
354     const char* message;
355     Heap::RootListIndex expected_map_index;
356     if (mode == CLONE_ELEMENTS) {
357       message = "Expected (writable) fixed array";
358       expected_map_index = Heap::kFixedArrayMapRootIndex;
359     } else if (mode == CLONE_DOUBLE_ELEMENTS) {
360       message = "Expected (writable) fixed double array";
361       expected_map_index = Heap::kFixedDoubleArrayMapRootIndex;
362     } else {
363       ASSERT(mode == COPY_ON_WRITE_ELEMENTS);
364       message = "Expected copy-on-write fixed array";
365       expected_map_index = Heap::kFixedCOWArrayMapRootIndex;
366     }
367     __ push(a3);
368     __ lw(a3, FieldMemOperand(a3, JSArray::kElementsOffset));
369     __ lw(a3, FieldMemOperand(a3, HeapObject::kMapOffset));
370     __ LoadRoot(at, expected_map_index);
371     __ Assert(eq, message, a3, Operand(at));
372     __ pop(a3);
373   }
374
375   GenerateFastCloneShallowArrayCommon(masm, length_, mode, &slow_case);
376
377   // Return and remove the on-stack parameters.
378   __ DropAndRet(3);
379
380   __ bind(&slow_case);
381   __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
382 }
383
384
385 void FastCloneShallowObjectStub::Generate(MacroAssembler* masm) {
386   // Stack layout on entry:
387   //
388   // [sp]: object literal flags.
389   // [sp + kPointerSize]: constant properties.
390   // [sp + (2 * kPointerSize)]: literal index.
391   // [sp + (3 * kPointerSize)]: literals array.
392
393   // Load boilerplate object into a3 and check if we need to create a
394   // boilerplate.
395   Label slow_case;
396   __ lw(a3, MemOperand(sp, 3 * kPointerSize));
397   __ lw(a0, MemOperand(sp, 2 * kPointerSize));
398   __ Addu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
399   __ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize);
400   __ Addu(a3, t0, a3);
401   __ lw(a3, MemOperand(a3));
402   __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
403   __ Branch(&slow_case, eq, a3, Operand(t0));
404
405   // Check that the boilerplate contains only fast properties and we can
406   // statically determine the instance size.
407   int size = JSObject::kHeaderSize + length_ * kPointerSize;
408   __ lw(a0, FieldMemOperand(a3, HeapObject::kMapOffset));
409   __ lbu(a0, FieldMemOperand(a0, Map::kInstanceSizeOffset));
410   __ Branch(&slow_case, ne, a0, Operand(size >> kPointerSizeLog2));
411
412   // Allocate the JS object and copy header together with all in-object
413   // properties from the boilerplate.
414   __ AllocateInNewSpace(size, v0, a1, a2, &slow_case, TAG_OBJECT);
415   for (int i = 0; i < size; i += kPointerSize) {
416     __ lw(a1, FieldMemOperand(a3, i));
417     __ sw(a1, FieldMemOperand(v0, i));
418   }
419
420   // Return and remove the on-stack parameters.
421   __ DropAndRet(4);
422
423   __ bind(&slow_case);
424   __ TailCallRuntime(Runtime::kCreateObjectLiteralShallow, 4, 1);
425 }
426
427
428 // Takes a Smi and converts to an IEEE 64 bit floating point value in two
429 // registers.  The format is 1 sign bit, 11 exponent bits (biased 1023) and
430 // 52 fraction bits (20 in the first word, 32 in the second).  Zeros is a
431 // scratch register.  Destroys the source register.  No GC occurs during this
432 // stub so you don't have to set up the frame.
433 class ConvertToDoubleStub : public CodeStub {
434  public:
435   ConvertToDoubleStub(Register result_reg_1,
436                       Register result_reg_2,
437                       Register source_reg,
438                       Register scratch_reg)
439       : result1_(result_reg_1),
440         result2_(result_reg_2),
441         source_(source_reg),
442         zeros_(scratch_reg) { }
443
444  private:
445   Register result1_;
446   Register result2_;
447   Register source_;
448   Register zeros_;
449
450   // Minor key encoding in 16 bits.
451   class ModeBits: public BitField<OverwriteMode, 0, 2> {};
452   class OpBits: public BitField<Token::Value, 2, 14> {};
453
454   Major MajorKey() { return ConvertToDouble; }
455   int MinorKey() {
456     // Encode the parameters in a unique 16 bit value.
457     return  result1_.code() +
458            (result2_.code() << 4) +
459            (source_.code() << 8) +
460            (zeros_.code() << 12);
461   }
462
463   void Generate(MacroAssembler* masm);
464 };
465
466
467 void ConvertToDoubleStub::Generate(MacroAssembler* masm) {
468 #ifndef BIG_ENDIAN_FLOATING_POINT
469   Register exponent = result1_;
470   Register mantissa = result2_;
471 #else
472   Register exponent = result2_;
473   Register mantissa = result1_;
474 #endif
475   Label not_special;
476   // Convert from Smi to integer.
477   __ sra(source_, source_, kSmiTagSize);
478   // Move sign bit from source to destination.  This works because the sign bit
479   // in the exponent word of the double has the same position and polarity as
480   // the 2's complement sign bit in a Smi.
481   STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u);
482   __ And(exponent, source_, Operand(HeapNumber::kSignMask));
483   // Subtract from 0 if source was negative.
484   __ subu(at, zero_reg, source_);
485   __ Movn(source_, at, exponent);
486
487   // We have -1, 0 or 1, which we treat specially. Register source_ contains
488   // absolute value: it is either equal to 1 (special case of -1 and 1),
489   // greater than 1 (not a special case) or less than 1 (special case of 0).
490   __ Branch(&not_special, gt, source_, Operand(1));
491
492   // For 1 or -1 we need to or in the 0 exponent (biased to 1023).
493   const uint32_t exponent_word_for_1 =
494       HeapNumber::kExponentBias << HeapNumber::kExponentShift;
495   // Safe to use 'at' as dest reg here.
496   __ Or(at, exponent, Operand(exponent_word_for_1));
497   __ Movn(exponent, at, source_);  // Write exp when source not 0.
498   // 1, 0 and -1 all have 0 for the second word.
499   __ Ret(USE_DELAY_SLOT);
500   __ mov(mantissa, zero_reg);
501
502   __ bind(&not_special);
503   // Count leading zeros.
504   // Gets the wrong answer for 0, but we already checked for that case above.
505   __ Clz(zeros_, source_);
506   // Compute exponent and or it into the exponent register.
507   // We use mantissa as a scratch register here.
508   __ li(mantissa, Operand(31 + HeapNumber::kExponentBias));
509   __ subu(mantissa, mantissa, zeros_);
510   __ sll(mantissa, mantissa, HeapNumber::kExponentShift);
511   __ Or(exponent, exponent, mantissa);
512
513   // Shift up the source chopping the top bit off.
514   __ Addu(zeros_, zeros_, Operand(1));
515   // This wouldn't work for 1.0 or -1.0 as the shift would be 32 which means 0.
516   __ sllv(source_, source_, zeros_);
517   // Compute lower part of fraction (last 12 bits).
518   __ sll(mantissa, source_, HeapNumber::kMantissaBitsInTopWord);
519   // And the top (top 20 bits).
520   __ srl(source_, source_, 32 - HeapNumber::kMantissaBitsInTopWord);
521
522   __ Ret(USE_DELAY_SLOT);
523   __ or_(exponent, exponent, source_);
524 }
525
526
527 void FloatingPointHelper::LoadSmis(MacroAssembler* masm,
528                                    FloatingPointHelper::Destination destination,
529                                    Register scratch1,
530                                    Register scratch2) {
531   if (CpuFeatures::IsSupported(FPU)) {
532     CpuFeatures::Scope scope(FPU);
533     __ sra(scratch1, a0, kSmiTagSize);
534     __ mtc1(scratch1, f14);
535     __ cvt_d_w(f14, f14);
536     __ sra(scratch1, a1, kSmiTagSize);
537     __ mtc1(scratch1, f12);
538     __ cvt_d_w(f12, f12);
539     if (destination == kCoreRegisters) {
540       __ Move(a2, a3, f14);
541       __ Move(a0, a1, f12);
542     }
543   } else {
544     ASSERT(destination == kCoreRegisters);
545     // Write Smi from a0 to a3 and a2 in double format.
546     __ mov(scratch1, a0);
547     ConvertToDoubleStub stub1(a3, a2, scratch1, scratch2);
548     __ push(ra);
549     __ Call(stub1.GetCode());
550     // Write Smi from a1 to a1 and a0 in double format.
551     __ mov(scratch1, a1);
552     ConvertToDoubleStub stub2(a1, a0, scratch1, scratch2);
553     __ Call(stub2.GetCode());
554     __ pop(ra);
555   }
556 }
557
558
559 void FloatingPointHelper::LoadOperands(
560     MacroAssembler* masm,
561     FloatingPointHelper::Destination destination,
562     Register heap_number_map,
563     Register scratch1,
564     Register scratch2,
565     Label* slow) {
566
567   // Load right operand (a0) to f12 or a2/a3.
568   LoadNumber(masm, destination,
569              a0, f14, a2, a3, heap_number_map, scratch1, scratch2, slow);
570
571   // Load left operand (a1) to f14 or a0/a1.
572   LoadNumber(masm, destination,
573              a1, f12, a0, a1, heap_number_map, scratch1, scratch2, slow);
574 }
575
576
577 void FloatingPointHelper::LoadNumber(MacroAssembler* masm,
578                                      Destination destination,
579                                      Register object,
580                                      FPURegister dst,
581                                      Register dst1,
582                                      Register dst2,
583                                      Register heap_number_map,
584                                      Register scratch1,
585                                      Register scratch2,
586                                      Label* not_number) {
587   if (FLAG_debug_code) {
588     __ AbortIfNotRootValue(heap_number_map,
589                            Heap::kHeapNumberMapRootIndex,
590                            "HeapNumberMap register clobbered.");
591   }
592
593   Label is_smi, done;
594
595   // Smi-check
596   __ UntagAndJumpIfSmi(scratch1, object, &is_smi);
597   // Heap number check
598   __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
599
600   // Handle loading a double from a heap number.
601   if (CpuFeatures::IsSupported(FPU) &&
602       destination == kFPURegisters) {
603     CpuFeatures::Scope scope(FPU);
604     // Load the double from tagged HeapNumber to double register.
605
606     // ARM uses a workaround here because of the unaligned HeapNumber
607     // kValueOffset. On MIPS this workaround is built into ldc1 so there's no
608     // point in generating even more instructions.
609     __ ldc1(dst, FieldMemOperand(object, HeapNumber::kValueOffset));
610   } else {
611     ASSERT(destination == kCoreRegisters);
612     // Load the double from heap number to dst1 and dst2 in double format.
613     __ lw(dst1, FieldMemOperand(object, HeapNumber::kValueOffset));
614     __ lw(dst2, FieldMemOperand(object,
615         HeapNumber::kValueOffset + kPointerSize));
616   }
617   __ Branch(&done);
618
619   // Handle loading a double from a smi.
620   __ bind(&is_smi);
621   if (CpuFeatures::IsSupported(FPU)) {
622     CpuFeatures::Scope scope(FPU);
623     // Convert smi to double using FPU instructions.
624     __ mtc1(scratch1, dst);
625     __ cvt_d_w(dst, dst);
626     if (destination == kCoreRegisters) {
627       // Load the converted smi to dst1 and dst2 in double format.
628       __ Move(dst1, dst2, dst);
629     }
630   } else {
631     ASSERT(destination == kCoreRegisters);
632     // Write smi to dst1 and dst2 double format.
633     __ mov(scratch1, object);
634     ConvertToDoubleStub stub(dst2, dst1, scratch1, scratch2);
635     __ push(ra);
636     __ Call(stub.GetCode());
637     __ pop(ra);
638   }
639
640   __ bind(&done);
641 }
642
643
644 void FloatingPointHelper::ConvertNumberToInt32(MacroAssembler* masm,
645                                                Register object,
646                                                Register dst,
647                                                Register heap_number_map,
648                                                Register scratch1,
649                                                Register scratch2,
650                                                Register scratch3,
651                                                FPURegister double_scratch,
652                                                Label* not_number) {
653   if (FLAG_debug_code) {
654     __ AbortIfNotRootValue(heap_number_map,
655                            Heap::kHeapNumberMapRootIndex,
656                            "HeapNumberMap register clobbered.");
657   }
658   Label done;
659   Label not_in_int32_range;
660
661   __ UntagAndJumpIfSmi(dst, object, &done);
662   __ lw(scratch1, FieldMemOperand(object, HeapNumber::kMapOffset));
663   __ Branch(not_number, ne, scratch1, Operand(heap_number_map));
664   __ ConvertToInt32(object,
665                     dst,
666                     scratch1,
667                     scratch2,
668                     double_scratch,
669                     &not_in_int32_range);
670   __ jmp(&done);
671
672   __ bind(&not_in_int32_range);
673   __ lw(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
674   __ lw(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset));
675
676   __ EmitOutOfInt32RangeTruncate(dst,
677                                  scratch1,
678                                  scratch2,
679                                  scratch3);
680
681   __ bind(&done);
682 }
683
684
685 void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm,
686                                              Register int_scratch,
687                                              Destination destination,
688                                              FPURegister double_dst,
689                                              Register dst1,
690                                              Register dst2,
691                                              Register scratch2,
692                                              FPURegister single_scratch) {
693   ASSERT(!int_scratch.is(scratch2));
694   ASSERT(!int_scratch.is(dst1));
695   ASSERT(!int_scratch.is(dst2));
696
697   Label done;
698
699   if (CpuFeatures::IsSupported(FPU)) {
700     CpuFeatures::Scope scope(FPU);
701     __ mtc1(int_scratch, single_scratch);
702     __ cvt_d_w(double_dst, single_scratch);
703     if (destination == kCoreRegisters) {
704       __ Move(dst1, dst2, double_dst);
705     }
706   } else {
707     Label fewer_than_20_useful_bits;
708     // Expected output:
709     // |         dst2            |         dst1            |
710     // | s |   exp   |              mantissa               |
711
712     // Check for zero.
713     __ mov(dst2, int_scratch);
714     __ mov(dst1, int_scratch);
715     __ Branch(&done, eq, int_scratch, Operand(zero_reg));
716
717     // Preload the sign of the value.
718     __ And(dst2, int_scratch, Operand(HeapNumber::kSignMask));
719     // Get the absolute value of the object (as an unsigned integer).
720     Label skip_sub;
721     __ Branch(&skip_sub, ge, dst2, Operand(zero_reg));
722     __ Subu(int_scratch, zero_reg, int_scratch);
723     __ bind(&skip_sub);
724
725     // Get mantissa[51:20].
726
727     // Get the position of the first set bit.
728     __ Clz(dst1, int_scratch);
729     __ li(scratch2, 31);
730     __ Subu(dst1, scratch2, dst1);
731
732     // Set the exponent.
733     __ Addu(scratch2, dst1, Operand(HeapNumber::kExponentBias));
734     __ Ins(dst2, scratch2,
735         HeapNumber::kExponentShift, HeapNumber::kExponentBits);
736
737     // Clear the first non null bit.
738     __ li(scratch2, Operand(1));
739     __ sllv(scratch2, scratch2, dst1);
740     __ li(at, -1);
741     __ Xor(scratch2, scratch2, at);
742     __ And(int_scratch, int_scratch, scratch2);
743
744     // Get the number of bits to set in the lower part of the mantissa.
745     __ Subu(scratch2, dst1, Operand(HeapNumber::kMantissaBitsInTopWord));
746     __ Branch(&fewer_than_20_useful_bits, lt, scratch2, Operand(zero_reg));
747     // Set the higher 20 bits of the mantissa.
748     __ srlv(at, int_scratch, scratch2);
749     __ or_(dst2, dst2, at);
750     __ li(at, 32);
751     __ subu(scratch2, at, scratch2);
752     __ sllv(dst1, int_scratch, scratch2);
753     __ Branch(&done);
754
755     __ bind(&fewer_than_20_useful_bits);
756     __ li(at, HeapNumber::kMantissaBitsInTopWord);
757     __ subu(scratch2, at, dst1);
758     __ sllv(scratch2, int_scratch, scratch2);
759     __ Or(dst2, dst2, scratch2);
760     // Set dst1 to 0.
761     __ mov(dst1, zero_reg);
762   }
763   __ bind(&done);
764 }
765
766
767 void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
768                                                   Register object,
769                                                   Destination destination,
770                                                   DoubleRegister double_dst,
771                                                   Register dst1,
772                                                   Register dst2,
773                                                   Register heap_number_map,
774                                                   Register scratch1,
775                                                   Register scratch2,
776                                                   FPURegister single_scratch,
777                                                   Label* not_int32) {
778   ASSERT(!scratch1.is(object) && !scratch2.is(object));
779   ASSERT(!scratch1.is(scratch2));
780   ASSERT(!heap_number_map.is(object) &&
781          !heap_number_map.is(scratch1) &&
782          !heap_number_map.is(scratch2));
783
784   Label done, obj_is_not_smi;
785
786   __ JumpIfNotSmi(object, &obj_is_not_smi);
787   __ SmiUntag(scratch1, object);
788   ConvertIntToDouble(masm, scratch1, destination, double_dst, dst1, dst2,
789                      scratch2, single_scratch);
790   __ Branch(&done);
791
792   __ bind(&obj_is_not_smi);
793   if (FLAG_debug_code) {
794     __ AbortIfNotRootValue(heap_number_map,
795                            Heap::kHeapNumberMapRootIndex,
796                            "HeapNumberMap register clobbered.");
797   }
798   __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
799
800   // Load the number.
801   if (CpuFeatures::IsSupported(FPU)) {
802     CpuFeatures::Scope scope(FPU);
803     // Load the double value.
804     __ ldc1(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset));
805
806     Register except_flag = scratch2;
807     __ EmitFPUTruncate(kRoundToZero,
808                        single_scratch,
809                        double_dst,
810                        scratch1,
811                        except_flag,
812                        kCheckForInexactConversion);
813
814     // Jump to not_int32 if the operation did not succeed.
815     __ Branch(not_int32, ne, except_flag, Operand(zero_reg));
816
817     if (destination == kCoreRegisters) {
818       __ Move(dst1, dst2, double_dst);
819     }
820
821   } else {
822     ASSERT(!scratch1.is(object) && !scratch2.is(object));
823     // Load the double value in the destination registers.
824     __ lw(dst2, FieldMemOperand(object, HeapNumber::kExponentOffset));
825     __ lw(dst1, FieldMemOperand(object, HeapNumber::kMantissaOffset));
826
827     // Check for 0 and -0.
828     __ And(scratch1, dst1, Operand(~HeapNumber::kSignMask));
829     __ Or(scratch1, scratch1, Operand(dst2));
830     __ Branch(&done, eq, scratch1, Operand(zero_reg));
831
832     // Check that the value can be exactly represented by a 32-bit integer.
833     // Jump to not_int32 if that's not the case.
834     DoubleIs32BitInteger(masm, dst1, dst2, scratch1, scratch2, not_int32);
835
836     // dst1 and dst2 were trashed. Reload the double value.
837     __ lw(dst2, FieldMemOperand(object, HeapNumber::kExponentOffset));
838     __ lw(dst1, FieldMemOperand(object, HeapNumber::kMantissaOffset));
839   }
840
841   __ bind(&done);
842 }
843
844
845 void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
846                                             Register object,
847                                             Register dst,
848                                             Register heap_number_map,
849                                             Register scratch1,
850                                             Register scratch2,
851                                             Register scratch3,
852                                             DoubleRegister double_scratch,
853                                             Label* not_int32) {
854   ASSERT(!dst.is(object));
855   ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object));
856   ASSERT(!scratch1.is(scratch2) &&
857          !scratch1.is(scratch3) &&
858          !scratch2.is(scratch3));
859
860   Label done;
861
862   __ UntagAndJumpIfSmi(dst, object, &done);
863
864   if (FLAG_debug_code) {
865     __ AbortIfNotRootValue(heap_number_map,
866                            Heap::kHeapNumberMapRootIndex,
867                            "HeapNumberMap register clobbered.");
868   }
869   __ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
870
871   // Object is a heap number.
872   // Convert the floating point value to a 32-bit integer.
873   if (CpuFeatures::IsSupported(FPU)) {
874     CpuFeatures::Scope scope(FPU);
875     // Load the double value.
876     __ ldc1(double_scratch, FieldMemOperand(object, HeapNumber::kValueOffset));
877
878     FPURegister single_scratch = double_scratch.low();
879     Register except_flag = scratch2;
880     __ EmitFPUTruncate(kRoundToZero,
881                        single_scratch,
882                        double_scratch,
883                        scratch1,
884                        except_flag,
885                        kCheckForInexactConversion);
886
887     // Jump to not_int32 if the operation did not succeed.
888     __ Branch(not_int32, ne, except_flag, Operand(zero_reg));
889     // Get the result in the destination register.
890     __ mfc1(dst, single_scratch);
891
892   } else {
893     // Load the double value in the destination registers.
894     __ lw(scratch2, FieldMemOperand(object, HeapNumber::kExponentOffset));
895     __ lw(scratch1, FieldMemOperand(object, HeapNumber::kMantissaOffset));
896
897     // Check for 0 and -0.
898     __ And(dst, scratch1, Operand(~HeapNumber::kSignMask));
899     __ Or(dst, scratch2, Operand(dst));
900     __ Branch(&done, eq, dst, Operand(zero_reg));
901
902     DoubleIs32BitInteger(masm, scratch1, scratch2, dst, scratch3, not_int32);
903
904     // Registers state after DoubleIs32BitInteger.
905     // dst: mantissa[51:20].
906     // scratch2: 1
907
908     // Shift back the higher bits of the mantissa.
909     __ srlv(dst, dst, scratch3);
910     // Set the implicit first bit.
911     __ li(at, 32);
912     __ subu(scratch3, at, scratch3);
913     __ sllv(scratch2, scratch2, scratch3);
914     __ Or(dst, dst, scratch2);
915     // Set the sign.
916     __ lw(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
917     __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
918     Label skip_sub;
919     __ Branch(&skip_sub, ge, scratch1, Operand(zero_reg));
920     __ Subu(dst, zero_reg, dst);
921     __ bind(&skip_sub);
922   }
923
924   __ bind(&done);
925 }
926
927
928 void FloatingPointHelper::DoubleIs32BitInteger(MacroAssembler* masm,
929                                                Register src1,
930                                                Register src2,
931                                                Register dst,
932                                                Register scratch,
933                                                Label* not_int32) {
934   // Get exponent alone in scratch.
935   __ Ext(scratch,
936          src1,
937          HeapNumber::kExponentShift,
938          HeapNumber::kExponentBits);
939
940   // Substract the bias from the exponent.
941   __ Subu(scratch, scratch, Operand(HeapNumber::kExponentBias));
942
943   // src1: higher (exponent) part of the double value.
944   // src2: lower (mantissa) part of the double value.
945   // scratch: unbiased exponent.
946
947   // Fast cases. Check for obvious non 32-bit integer values.
948   // Negative exponent cannot yield 32-bit integers.
949   __ Branch(not_int32, lt, scratch, Operand(zero_reg));
950   // Exponent greater than 31 cannot yield 32-bit integers.
951   // Also, a positive value with an exponent equal to 31 is outside of the
952   // signed 32-bit integer range.
953   // Another way to put it is that if (exponent - signbit) > 30 then the
954   // number cannot be represented as an int32.
955   Register tmp = dst;
956   __ srl(at, src1, 31);
957   __ subu(tmp, scratch, at);
958   __ Branch(not_int32, gt, tmp, Operand(30));
959   // - Bits [21:0] in the mantissa are not null.
960   __ And(tmp, src2, 0x3fffff);
961   __ Branch(not_int32, ne, tmp, Operand(zero_reg));
962
963   // Otherwise the exponent needs to be big enough to shift left all the
964   // non zero bits left. So we need the (30 - exponent) last bits of the
965   // 31 higher bits of the mantissa to be null.
966   // Because bits [21:0] are null, we can check instead that the
967   // (32 - exponent) last bits of the 32 higher bits of the mantissa are null.
968
969   // Get the 32 higher bits of the mantissa in dst.
970   __ Ext(dst,
971          src2,
972          HeapNumber::kMantissaBitsInTopWord,
973          32 - HeapNumber::kMantissaBitsInTopWord);
974   __ sll(at, src1, HeapNumber::kNonMantissaBitsInTopWord);
975   __ or_(dst, dst, at);
976
977   // Create the mask and test the lower bits (of the higher bits).
978   __ li(at, 32);
979   __ subu(scratch, at, scratch);
980   __ li(src2, 1);
981   __ sllv(src1, src2, scratch);
982   __ Subu(src1, src1, Operand(1));
983   __ And(src1, dst, src1);
984   __ Branch(not_int32, ne, src1, Operand(zero_reg));
985 }
986
987
988 void FloatingPointHelper::CallCCodeForDoubleOperation(
989     MacroAssembler* masm,
990     Token::Value op,
991     Register heap_number_result,
992     Register scratch) {
993   // Using core registers:
994   // a0: Left value (least significant part of mantissa).
995   // a1: Left value (sign, exponent, top of mantissa).
996   // a2: Right value (least significant part of mantissa).
997   // a3: Right value (sign, exponent, top of mantissa).
998
999   // Assert that heap_number_result is saved.
1000   // We currently always use s0 to pass it.
1001   ASSERT(heap_number_result.is(s0));
1002
1003   // Push the current return address before the C call.
1004   __ push(ra);
1005   __ PrepareCallCFunction(4, scratch);  // Two doubles are 4 arguments.
1006   if (!IsMipsSoftFloatABI) {
1007     CpuFeatures::Scope scope(FPU);
1008     // We are not using MIPS FPU instructions, and parameters for the runtime
1009     // function call are prepaired in a0-a3 registers, but function we are
1010     // calling is compiled with hard-float flag and expecting hard float ABI
1011     // (parameters in f12/f14 registers). We need to copy parameters from
1012     // a0-a3 registers to f12/f14 register pairs.
1013     __ Move(f12, a0, a1);
1014     __ Move(f14, a2, a3);
1015   }
1016   {
1017     AllowExternalCallThatCantCauseGC scope(masm);
1018     __ CallCFunction(
1019         ExternalReference::double_fp_operation(op, masm->isolate()), 0, 2);
1020   }
1021   // Store answer in the overwritable heap number.
1022   if (!IsMipsSoftFloatABI) {
1023     CpuFeatures::Scope scope(FPU);
1024     // Double returned in register f0.
1025     __ sdc1(f0, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
1026   } else {
1027     // Double returned in registers v0 and v1.
1028     __ sw(v1, FieldMemOperand(heap_number_result, HeapNumber::kExponentOffset));
1029     __ sw(v0, FieldMemOperand(heap_number_result, HeapNumber::kMantissaOffset));
1030   }
1031   // Place heap_number_result in v0 and return to the pushed return address.
1032   __ pop(ra);
1033   __ Ret(USE_DELAY_SLOT);
1034   __ mov(v0, heap_number_result);
1035 }
1036
1037
1038 bool WriteInt32ToHeapNumberStub::IsPregenerated() {
1039   // These variants are compiled ahead of time.  See next method.
1040   if (the_int_.is(a1) &&
1041       the_heap_number_.is(v0) &&
1042       scratch_.is(a2) &&
1043       sign_.is(a3)) {
1044     return true;
1045   }
1046   if (the_int_.is(a2) &&
1047       the_heap_number_.is(v0) &&
1048       scratch_.is(a3) &&
1049       sign_.is(a0)) {
1050     return true;
1051   }
1052   // Other register combinations are generated as and when they are needed,
1053   // so it is unsafe to call them from stubs (we can't generate a stub while
1054   // we are generating a stub).
1055   return false;
1056 }
1057
1058
1059 void WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime() {
1060   WriteInt32ToHeapNumberStub stub1(a1, v0, a2, a3);
1061   WriteInt32ToHeapNumberStub stub2(a2, v0, a3, a0);
1062   stub1.GetCode()->set_is_pregenerated(true);
1063   stub2.GetCode()->set_is_pregenerated(true);
1064 }
1065
1066
1067 // See comment for class, this does NOT work for int32's that are in Smi range.
1068 void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) {
1069   Label max_negative_int;
1070   // the_int_ has the answer which is a signed int32 but not a Smi.
1071   // We test for the special value that has a different exponent.
1072   STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u);
1073   // Test sign, and save for later conditionals.
1074   __ And(sign_, the_int_, Operand(0x80000000u));
1075   __ Branch(&max_negative_int, eq, the_int_, Operand(0x80000000u));
1076
1077   // Set up the correct exponent in scratch_.  All non-Smi int32s have the same.
1078   // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased).
1079   uint32_t non_smi_exponent =
1080       (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift;
1081   __ li(scratch_, Operand(non_smi_exponent));
1082   // Set the sign bit in scratch_ if the value was negative.
1083   __ or_(scratch_, scratch_, sign_);
1084   // Subtract from 0 if the value was negative.
1085   __ subu(at, zero_reg, the_int_);
1086   __ Movn(the_int_, at, sign_);
1087   // We should be masking the implict first digit of the mantissa away here,
1088   // but it just ends up combining harmlessly with the last digit of the
1089   // exponent that happens to be 1.  The sign bit is 0 so we shift 10 to get
1090   // the most significant 1 to hit the last bit of the 12 bit sign and exponent.
1091   ASSERT(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0);
1092   const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2;
1093   __ srl(at, the_int_, shift_distance);
1094   __ or_(scratch_, scratch_, at);
1095   __ sw(scratch_, FieldMemOperand(the_heap_number_,
1096                                    HeapNumber::kExponentOffset));
1097   __ sll(scratch_, the_int_, 32 - shift_distance);
1098   __ sw(scratch_, FieldMemOperand(the_heap_number_,
1099                                    HeapNumber::kMantissaOffset));
1100   __ Ret();
1101
1102   __ bind(&max_negative_int);
1103   // The max negative int32 is stored as a positive number in the mantissa of
1104   // a double because it uses a sign bit instead of using two's complement.
1105   // The actual mantissa bits stored are all 0 because the implicit most
1106   // significant 1 bit is not stored.
1107   non_smi_exponent += 1 << HeapNumber::kExponentShift;
1108   __ li(scratch_, Operand(HeapNumber::kSignMask | non_smi_exponent));
1109   __ sw(scratch_,
1110         FieldMemOperand(the_heap_number_, HeapNumber::kExponentOffset));
1111   __ mov(scratch_, zero_reg);
1112   __ sw(scratch_,
1113         FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset));
1114   __ Ret();
1115 }
1116
1117
1118 // Handle the case where the lhs and rhs are the same object.
1119 // Equality is almost reflexive (everything but NaN), so this is a test
1120 // for "identity and not NaN".
1121 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
1122                                           Label* slow,
1123                                           Condition cc,
1124                                           bool never_nan_nan) {
1125   Label not_identical;
1126   Label heap_number, return_equal;
1127   Register exp_mask_reg = t5;
1128
1129   __ Branch(&not_identical, ne, a0, Operand(a1));
1130
1131   // The two objects are identical. If we know that one of them isn't NaN then
1132   // we now know they test equal.
1133   if (cc != eq || !never_nan_nan) {
1134     __ li(exp_mask_reg, Operand(HeapNumber::kExponentMask));
1135
1136     // Test for NaN. Sadly, we can't just compare to factory->nan_value(),
1137     // so we do the second best thing - test it ourselves.
1138     // They are both equal and they are not both Smis so both of them are not
1139     // Smis. If it's not a heap number, then return equal.
1140     if (cc == less || cc == greater) {
1141       __ GetObjectType(a0, t4, t4);
1142       __ Branch(slow, greater, t4, Operand(FIRST_SPEC_OBJECT_TYPE));
1143     } else {
1144       __ GetObjectType(a0, t4, t4);
1145       __ Branch(&heap_number, eq, t4, Operand(HEAP_NUMBER_TYPE));
1146       // Comparing JS objects with <=, >= is complicated.
1147       if (cc != eq) {
1148       __ Branch(slow, greater, t4, Operand(FIRST_SPEC_OBJECT_TYPE));
1149         // Normally here we fall through to return_equal, but undefined is
1150         // special: (undefined == undefined) == true, but
1151         // (undefined <= undefined) == false!  See ECMAScript 11.8.5.
1152         if (cc == less_equal || cc == greater_equal) {
1153           __ Branch(&return_equal, ne, t4, Operand(ODDBALL_TYPE));
1154           __ LoadRoot(t2, Heap::kUndefinedValueRootIndex);
1155           __ Branch(&return_equal, ne, a0, Operand(t2));
1156           if (cc == le) {
1157             // undefined <= undefined should fail.
1158             __ li(v0, Operand(GREATER));
1159           } else  {
1160             // undefined >= undefined should fail.
1161             __ li(v0, Operand(LESS));
1162           }
1163           __ Ret();
1164         }
1165       }
1166     }
1167   }
1168
1169   __ bind(&return_equal);
1170
1171   if (cc == less) {
1172     __ li(v0, Operand(GREATER));  // Things aren't less than themselves.
1173   } else if (cc == greater) {
1174     __ li(v0, Operand(LESS));     // Things aren't greater than themselves.
1175   } else {
1176     __ mov(v0, zero_reg);         // Things are <=, >=, ==, === themselves.
1177   }
1178   __ Ret();
1179
1180   if (cc != eq || !never_nan_nan) {
1181     // For less and greater we don't have to check for NaN since the result of
1182     // x < x is false regardless.  For the others here is some code to check
1183     // for NaN.
1184     if (cc != lt && cc != gt) {
1185       __ bind(&heap_number);
1186       // It is a heap number, so return non-equal if it's NaN and equal if it's
1187       // not NaN.
1188
1189       // The representation of NaN values has all exponent bits (52..62) set,
1190       // and not all mantissa bits (0..51) clear.
1191       // Read top bits of double representation (second word of value).
1192       __ lw(t2, FieldMemOperand(a0, HeapNumber::kExponentOffset));
1193       // Test that exponent bits are all set.
1194       __ And(t3, t2, Operand(exp_mask_reg));
1195       // If all bits not set (ne cond), then not a NaN, objects are equal.
1196       __ Branch(&return_equal, ne, t3, Operand(exp_mask_reg));
1197
1198       // Shift out flag and all exponent bits, retaining only mantissa.
1199       __ sll(t2, t2, HeapNumber::kNonMantissaBitsInTopWord);
1200       // Or with all low-bits of mantissa.
1201       __ lw(t3, FieldMemOperand(a0, HeapNumber::kMantissaOffset));
1202       __ Or(v0, t3, Operand(t2));
1203       // For equal we already have the right value in v0:  Return zero (equal)
1204       // if all bits in mantissa are zero (it's an Infinity) and non-zero if
1205       // not (it's a NaN).  For <= and >= we need to load v0 with the failing
1206       // value if it's a NaN.
1207       if (cc != eq) {
1208         // All-zero means Infinity means equal.
1209         __ Ret(eq, v0, Operand(zero_reg));
1210         if (cc == le) {
1211           __ li(v0, Operand(GREATER));  // NaN <= NaN should fail.
1212         } else {
1213           __ li(v0, Operand(LESS));     // NaN >= NaN should fail.
1214         }
1215       }
1216       __ Ret();
1217     }
1218     // No fall through here.
1219   }
1220
1221   __ bind(&not_identical);
1222 }
1223
1224
1225 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
1226                                     Register lhs,
1227                                     Register rhs,
1228                                     Label* both_loaded_as_doubles,
1229                                     Label* slow,
1230                                     bool strict) {
1231   ASSERT((lhs.is(a0) && rhs.is(a1)) ||
1232          (lhs.is(a1) && rhs.is(a0)));
1233
1234   Label lhs_is_smi;
1235   __ JumpIfSmi(lhs, &lhs_is_smi);
1236   // Rhs is a Smi.
1237   // Check whether the non-smi is a heap number.
1238   __ GetObjectType(lhs, t4, t4);
1239   if (strict) {
1240     // If lhs was not a number and rhs was a Smi then strict equality cannot
1241     // succeed. Return non-equal (lhs is already not zero).
1242     __ Ret(USE_DELAY_SLOT, ne, t4, Operand(HEAP_NUMBER_TYPE));
1243     __ mov(v0, lhs);
1244   } else {
1245     // Smi compared non-strictly with a non-Smi non-heap-number. Call
1246     // the runtime.
1247     __ Branch(slow, ne, t4, Operand(HEAP_NUMBER_TYPE));
1248   }
1249
1250   // Rhs is a smi, lhs is a number.
1251   // Convert smi rhs to double.
1252   if (CpuFeatures::IsSupported(FPU)) {
1253     CpuFeatures::Scope scope(FPU);
1254     __ sra(at, rhs, kSmiTagSize);
1255     __ mtc1(at, f14);
1256     __ cvt_d_w(f14, f14);
1257     __ ldc1(f12, FieldMemOperand(lhs, HeapNumber::kValueOffset));
1258   } else {
1259     // Load lhs to a double in a2, a3.
1260     __ lw(a3, FieldMemOperand(lhs, HeapNumber::kValueOffset + 4));
1261     __ lw(a2, FieldMemOperand(lhs, HeapNumber::kValueOffset));
1262
1263     // Write Smi from rhs to a1 and a0 in double format. t5 is scratch.
1264     __ mov(t6, rhs);
1265     ConvertToDoubleStub stub1(a1, a0, t6, t5);
1266     __ push(ra);
1267     __ Call(stub1.GetCode());
1268
1269     __ pop(ra);
1270   }
1271
1272   // We now have both loaded as doubles.
1273   __ jmp(both_loaded_as_doubles);
1274
1275   __ bind(&lhs_is_smi);
1276   // Lhs is a Smi.  Check whether the non-smi is a heap number.
1277   __ GetObjectType(rhs, t4, t4);
1278   if (strict) {
1279     // If lhs was not a number and rhs was a Smi then strict equality cannot
1280     // succeed. Return non-equal.
1281     __ Ret(USE_DELAY_SLOT, ne, t4, Operand(HEAP_NUMBER_TYPE));
1282     __ li(v0, Operand(1));
1283   } else {
1284     // Smi compared non-strictly with a non-Smi non-heap-number. Call
1285     // the runtime.
1286     __ Branch(slow, ne, t4, Operand(HEAP_NUMBER_TYPE));
1287   }
1288
1289   // Lhs is a smi, rhs is a number.
1290   // Convert smi lhs to double.
1291   if (CpuFeatures::IsSupported(FPU)) {
1292     CpuFeatures::Scope scope(FPU);
1293     __ sra(at, lhs, kSmiTagSize);
1294     __ mtc1(at, f12);
1295     __ cvt_d_w(f12, f12);
1296     __ ldc1(f14, FieldMemOperand(rhs, HeapNumber::kValueOffset));
1297   } else {
1298     // Convert lhs to a double format. t5 is scratch.
1299     __ mov(t6, lhs);
1300     ConvertToDoubleStub stub2(a3, a2, t6, t5);
1301     __ push(ra);
1302     __ Call(stub2.GetCode());
1303     __ pop(ra);
1304     // Load rhs to a double in a1, a0.
1305     if (rhs.is(a0)) {
1306       __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4));
1307       __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset));
1308     } else {
1309       __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset));
1310       __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4));
1311     }
1312   }
1313   // Fall through to both_loaded_as_doubles.
1314 }
1315
1316
1317 void EmitNanCheck(MacroAssembler* masm, Condition cc) {
1318   bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset);
1319   if (CpuFeatures::IsSupported(FPU)) {
1320     CpuFeatures::Scope scope(FPU);
1321     // Lhs and rhs are already loaded to f12 and f14 register pairs.
1322     __ Move(t0, t1, f14);
1323     __ Move(t2, t3, f12);
1324   } else {
1325     // Lhs and rhs are already loaded to GP registers.
1326     __ mov(t0, a0);  // a0 has LS 32 bits of rhs.
1327     __ mov(t1, a1);  // a1 has MS 32 bits of rhs.
1328     __ mov(t2, a2);  // a2 has LS 32 bits of lhs.
1329     __ mov(t3, a3);  // a3 has MS 32 bits of lhs.
1330   }
1331   Register rhs_exponent = exp_first ? t0 : t1;
1332   Register lhs_exponent = exp_first ? t2 : t3;
1333   Register rhs_mantissa = exp_first ? t1 : t0;
1334   Register lhs_mantissa = exp_first ? t3 : t2;
1335   Label one_is_nan, neither_is_nan;
1336   Label lhs_not_nan_exp_mask_is_loaded;
1337
1338   Register exp_mask_reg = t4;
1339   __ li(exp_mask_reg, HeapNumber::kExponentMask);
1340   __ and_(t5, lhs_exponent, exp_mask_reg);
1341   __ Branch(&lhs_not_nan_exp_mask_is_loaded, ne, t5, Operand(exp_mask_reg));
1342
1343   __ sll(t5, lhs_exponent, HeapNumber::kNonMantissaBitsInTopWord);
1344   __ Branch(&one_is_nan, ne, t5, Operand(zero_reg));
1345
1346   __ Branch(&one_is_nan, ne, lhs_mantissa, Operand(zero_reg));
1347
1348   __ li(exp_mask_reg, HeapNumber::kExponentMask);
1349   __ bind(&lhs_not_nan_exp_mask_is_loaded);
1350   __ and_(t5, rhs_exponent, exp_mask_reg);
1351
1352   __ Branch(&neither_is_nan, ne, t5, Operand(exp_mask_reg));
1353
1354   __ sll(t5, rhs_exponent, HeapNumber::kNonMantissaBitsInTopWord);
1355   __ Branch(&one_is_nan, ne, t5, Operand(zero_reg));
1356
1357   __ Branch(&neither_is_nan, eq, rhs_mantissa, Operand(zero_reg));
1358
1359   __ bind(&one_is_nan);
1360   // NaN comparisons always fail.
1361   // Load whatever we need in v0 to make the comparison fail.
1362
1363   if (cc == lt || cc == le) {
1364     __ li(v0, Operand(GREATER));
1365   } else {
1366     __ li(v0, Operand(LESS));
1367   }
1368   __ Ret();
1369
1370   __ bind(&neither_is_nan);
1371 }
1372
1373
1374 static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc) {
1375   // f12 and f14 have the two doubles.  Neither is a NaN.
1376   // Call a native function to do a comparison between two non-NaNs.
1377   // Call C routine that may not cause GC or other trouble.
1378   // We use a call_was and return manually because we need arguments slots to
1379   // be freed.
1380
1381   Label return_result_not_equal, return_result_equal;
1382   if (cc == eq) {
1383     // Doubles are not equal unless they have the same bit pattern.
1384     // Exception: 0 and -0.
1385     bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset);
1386     if (CpuFeatures::IsSupported(FPU)) {
1387       CpuFeatures::Scope scope(FPU);
1388       // Lhs and rhs are already loaded to f12 and f14 register pairs.
1389       __ Move(t0, t1, f14);
1390       __ Move(t2, t3, f12);
1391     } else {
1392       // Lhs and rhs are already loaded to GP registers.
1393       __ mov(t0, a0);  // a0 has LS 32 bits of rhs.
1394       __ mov(t1, a1);  // a1 has MS 32 bits of rhs.
1395       __ mov(t2, a2);  // a2 has LS 32 bits of lhs.
1396       __ mov(t3, a3);  // a3 has MS 32 bits of lhs.
1397     }
1398     Register rhs_exponent = exp_first ? t0 : t1;
1399     Register lhs_exponent = exp_first ? t2 : t3;
1400     Register rhs_mantissa = exp_first ? t1 : t0;
1401     Register lhs_mantissa = exp_first ? t3 : t2;
1402
1403     __ xor_(v0, rhs_mantissa, lhs_mantissa);
1404     __ Branch(&return_result_not_equal, ne, v0, Operand(zero_reg));
1405
1406     __ subu(v0, rhs_exponent, lhs_exponent);
1407     __ Branch(&return_result_equal, eq, v0, Operand(zero_reg));
1408     // 0, -0 case.
1409     __ sll(rhs_exponent, rhs_exponent, kSmiTagSize);
1410     __ sll(lhs_exponent, lhs_exponent, kSmiTagSize);
1411     __ or_(t4, rhs_exponent, lhs_exponent);
1412     __ or_(t4, t4, rhs_mantissa);
1413
1414     __ Branch(&return_result_not_equal, ne, t4, Operand(zero_reg));
1415
1416     __ bind(&return_result_equal);
1417
1418     __ li(v0, Operand(EQUAL));
1419     __ Ret();
1420   }
1421
1422   __ bind(&return_result_not_equal);
1423
1424   if (!CpuFeatures::IsSupported(FPU)) {
1425     __ push(ra);
1426     __ PrepareCallCFunction(0, 2, t4);
1427     if (!IsMipsSoftFloatABI) {
1428       // We are not using MIPS FPU instructions, and parameters for the runtime
1429       // function call are prepaired in a0-a3 registers, but function we are
1430       // calling is compiled with hard-float flag and expecting hard float ABI
1431       // (parameters in f12/f14 registers). We need to copy parameters from
1432       // a0-a3 registers to f12/f14 register pairs.
1433       __ Move(f12, a0, a1);
1434       __ Move(f14, a2, a3);
1435     }
1436
1437     AllowExternalCallThatCantCauseGC scope(masm);
1438     __ CallCFunction(ExternalReference::compare_doubles(masm->isolate()),
1439        0, 2);
1440     __ pop(ra);  // Because this function returns int, result is in v0.
1441     __ Ret();
1442   } else {
1443     CpuFeatures::Scope scope(FPU);
1444     Label equal, less_than;
1445     __ BranchF(&equal, NULL, eq, f12, f14);
1446     __ BranchF(&less_than, NULL, lt, f12, f14);
1447
1448     // Not equal, not less, not NaN, must be greater.
1449
1450     __ li(v0, Operand(GREATER));
1451     __ Ret();
1452
1453     __ bind(&equal);
1454     __ li(v0, Operand(EQUAL));
1455     __ Ret();
1456
1457     __ bind(&less_than);
1458     __ li(v0, Operand(LESS));
1459     __ Ret();
1460   }
1461 }
1462
1463
1464 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
1465                                            Register lhs,
1466                                            Register rhs) {
1467     // If either operand is a JS object or an oddball value, then they are
1468     // not equal since their pointers are different.
1469     // There is no test for undetectability in strict equality.
1470     STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
1471     Label first_non_object;
1472     // Get the type of the first operand into a2 and compare it with
1473     // FIRST_SPEC_OBJECT_TYPE.
1474     __ GetObjectType(lhs, a2, a2);
1475     __ Branch(&first_non_object, less, a2, Operand(FIRST_SPEC_OBJECT_TYPE));
1476
1477     // Return non-zero.
1478     Label return_not_equal;
1479     __ bind(&return_not_equal);
1480     __ Ret(USE_DELAY_SLOT);
1481     __ li(v0, Operand(1));
1482
1483     __ bind(&first_non_object);
1484     // Check for oddballs: true, false, null, undefined.
1485     __ Branch(&return_not_equal, eq, a2, Operand(ODDBALL_TYPE));
1486
1487     __ GetObjectType(rhs, a3, a3);
1488     __ Branch(&return_not_equal, greater, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
1489
1490     // Check for oddballs: true, false, null, undefined.
1491     __ Branch(&return_not_equal, eq, a3, Operand(ODDBALL_TYPE));
1492
1493     // Now that we have the types we might as well check for symbol-symbol.
1494     // Ensure that no non-strings have the symbol bit set.
1495     STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsSymbolMask);
1496     STATIC_ASSERT(kSymbolTag != 0);
1497     __ And(t2, a2, Operand(a3));
1498     __ And(t0, t2, Operand(kIsSymbolMask));
1499     __ Branch(&return_not_equal, ne, t0, Operand(zero_reg));
1500 }
1501
1502
1503 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
1504                                        Register lhs,
1505                                        Register rhs,
1506                                        Label* both_loaded_as_doubles,
1507                                        Label* not_heap_numbers,
1508                                        Label* slow) {
1509   __ GetObjectType(lhs, a3, a2);
1510   __ Branch(not_heap_numbers, ne, a2, Operand(HEAP_NUMBER_TYPE));
1511   __ lw(a2, FieldMemOperand(rhs, HeapObject::kMapOffset));
1512   // If first was a heap number & second wasn't, go to slow case.
1513   __ Branch(slow, ne, a3, Operand(a2));
1514
1515   // Both are heap numbers. Load them up then jump to the code we have
1516   // for that.
1517   if (CpuFeatures::IsSupported(FPU)) {
1518     CpuFeatures::Scope scope(FPU);
1519     __ ldc1(f12, FieldMemOperand(lhs, HeapNumber::kValueOffset));
1520     __ ldc1(f14, FieldMemOperand(rhs, HeapNumber::kValueOffset));
1521   } else {
1522     __ lw(a2, FieldMemOperand(lhs, HeapNumber::kValueOffset));
1523     __ lw(a3, FieldMemOperand(lhs, HeapNumber::kValueOffset + 4));
1524     if (rhs.is(a0)) {
1525       __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4));
1526       __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset));
1527     } else {
1528       __ lw(a0, FieldMemOperand(rhs, HeapNumber::kValueOffset));
1529       __ lw(a1, FieldMemOperand(rhs, HeapNumber::kValueOffset + 4));
1530     }
1531   }
1532   __ jmp(both_loaded_as_doubles);
1533 }
1534
1535
1536 // Fast negative check for symbol-to-symbol equality.
1537 static void EmitCheckForSymbolsOrObjects(MacroAssembler* masm,
1538                                          Register lhs,
1539                                          Register rhs,
1540                                          Label* possible_strings,
1541                                          Label* not_both_strings) {
1542   ASSERT((lhs.is(a0) && rhs.is(a1)) ||
1543          (lhs.is(a1) && rhs.is(a0)));
1544
1545   // a2 is object type of lhs.
1546   // Ensure that no non-strings have the symbol bit set.
1547   Label object_test;
1548   STATIC_ASSERT(kSymbolTag != 0);
1549   __ And(at, a2, Operand(kIsNotStringMask));
1550   __ Branch(&object_test, ne, at, Operand(zero_reg));
1551   __ And(at, a2, Operand(kIsSymbolMask));
1552   __ Branch(possible_strings, eq, at, Operand(zero_reg));
1553   __ GetObjectType(rhs, a3, a3);
1554   __ Branch(not_both_strings, ge, a3, Operand(FIRST_NONSTRING_TYPE));
1555   __ And(at, a3, Operand(kIsSymbolMask));
1556   __ Branch(possible_strings, eq, at, Operand(zero_reg));
1557
1558   // Both are symbols. We already checked they weren't the same pointer
1559   // so they are not equal.
1560   __ Ret(USE_DELAY_SLOT);
1561   __ li(v0, Operand(1));   // Non-zero indicates not equal.
1562
1563   __ bind(&object_test);
1564   __ Branch(not_both_strings, lt, a2, Operand(FIRST_SPEC_OBJECT_TYPE));
1565   __ GetObjectType(rhs, a2, a3);
1566   __ Branch(not_both_strings, lt, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
1567
1568   // If both objects are undetectable, they are equal.  Otherwise, they
1569   // are not equal, since they are different objects and an object is not
1570   // equal to undefined.
1571   __ lw(a3, FieldMemOperand(lhs, HeapObject::kMapOffset));
1572   __ lbu(a2, FieldMemOperand(a2, Map::kBitFieldOffset));
1573   __ lbu(a3, FieldMemOperand(a3, Map::kBitFieldOffset));
1574   __ and_(a0, a2, a3);
1575   __ And(a0, a0, Operand(1 << Map::kIsUndetectable));
1576   __ Ret(USE_DELAY_SLOT);
1577   __ xori(v0, a0, 1 << Map::kIsUndetectable);
1578 }
1579
1580
1581 void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
1582                                                          Register object,
1583                                                          Register result,
1584                                                          Register scratch1,
1585                                                          Register scratch2,
1586                                                          Register scratch3,
1587                                                          bool object_is_smi,
1588                                                          Label* not_found) {
1589   // Use of registers. Register result is used as a temporary.
1590   Register number_string_cache = result;
1591   Register mask = scratch3;
1592
1593   // Load the number string cache.
1594   __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
1595
1596   // Make the hash mask from the length of the number string cache. It
1597   // contains two elements (number and string) for each cache entry.
1598   __ lw(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset));
1599   // Divide length by two (length is a smi).
1600   __ sra(mask, mask, kSmiTagSize + 1);
1601   __ Addu(mask, mask, -1);  // Make mask.
1602
1603   // Calculate the entry in the number string cache. The hash value in the
1604   // number string cache for smis is just the smi value, and the hash for
1605   // doubles is the xor of the upper and lower words. See
1606   // Heap::GetNumberStringCache.
1607   Isolate* isolate = masm->isolate();
1608   Label is_smi;
1609   Label load_result_from_cache;
1610   if (!object_is_smi) {
1611     __ JumpIfSmi(object, &is_smi);
1612     if (CpuFeatures::IsSupported(FPU)) {
1613       CpuFeatures::Scope scope(FPU);
1614       __ CheckMap(object,
1615                   scratch1,
1616                   Heap::kHeapNumberMapRootIndex,
1617                   not_found,
1618                   DONT_DO_SMI_CHECK);
1619
1620       STATIC_ASSERT(8 == kDoubleSize);
1621       __ Addu(scratch1,
1622               object,
1623               Operand(HeapNumber::kValueOffset - kHeapObjectTag));
1624       __ lw(scratch2, MemOperand(scratch1, kPointerSize));
1625       __ lw(scratch1, MemOperand(scratch1, 0));
1626       __ Xor(scratch1, scratch1, Operand(scratch2));
1627       __ And(scratch1, scratch1, Operand(mask));
1628
1629       // Calculate address of entry in string cache: each entry consists
1630       // of two pointer sized fields.
1631       __ sll(scratch1, scratch1, kPointerSizeLog2 + 1);
1632       __ Addu(scratch1, number_string_cache, scratch1);
1633
1634       Register probe = mask;
1635       __ lw(probe,
1636              FieldMemOperand(scratch1, FixedArray::kHeaderSize));
1637       __ JumpIfSmi(probe, not_found);
1638       __ ldc1(f12, FieldMemOperand(object, HeapNumber::kValueOffset));
1639       __ ldc1(f14, FieldMemOperand(probe, HeapNumber::kValueOffset));
1640       __ BranchF(&load_result_from_cache, NULL, eq, f12, f14);
1641       __ Branch(not_found);
1642     } else {
1643       // Note that there is no cache check for non-FPU case, even though
1644       // it seems there could be. May be a tiny opimization for non-FPU
1645       // cores.
1646       __ Branch(not_found);
1647     }
1648   }
1649
1650   __ bind(&is_smi);
1651   Register scratch = scratch1;
1652   __ sra(scratch, object, 1);   // Shift away the tag.
1653   __ And(scratch, mask, Operand(scratch));
1654
1655   // Calculate address of entry in string cache: each entry consists
1656   // of two pointer sized fields.
1657   __ sll(scratch, scratch, kPointerSizeLog2 + 1);
1658   __ Addu(scratch, number_string_cache, scratch);
1659
1660   // Check if the entry is the smi we are looking for.
1661   Register probe = mask;
1662   __ lw(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize));
1663   __ Branch(not_found, ne, object, Operand(probe));
1664
1665   // Get the result from the cache.
1666   __ bind(&load_result_from_cache);
1667   __ lw(result,
1668          FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize));
1669
1670   __ IncrementCounter(isolate->counters()->number_to_string_native(),
1671                       1,
1672                       scratch1,
1673                       scratch2);
1674 }
1675
1676
1677 void NumberToStringStub::Generate(MacroAssembler* masm) {
1678   Label runtime;
1679
1680   __ lw(a1, MemOperand(sp, 0));
1681
1682   // Generate code to lookup number in the number string cache.
1683   GenerateLookupNumberStringCache(masm, a1, v0, a2, a3, t0, false, &runtime);
1684   __ DropAndRet(1);
1685
1686   __ bind(&runtime);
1687   // Handle number to string in the runtime system if not found in the cache.
1688   __ TailCallRuntime(Runtime::kNumberToString, 1, 1);
1689 }
1690
1691
1692 // On entry lhs_ (lhs) and rhs_ (rhs) are the things to be compared.
1693 // On exit, v0 is 0, positive, or negative (smi) to indicate the result
1694 // of the comparison.
1695 void CompareStub::Generate(MacroAssembler* masm) {
1696   Label slow;  // Call builtin.
1697   Label not_smis, both_loaded_as_doubles;
1698
1699
1700   if (include_smi_compare_) {
1701     Label not_two_smis, smi_done;
1702     __ Or(a2, a1, a0);
1703     __ JumpIfNotSmi(a2, &not_two_smis);
1704     __ sra(a1, a1, 1);
1705     __ sra(a0, a0, 1);
1706     __ Ret(USE_DELAY_SLOT);
1707     __ subu(v0, a1, a0);
1708     __ bind(&not_two_smis);
1709   } else if (FLAG_debug_code) {
1710     __ Or(a2, a1, a0);
1711     __ And(a2, a2, kSmiTagMask);
1712     __ Assert(ne, "CompareStub: unexpected smi operands.",
1713         a2, Operand(zero_reg));
1714   }
1715
1716
1717   // NOTICE! This code is only reached after a smi-fast-case check, so
1718   // it is certain that at least one operand isn't a smi.
1719   {
1720     // This is optimized for reading the code and not benchmarked for
1721     // speed or amount of instructions. The code is not ordered for speed
1722     // or anything like this
1723     Label miss, user_compare;
1724
1725     // No global compare if both operands are SMIs
1726     __ And(a2, a1, Operand(a0));
1727     __ JumpIfSmi(a2, &miss);
1728
1729
1730     // We need to check if lhs and rhs are both objects, if not we are
1731     // jumping out of the function. We will keep the 'map' in t0 (lhs) and
1732     // t1 (rhs) for later usage.
1733     __ GetObjectType(a0, t0, a3);
1734     __ Branch(&miss, ne, a3, Operand(JS_OBJECT_TYPE));
1735
1736     __ GetObjectType(a1, t1, a3);
1737     __ Branch(&miss, ne, a3, Operand(JS_OBJECT_TYPE));
1738
1739     // Check if the UseUserComparison flag is set by using the map of t0 for lhs
1740     __ lbu(t0, FieldMemOperand(t0, Map::kBitField2Offset));
1741     __ And(t0, t0, Operand(1 << Map::kUseUserObjectComparison));
1742     __ Branch(&user_compare, eq, t0, Operand(1 << Map::kUseUserObjectComparison));
1743
1744
1745     // Check if the UseUserComparison flag is _not_ set by using the map of t1 for
1746     // rhs and then jump to the miss label.
1747     __ lbu(t1, FieldMemOperand(t1, Map::kBitField2Offset));
1748     __ And(t1, t1, Operand(1 << Map::kUseUserObjectComparison));
1749     __ Branch(&miss, ne, t1, Operand(1 << Map::kUseUserObjectComparison));
1750
1751     // Invoke the runtime function here
1752     __ bind(&user_compare);
1753     __ Push(a0, a1);
1754     __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1);
1755
1756     // We exit here without doing anything
1757     __ bind(&miss);
1758   }
1759
1760   // Handle the case where the objects are identical.  Either returns the answer
1761   // or goes to slow.  Only falls through if the objects were not identical.
1762   EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_);
1763
1764   // If either is a Smi (we know that not both are), then they can only
1765   // be strictly equal if the other is a HeapNumber.
1766   STATIC_ASSERT(kSmiTag == 0);
1767   ASSERT_EQ(0, Smi::FromInt(0));
1768   __ And(t2, lhs_, Operand(rhs_));
1769   __ JumpIfNotSmi(t2, &not_smis, t0);
1770   // One operand is a smi. EmitSmiNonsmiComparison generates code that can:
1771   // 1) Return the answer.
1772   // 2) Go to slow.
1773   // 3) Fall through to both_loaded_as_doubles.
1774   // 4) Jump to rhs_not_nan.
1775   // In cases 3 and 4 we have found out we were dealing with a number-number
1776   // comparison and the numbers have been loaded into f12 and f14 as doubles,
1777   // or in GP registers (a0, a1, a2, a3) depending on the presence of the FPU.
1778   EmitSmiNonsmiComparison(masm, lhs_, rhs_,
1779                           &both_loaded_as_doubles, &slow, strict_);
1780
1781   __ bind(&both_loaded_as_doubles);
1782   // f12, f14 are the double representations of the left hand side
1783   // and the right hand side if we have FPU. Otherwise a2, a3 represent
1784   // left hand side and a0, a1 represent right hand side.
1785
1786   Isolate* isolate = masm->isolate();
1787   if (CpuFeatures::IsSupported(FPU)) {
1788     CpuFeatures::Scope scope(FPU);
1789     Label nan;
1790     __ li(t0, Operand(LESS));
1791     __ li(t1, Operand(GREATER));
1792     __ li(t2, Operand(EQUAL));
1793
1794     // Check if either rhs or lhs is NaN.
1795     __ BranchF(NULL, &nan, eq, f12, f14);
1796
1797     // Check if LESS condition is satisfied. If true, move conditionally
1798     // result to v0.
1799     __ c(OLT, D, f12, f14);
1800     __ Movt(v0, t0);
1801     // Use previous check to store conditionally to v0 oposite condition
1802     // (GREATER). If rhs is equal to lhs, this will be corrected in next
1803     // check.
1804     __ Movf(v0, t1);
1805     // Check if EQUAL condition is satisfied. If true, move conditionally
1806     // result to v0.
1807     __ c(EQ, D, f12, f14);
1808     __ Movt(v0, t2);
1809
1810     __ Ret();
1811
1812     __ bind(&nan);
1813     // NaN comparisons always fail.
1814     // Load whatever we need in v0 to make the comparison fail.
1815     if (cc_ == lt || cc_ == le) {
1816       __ li(v0, Operand(GREATER));
1817     } else {
1818       __ li(v0, Operand(LESS));
1819     }
1820     __ Ret();
1821   } else {
1822     // Checks for NaN in the doubles we have loaded.  Can return the answer or
1823     // fall through if neither is a NaN.  Also binds rhs_not_nan.
1824     EmitNanCheck(masm, cc_);
1825
1826     // Compares two doubles that are not NaNs. Returns the answer.
1827     // Never falls through.
1828     EmitTwoNonNanDoubleComparison(masm, cc_);
1829   }
1830
1831   __ bind(&not_smis);
1832   // At this point we know we are dealing with two different objects,
1833   // and neither of them is a Smi. The objects are in lhs_ and rhs_.
1834   if (strict_) {
1835     // This returns non-equal for some object types, or falls through if it
1836     // was not lucky.
1837     EmitStrictTwoHeapObjectCompare(masm, lhs_, rhs_);
1838   }
1839
1840   Label check_for_symbols;
1841   Label flat_string_check;
1842   // Check for heap-number-heap-number comparison. Can jump to slow case,
1843   // or load both doubles and jump to the code that handles
1844   // that case. If the inputs are not doubles then jumps to check_for_symbols.
1845   // In this case a2 will contain the type of lhs_.
1846   EmitCheckForTwoHeapNumbers(masm,
1847                              lhs_,
1848                              rhs_,
1849                              &both_loaded_as_doubles,
1850                              &check_for_symbols,
1851                              &flat_string_check);
1852
1853   __ bind(&check_for_symbols);
1854   if (cc_ == eq && !strict_) {
1855     // Returns an answer for two symbols or two detectable objects.
1856     // Otherwise jumps to string case or not both strings case.
1857     // Assumes that a2 is the type of lhs_ on entry.
1858     EmitCheckForSymbolsOrObjects(masm, lhs_, rhs_, &flat_string_check, &slow);
1859   }
1860
1861   // Check for both being sequential ASCII strings, and inline if that is the
1862   // case.
1863   __ bind(&flat_string_check);
1864
1865   __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs_, rhs_, a2, a3, &slow);
1866
1867   __ IncrementCounter(isolate->counters()->string_compare_native(), 1, a2, a3);
1868   if (cc_ == eq) {
1869     StringCompareStub::GenerateFlatAsciiStringEquals(masm,
1870                                                      lhs_,
1871                                                      rhs_,
1872                                                      a2,
1873                                                      a3,
1874                                                      t0);
1875   } else {
1876     StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
1877                                                        lhs_,
1878                                                        rhs_,
1879                                                        a2,
1880                                                        a3,
1881                                                        t0,
1882                                                        t1);
1883   }
1884   // Never falls through to here.
1885
1886   __ bind(&slow);
1887   // Prepare for call to builtin. Push object pointers, a0 (lhs) first,
1888   // a1 (rhs) second.
1889   __ Push(lhs_, rhs_);
1890   // Figure out which native to call and setup the arguments.
1891   Builtins::JavaScript native;
1892   if (cc_ == eq) {
1893     native = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
1894   } else {
1895     native = Builtins::COMPARE;
1896     int ncr;  // NaN compare result.
1897     if (cc_ == lt || cc_ == le) {
1898       ncr = GREATER;
1899     } else {
1900       ASSERT(cc_ == gt || cc_ == ge);  // Remaining cases.
1901       ncr = LESS;
1902     }
1903     __ li(a0, Operand(Smi::FromInt(ncr)));
1904     __ push(a0);
1905   }
1906
1907   // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
1908   // tagged as a small integer.
1909   __ InvokeBuiltin(native, JUMP_FUNCTION);
1910 }
1911
1912
1913 // The stub expects its argument in the tos_ register and returns its result in
1914 // it, too: zero for false, and a non-zero value for true.
1915 void ToBooleanStub::Generate(MacroAssembler* masm) {
1916   // This stub uses FPU instructions.
1917   CpuFeatures::Scope scope(FPU);
1918
1919   Label patch;
1920   const Register map = t5.is(tos_) ? t3 : t5;
1921
1922   // undefined -> false.
1923   CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false);
1924
1925   // Boolean -> its value.
1926   CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false);
1927   CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true);
1928
1929   // 'null' -> false.
1930   CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false);
1931
1932   if (types_.Contains(SMI)) {
1933     // Smis: 0 -> false, all other -> true
1934     __ And(at, tos_, kSmiTagMask);
1935     // tos_ contains the correct return value already
1936     __ Ret(eq, at, Operand(zero_reg));
1937   } else if (types_.NeedsMap()) {
1938     // If we need a map later and have a Smi -> patch.
1939     __ JumpIfSmi(tos_, &patch);
1940   }
1941
1942   if (types_.NeedsMap()) {
1943     __ lw(map, FieldMemOperand(tos_, HeapObject::kMapOffset));
1944
1945     if (types_.CanBeUndetectable()) {
1946       __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset));
1947       __ And(at, at, Operand(1 << Map::kIsUndetectable));
1948       // Undetectable -> false.
1949       __ Movn(tos_, zero_reg, at);
1950       __ Ret(ne, at, Operand(zero_reg));
1951     }
1952   }
1953
1954   if (types_.Contains(SPEC_OBJECT)) {
1955     // Spec object -> true.
1956     __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
1957     // tos_ contains the correct non-zero return value already.
1958     __ Ret(ge, at, Operand(FIRST_SPEC_OBJECT_TYPE));
1959   }
1960
1961   if (types_.Contains(STRING)) {
1962     // String value -> false iff empty.
1963     __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
1964     Label skip;
1965     __ Branch(&skip, ge, at, Operand(FIRST_NONSTRING_TYPE));
1966     __ Ret(USE_DELAY_SLOT);  // the string length is OK as the return value
1967     __ lw(tos_, FieldMemOperand(tos_, String::kLengthOffset));
1968     __ bind(&skip);
1969   }
1970
1971   if (types_.Contains(HEAP_NUMBER)) {
1972     // Heap number -> false iff +0, -0, or NaN.
1973     Label not_heap_number;
1974     __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
1975     __ Branch(&not_heap_number, ne, map, Operand(at));
1976     Label zero_or_nan, number;
1977     __ ldc1(f2, FieldMemOperand(tos_, HeapNumber::kValueOffset));
1978     __ BranchF(&number, &zero_or_nan, ne, f2, kDoubleRegZero);
1979     // "tos_" is a register, and contains a non zero value by default.
1980     // Hence we only need to overwrite "tos_" with zero to return false for
1981     // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true.
1982     __ bind(&zero_or_nan);
1983     __ mov(tos_, zero_reg);
1984     __ bind(&number);
1985     __ Ret();
1986     __ bind(&not_heap_number);
1987   }
1988
1989   __ bind(&patch);
1990   GenerateTypeTransition(masm);
1991 }
1992
1993
1994 void ToBooleanStub::CheckOddball(MacroAssembler* masm,
1995                                  Type type,
1996                                  Heap::RootListIndex value,
1997                                  bool result) {
1998   if (types_.Contains(type)) {
1999     // If we see an expected oddball, return its ToBoolean value tos_.
2000     __ LoadRoot(at, value);
2001     __ Subu(at, at, tos_);  // This is a check for equality for the movz below.
2002     // The value of a root is never NULL, so we can avoid loading a non-null
2003     // value into tos_ when we want to return 'true'.
2004     if (!result) {
2005       __ Movz(tos_, zero_reg, at);
2006     }
2007     __ Ret(eq, at, Operand(zero_reg));
2008   }
2009 }
2010
2011
2012 void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
2013   __ Move(a3, tos_);
2014   __ li(a2, Operand(Smi::FromInt(tos_.code())));
2015   __ li(a1, Operand(Smi::FromInt(types_.ToByte())));
2016   __ Push(a3, a2, a1);
2017   // Patch the caller to an appropriate specialized stub and return the
2018   // operation result to the caller of the stub.
2019   __ TailCallExternalReference(
2020       ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
2021       3,
2022       1);
2023 }
2024
2025
2026 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
2027   // We don't allow a GC during a store buffer overflow so there is no need to
2028   // store the registers in any particular way, but we do have to store and
2029   // restore them.
2030   __ MultiPush(kJSCallerSaved | ra.bit());
2031   if (save_doubles_ == kSaveFPRegs) {
2032     CpuFeatures::Scope scope(FPU);
2033     __ MultiPushFPU(kCallerSavedFPU);
2034   }
2035   const int argument_count = 1;
2036   const int fp_argument_count = 0;
2037   const Register scratch = a1;
2038
2039   AllowExternalCallThatCantCauseGC scope(masm);
2040   __ PrepareCallCFunction(argument_count, fp_argument_count, scratch);
2041   __ li(a0, Operand(ExternalReference::isolate_address()));
2042   __ CallCFunction(
2043       ExternalReference::store_buffer_overflow_function(masm->isolate()),
2044       argument_count);
2045   if (save_doubles_ == kSaveFPRegs) {
2046     CpuFeatures::Scope scope(FPU);
2047     __ MultiPopFPU(kCallerSavedFPU);
2048   }
2049
2050   __ MultiPop(kJSCallerSaved | ra.bit());
2051   __ Ret();
2052 }
2053
2054
2055 void UnaryOpStub::PrintName(StringStream* stream) {
2056   const char* op_name = Token::Name(op_);
2057   const char* overwrite_name = NULL;  // Make g++ happy.
2058   switch (mode_) {
2059     case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break;
2060     case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break;
2061   }
2062   stream->Add("UnaryOpStub_%s_%s_%s",
2063               op_name,
2064               overwrite_name,
2065               UnaryOpIC::GetName(operand_type_));
2066 }
2067
2068
2069 // TODO(svenpanne): Use virtual functions instead of switch.
2070 void UnaryOpStub::Generate(MacroAssembler* masm) {
2071   switch (operand_type_) {
2072     case UnaryOpIC::UNINITIALIZED:
2073       GenerateTypeTransition(masm);
2074       break;
2075     case UnaryOpIC::SMI:
2076       GenerateSmiStub(masm);
2077       break;
2078     case UnaryOpIC::HEAP_NUMBER:
2079       GenerateHeapNumberStub(masm);
2080       break;
2081     case UnaryOpIC::GENERIC:
2082       GenerateGenericStub(masm);
2083       break;
2084   }
2085 }
2086
2087
2088 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
2089   // Argument is in a0 and v0 at this point, so we can overwrite a0.
2090   __ li(a2, Operand(Smi::FromInt(op_)));
2091   __ li(a1, Operand(Smi::FromInt(mode_)));
2092   __ li(a0, Operand(Smi::FromInt(operand_type_)));
2093   __ Push(v0, a2, a1, a0);
2094
2095   __ TailCallExternalReference(
2096       ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1);
2097 }
2098
2099
2100 // TODO(svenpanne): Use virtual functions instead of switch.
2101 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
2102   switch (op_) {
2103     case Token::SUB:
2104       GenerateSmiStubSub(masm);
2105       break;
2106     case Token::BIT_NOT:
2107       GenerateSmiStubBitNot(masm);
2108       break;
2109     default:
2110       UNREACHABLE();
2111   }
2112 }
2113
2114
2115 void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
2116   Label non_smi, slow;
2117   GenerateSmiCodeSub(masm, &non_smi, &slow);
2118   __ bind(&non_smi);
2119   __ bind(&slow);
2120   GenerateTypeTransition(masm);
2121 }
2122
2123
2124 void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
2125   Label non_smi;
2126   GenerateSmiCodeBitNot(masm, &non_smi);
2127   __ bind(&non_smi);
2128   GenerateTypeTransition(masm);
2129 }
2130
2131
2132 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
2133                                      Label* non_smi,
2134                                      Label* slow) {
2135   __ JumpIfNotSmi(a0, non_smi);
2136
2137   // The result of negating zero or the smallest negative smi is not a smi.
2138   __ And(t0, a0, ~0x80000000);
2139   __ Branch(slow, eq, t0, Operand(zero_reg));
2140
2141   // Return '0 - value'.
2142   __ Ret(USE_DELAY_SLOT);
2143   __ subu(v0, zero_reg, a0);
2144 }
2145
2146
2147 void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
2148                                         Label* non_smi) {
2149   __ JumpIfNotSmi(a0, non_smi);
2150
2151   // Flip bits and revert inverted smi-tag.
2152   __ Neg(v0, a0);
2153   __ And(v0, v0, ~kSmiTagMask);
2154   __ Ret();
2155 }
2156
2157
2158 // TODO(svenpanne): Use virtual functions instead of switch.
2159 void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
2160   switch (op_) {
2161     case Token::SUB:
2162       GenerateHeapNumberStubSub(masm);
2163       break;
2164     case Token::BIT_NOT:
2165       GenerateHeapNumberStubBitNot(masm);
2166       break;
2167     default:
2168       UNREACHABLE();
2169   }
2170 }
2171
2172
2173 void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
2174   Label non_smi, slow, call_builtin;
2175   GenerateSmiCodeSub(masm, &non_smi, &call_builtin);
2176   __ bind(&non_smi);
2177   GenerateHeapNumberCodeSub(masm, &slow);
2178   __ bind(&slow);
2179   GenerateTypeTransition(masm);
2180   __ bind(&call_builtin);
2181   GenerateGenericCodeFallback(masm);
2182 }
2183
2184
2185 void UnaryOpStub::GenerateHeapNumberStubBitNot(MacroAssembler* masm) {
2186   Label non_smi, slow;
2187   GenerateSmiCodeBitNot(masm, &non_smi);
2188   __ bind(&non_smi);
2189   GenerateHeapNumberCodeBitNot(masm, &slow);
2190   __ bind(&slow);
2191   GenerateTypeTransition(masm);
2192 }
2193
2194
2195 void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
2196                                             Label* slow) {
2197   EmitCheckForHeapNumber(masm, a0, a1, t2, slow);
2198   // a0 is a heap number.  Get a new heap number in a1.
2199   if (mode_ == UNARY_OVERWRITE) {
2200     __ lw(a2, FieldMemOperand(a0, HeapNumber::kExponentOffset));
2201     __ Xor(a2, a2, Operand(HeapNumber::kSignMask));  // Flip sign.
2202     __ sw(a2, FieldMemOperand(a0, HeapNumber::kExponentOffset));
2203   } else {
2204     Label slow_allocate_heapnumber, heapnumber_allocated;
2205     __ AllocateHeapNumber(a1, a2, a3, t2, &slow_allocate_heapnumber);
2206     __ jmp(&heapnumber_allocated);
2207
2208     __ bind(&slow_allocate_heapnumber);
2209     {
2210       FrameScope scope(masm, StackFrame::INTERNAL);
2211       __ push(a0);
2212       __ CallRuntime(Runtime::kNumberAlloc, 0);
2213       __ mov(a1, v0);
2214       __ pop(a0);
2215     }
2216
2217     __ bind(&heapnumber_allocated);
2218     __ lw(a3, FieldMemOperand(a0, HeapNumber::kMantissaOffset));
2219     __ lw(a2, FieldMemOperand(a0, HeapNumber::kExponentOffset));
2220     __ sw(a3, FieldMemOperand(a1, HeapNumber::kMantissaOffset));
2221     __ Xor(a2, a2, Operand(HeapNumber::kSignMask));  // Flip sign.
2222     __ sw(a2, FieldMemOperand(a1, HeapNumber::kExponentOffset));
2223     __ mov(v0, a1);
2224   }
2225   __ Ret();
2226 }
2227
2228
2229 void UnaryOpStub::GenerateHeapNumberCodeBitNot(
2230     MacroAssembler* masm,
2231     Label* slow) {
2232   Label impossible;
2233
2234   EmitCheckForHeapNumber(masm, a0, a1, t2, slow);
2235   // Convert the heap number in a0 to an untagged integer in a1.
2236   __ ConvertToInt32(a0, a1, a2, a3, f0, slow);
2237
2238   // Do the bitwise operation and check if the result fits in a smi.
2239   Label try_float;
2240   __ Neg(a1, a1);
2241   __ Addu(a2, a1, Operand(0x40000000));
2242   __ Branch(&try_float, lt, a2, Operand(zero_reg));
2243
2244   // Tag the result as a smi and we're done.
2245   __ SmiTag(v0, a1);
2246   __ Ret();
2247
2248   // Try to store the result in a heap number.
2249   __ bind(&try_float);
2250   if (mode_ == UNARY_NO_OVERWRITE) {
2251     Label slow_allocate_heapnumber, heapnumber_allocated;
2252     // Allocate a new heap number without zapping v0, which we need if it fails.
2253     __ AllocateHeapNumber(a2, a3, t0, t2, &slow_allocate_heapnumber);
2254     __ jmp(&heapnumber_allocated);
2255
2256     __ bind(&slow_allocate_heapnumber);
2257     {
2258       FrameScope scope(masm, StackFrame::INTERNAL);
2259       __ push(v0);  // Push the heap number, not the untagged int32.
2260       __ CallRuntime(Runtime::kNumberAlloc, 0);
2261       __ mov(a2, v0);  // Move the new heap number into a2.
2262       // Get the heap number into v0, now that the new heap number is in a2.
2263       __ pop(v0);
2264     }
2265
2266     // Convert the heap number in v0 to an untagged integer in a1.
2267     // This can't go slow-case because it's the same number we already
2268     // converted once again.
2269     __ ConvertToInt32(v0, a1, a3, t0, f0, &impossible);
2270     // Negate the result.
2271     __ Xor(a1, a1, -1);
2272
2273     __ bind(&heapnumber_allocated);
2274     __ mov(v0, a2);  // Move newly allocated heap number to v0.
2275   }
2276
2277   if (CpuFeatures::IsSupported(FPU)) {
2278     // Convert the int32 in a1 to the heap number in v0. a2 is corrupted.
2279     CpuFeatures::Scope scope(FPU);
2280     __ mtc1(a1, f0);
2281     __ cvt_d_w(f0, f0);
2282     __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset));
2283     __ Ret();
2284   } else {
2285     // WriteInt32ToHeapNumberStub does not trigger GC, so we do not
2286     // have to set up a frame.
2287     WriteInt32ToHeapNumberStub stub(a1, v0, a2, a3);
2288     __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
2289   }
2290
2291   __ bind(&impossible);
2292   if (FLAG_debug_code) {
2293     __ stop("Incorrect assumption in bit-not stub");
2294   }
2295 }
2296
2297
2298 // TODO(svenpanne): Use virtual functions instead of switch.
2299 void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
2300   switch (op_) {
2301     case Token::SUB:
2302       GenerateGenericStubSub(masm);
2303       break;
2304     case Token::BIT_NOT:
2305       GenerateGenericStubBitNot(masm);
2306       break;
2307     default:
2308       UNREACHABLE();
2309   }
2310 }
2311
2312
2313 void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
2314   Label non_smi, slow;
2315   GenerateSmiCodeSub(masm, &non_smi, &slow);
2316   __ bind(&non_smi);
2317   GenerateHeapNumberCodeSub(masm, &slow);
2318   __ bind(&slow);
2319   GenerateGenericCodeFallback(masm);
2320 }
2321
2322
2323 void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
2324   Label non_smi, slow;
2325   GenerateSmiCodeBitNot(masm, &non_smi);
2326   __ bind(&non_smi);
2327   GenerateHeapNumberCodeBitNot(masm, &slow);
2328   __ bind(&slow);
2329   GenerateGenericCodeFallback(masm);
2330 }
2331
2332
2333 void UnaryOpStub::GenerateGenericCodeFallback(
2334     MacroAssembler* masm) {
2335   // Handle the slow case by jumping to the JavaScript builtin.
2336   __ push(a0);
2337   switch (op_) {
2338     case Token::SUB:
2339       __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
2340       break;
2341     case Token::BIT_NOT:
2342       __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION);
2343       break;
2344     default:
2345       UNREACHABLE();
2346   }
2347 }
2348
2349
2350 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
2351   Label get_result;
2352
2353   __ Push(a1, a0);
2354
2355   __ li(a2, Operand(Smi::FromInt(MinorKey())));
2356   __ li(a1, Operand(Smi::FromInt(op_)));
2357   __ li(a0, Operand(Smi::FromInt(operands_type_)));
2358   __ Push(a2, a1, a0);
2359
2360   __ TailCallExternalReference(
2361       ExternalReference(IC_Utility(IC::kBinaryOp_Patch),
2362                         masm->isolate()),
2363       5,
2364       1);
2365 }
2366
2367
2368 void BinaryOpStub::GenerateTypeTransitionWithSavedArgs(
2369     MacroAssembler* masm) {
2370   UNIMPLEMENTED();
2371 }
2372
2373
2374 void BinaryOpStub::Generate(MacroAssembler* masm) {
2375   // Explicitly allow generation of nested stubs. It is safe here because
2376   // generation code does not use any raw pointers.
2377   AllowStubCallsScope allow_stub_calls(masm, true);
2378   switch (operands_type_) {
2379     case BinaryOpIC::UNINITIALIZED:
2380       GenerateTypeTransition(masm);
2381       break;
2382     case BinaryOpIC::SMI:
2383       GenerateSmiStub(masm);
2384       break;
2385     case BinaryOpIC::INT32:
2386       GenerateInt32Stub(masm);
2387       break;
2388     case BinaryOpIC::HEAP_NUMBER:
2389       GenerateHeapNumberStub(masm);
2390       break;
2391     case BinaryOpIC::ODDBALL:
2392       GenerateOddballStub(masm);
2393       break;
2394     case BinaryOpIC::BOTH_STRING:
2395       GenerateBothStringStub(masm);
2396       break;
2397     case BinaryOpIC::STRING:
2398       GenerateStringStub(masm);
2399       break;
2400     case BinaryOpIC::GENERIC:
2401       GenerateGeneric(masm);
2402       break;
2403     default:
2404       UNREACHABLE();
2405   }
2406 }
2407
2408
2409 void BinaryOpStub::PrintName(StringStream* stream) {
2410   const char* op_name = Token::Name(op_);
2411   const char* overwrite_name;
2412   switch (mode_) {
2413     case NO_OVERWRITE: overwrite_name = "Alloc"; break;
2414     case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
2415     case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
2416     default: overwrite_name = "UnknownOverwrite"; break;
2417   }
2418   stream->Add("BinaryOpStub_%s_%s_%s",
2419               op_name,
2420               overwrite_name,
2421               BinaryOpIC::GetName(operands_type_));
2422 }
2423
2424
2425
2426 void BinaryOpStub::GenerateSmiSmiOperation(MacroAssembler* masm) {
2427   Register left = a1;
2428   Register right = a0;
2429
2430   Register scratch1 = t0;
2431   Register scratch2 = t1;
2432
2433   ASSERT(right.is(a0));
2434   STATIC_ASSERT(kSmiTag == 0);
2435
2436   Label not_smi_result;
2437   switch (op_) {
2438     case Token::ADD:
2439       __ AdduAndCheckForOverflow(v0, left, right, scratch1);
2440       __ RetOnNoOverflow(scratch1);
2441       // No need to revert anything - right and left are intact.
2442       break;
2443     case Token::SUB:
2444       __ SubuAndCheckForOverflow(v0, left, right, scratch1);
2445       __ RetOnNoOverflow(scratch1);
2446       // No need to revert anything - right and left are intact.
2447       break;
2448     case Token::MUL: {
2449       // Remove tag from one of the operands. This way the multiplication result
2450       // will be a smi if it fits the smi range.
2451       __ SmiUntag(scratch1, right);
2452       // Do multiplication.
2453       // lo = lower 32 bits of scratch1 * left.
2454       // hi = higher 32 bits of scratch1 * left.
2455       __ Mult(left, scratch1);
2456       // Check for overflowing the smi range - no overflow if higher 33 bits of
2457       // the result are identical.
2458       __ mflo(scratch1);
2459       __ mfhi(scratch2);
2460       __ sra(scratch1, scratch1, 31);
2461       __ Branch(&not_smi_result, ne, scratch1, Operand(scratch2));
2462       // Go slow on zero result to handle -0.
2463       __ mflo(v0);
2464       __ Ret(ne, v0, Operand(zero_reg));
2465       // We need -0 if we were multiplying a negative number with 0 to get 0.
2466       // We know one of them was zero.
2467       __ Addu(scratch2, right, left);
2468       Label skip;
2469       // ARM uses the 'pl' condition, which is 'ge'.
2470       // Negating it results in 'lt'.
2471       __ Branch(&skip, lt, scratch2, Operand(zero_reg));
2472       ASSERT(Smi::FromInt(0) == 0);
2473       __ Ret(USE_DELAY_SLOT);
2474       __ mov(v0, zero_reg);  // Return smi 0 if the non-zero one was positive.
2475       __ bind(&skip);
2476       // We fall through here if we multiplied a negative number with 0, because
2477       // that would mean we should produce -0.
2478       }
2479       break;
2480     case Token::DIV: {
2481       Label done;
2482       __ SmiUntag(scratch2, right);
2483       __ SmiUntag(scratch1, left);
2484       __ Div(scratch1, scratch2);
2485       // A minor optimization: div may be calculated asynchronously, so we check
2486       // for division by zero before getting the result.
2487       __ Branch(&not_smi_result, eq, scratch2, Operand(zero_reg));
2488       // If the result is 0, we need to make sure the dividsor (right) is
2489       // positive, otherwise it is a -0 case.
2490       // Quotient is in 'lo', remainder is in 'hi'.
2491       // Check for no remainder first.
2492       __ mfhi(scratch1);
2493       __ Branch(&not_smi_result, ne, scratch1, Operand(zero_reg));
2494       __ mflo(scratch1);
2495       __ Branch(&done, ne, scratch1, Operand(zero_reg));
2496       __ Branch(&not_smi_result, lt, scratch2, Operand(zero_reg));
2497       __ bind(&done);
2498       // Check that the signed result fits in a Smi.
2499       __ Addu(scratch2, scratch1, Operand(0x40000000));
2500       __ Branch(&not_smi_result, lt, scratch2, Operand(zero_reg));
2501       __ SmiTag(v0, scratch1);
2502       __ Ret();
2503       }
2504       break;
2505     case Token::MOD: {
2506       Label done;
2507       __ SmiUntag(scratch2, right);
2508       __ SmiUntag(scratch1, left);
2509       __ Div(scratch1, scratch2);
2510       // A minor optimization: div may be calculated asynchronously, so we check
2511       // for division by 0 before calling mfhi.
2512       // Check for zero on the right hand side.
2513       __ Branch(&not_smi_result, eq, scratch2, Operand(zero_reg));
2514       // If the result is 0, we need to make sure the dividend (left) is
2515       // positive (or 0), otherwise it is a -0 case.
2516       // Remainder is in 'hi'.
2517       __ mfhi(scratch2);
2518       __ Branch(&done, ne, scratch2, Operand(zero_reg));
2519       __ Branch(&not_smi_result, lt, scratch1, Operand(zero_reg));
2520       __ bind(&done);
2521       // Check that the signed result fits in a Smi.
2522       __ Addu(scratch1, scratch2, Operand(0x40000000));
2523       __ Branch(&not_smi_result, lt, scratch1, Operand(zero_reg));
2524       __ SmiTag(v0, scratch2);
2525       __ Ret();
2526       }
2527       break;
2528     case Token::BIT_OR:
2529       __ Ret(USE_DELAY_SLOT);
2530       __ or_(v0, left, right);
2531       break;
2532     case Token::BIT_AND:
2533       __ Ret(USE_DELAY_SLOT);
2534       __ and_(v0, left, right);
2535       break;
2536     case Token::BIT_XOR:
2537       __ Ret(USE_DELAY_SLOT);
2538       __ xor_(v0, left, right);
2539       break;
2540     case Token::SAR:
2541       // Remove tags from right operand.
2542       __ GetLeastBitsFromSmi(scratch1, right, 5);
2543       __ srav(scratch1, left, scratch1);
2544       // Smi tag result.
2545       __ And(v0, scratch1, ~kSmiTagMask);
2546       __ Ret();
2547       break;
2548     case Token::SHR:
2549       // Remove tags from operands. We can't do this on a 31 bit number
2550       // because then the 0s get shifted into bit 30 instead of bit 31.
2551       __ SmiUntag(scratch1, left);
2552       __ GetLeastBitsFromSmi(scratch2, right, 5);
2553       __ srlv(v0, scratch1, scratch2);
2554       // Unsigned shift is not allowed to produce a negative number, so
2555       // check the sign bit and the sign bit after Smi tagging.
2556       __ And(scratch1, v0, Operand(0xc0000000));
2557       __ Branch(&not_smi_result, ne, scratch1, Operand(zero_reg));
2558       // Smi tag result.
2559       __ SmiTag(v0);
2560       __ Ret();
2561       break;
2562     case Token::SHL:
2563       // Remove tags from operands.
2564       __ SmiUntag(scratch1, left);
2565       __ GetLeastBitsFromSmi(scratch2, right, 5);
2566       __ sllv(scratch1, scratch1, scratch2);
2567       // Check that the signed result fits in a Smi.
2568       __ Addu(scratch2, scratch1, Operand(0x40000000));
2569       __ Branch(&not_smi_result, lt, scratch2, Operand(zero_reg));
2570       __ SmiTag(v0, scratch1);
2571       __ Ret();
2572       break;
2573     default:
2574       UNREACHABLE();
2575   }
2576   __ bind(&not_smi_result);
2577 }
2578
2579
2580 void BinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
2581                                        bool smi_operands,
2582                                        Label* not_numbers,
2583                                        Label* gc_required) {
2584   Register left = a1;
2585   Register right = a0;
2586   Register scratch1 = t3;
2587   Register scratch2 = t5;
2588   Register scratch3 = t0;
2589
2590   ASSERT(smi_operands || (not_numbers != NULL));
2591   if (smi_operands && FLAG_debug_code) {
2592     __ AbortIfNotSmi(left);
2593     __ AbortIfNotSmi(right);
2594   }
2595
2596   Register heap_number_map = t2;
2597   __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
2598
2599   switch (op_) {
2600     case Token::ADD:
2601     case Token::SUB:
2602     case Token::MUL:
2603     case Token::DIV:
2604     case Token::MOD: {
2605       // Load left and right operands into f12 and f14 or a0/a1 and a2/a3
2606       // depending on whether FPU is available or not.
2607       FloatingPointHelper::Destination destination =
2608           CpuFeatures::IsSupported(FPU) &&
2609           op_ != Token::MOD ?
2610               FloatingPointHelper::kFPURegisters :
2611               FloatingPointHelper::kCoreRegisters;
2612
2613       // Allocate new heap number for result.
2614       Register result = s0;
2615       GenerateHeapResultAllocation(
2616           masm, result, heap_number_map, scratch1, scratch2, gc_required);
2617
2618       // Load the operands.
2619       if (smi_operands) {
2620         FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2);
2621       } else {
2622         FloatingPointHelper::LoadOperands(masm,
2623                                           destination,
2624                                           heap_number_map,
2625                                           scratch1,
2626                                           scratch2,
2627                                           not_numbers);
2628       }
2629
2630       // Calculate the result.
2631       if (destination == FloatingPointHelper::kFPURegisters) {
2632         // Using FPU registers:
2633         // f12: Left value.
2634         // f14: Right value.
2635         CpuFeatures::Scope scope(FPU);
2636         switch (op_) {
2637         case Token::ADD:
2638           __ add_d(f10, f12, f14);
2639           break;
2640         case Token::SUB:
2641           __ sub_d(f10, f12, f14);
2642           break;
2643         case Token::MUL:
2644           __ mul_d(f10, f12, f14);
2645           break;
2646         case Token::DIV:
2647           __ div_d(f10, f12, f14);
2648           break;
2649         default:
2650           UNREACHABLE();
2651         }
2652
2653         // ARM uses a workaround here because of the unaligned HeapNumber
2654         // kValueOffset. On MIPS this workaround is built into sdc1 so
2655         // there's no point in generating even more instructions.
2656         __ sdc1(f10, FieldMemOperand(result, HeapNumber::kValueOffset));
2657         __ Ret(USE_DELAY_SLOT);
2658         __ mov(v0, result);
2659       } else {
2660         // Call the C function to handle the double operation.
2661         FloatingPointHelper::CallCCodeForDoubleOperation(masm,
2662                                                          op_,
2663                                                          result,
2664                                                          scratch1);
2665         if (FLAG_debug_code) {
2666           __ stop("Unreachable code.");
2667         }
2668       }
2669       break;
2670     }
2671     case Token::BIT_OR:
2672     case Token::BIT_XOR:
2673     case Token::BIT_AND:
2674     case Token::SAR:
2675     case Token::SHR:
2676     case Token::SHL: {
2677       if (smi_operands) {
2678         __ SmiUntag(a3, left);
2679         __ SmiUntag(a2, right);
2680       } else {
2681         // Convert operands to 32-bit integers. Right in a2 and left in a3.
2682         FloatingPointHelper::ConvertNumberToInt32(masm,
2683                                                   left,
2684                                                   a3,
2685                                                   heap_number_map,
2686                                                   scratch1,
2687                                                   scratch2,
2688                                                   scratch3,
2689                                                   f0,
2690                                                   not_numbers);
2691         FloatingPointHelper::ConvertNumberToInt32(masm,
2692                                                   right,
2693                                                   a2,
2694                                                   heap_number_map,
2695                                                   scratch1,
2696                                                   scratch2,
2697                                                   scratch3,
2698                                                   f0,
2699                                                   not_numbers);
2700       }
2701       Label result_not_a_smi;
2702       switch (op_) {
2703         case Token::BIT_OR:
2704           __ Or(a2, a3, Operand(a2));
2705           break;
2706         case Token::BIT_XOR:
2707           __ Xor(a2, a3, Operand(a2));
2708           break;
2709         case Token::BIT_AND:
2710           __ And(a2, a3, Operand(a2));
2711           break;
2712         case Token::SAR:
2713           // Use only the 5 least significant bits of the shift count.
2714           __ GetLeastBitsFromInt32(a2, a2, 5);
2715           __ srav(a2, a3, a2);
2716           break;
2717         case Token::SHR:
2718           // Use only the 5 least significant bits of the shift count.
2719           __ GetLeastBitsFromInt32(a2, a2, 5);
2720           __ srlv(a2, a3, a2);
2721           // SHR is special because it is required to produce a positive answer.
2722           // The code below for writing into heap numbers isn't capable of
2723           // writing the register as an unsigned int so we go to slow case if we
2724           // hit this case.
2725           if (CpuFeatures::IsSupported(FPU)) {
2726             __ Branch(&result_not_a_smi, lt, a2, Operand(zero_reg));
2727           } else {
2728             __ Branch(not_numbers, lt, a2, Operand(zero_reg));
2729           }
2730           break;
2731         case Token::SHL:
2732           // Use only the 5 least significant bits of the shift count.
2733           __ GetLeastBitsFromInt32(a2, a2, 5);
2734           __ sllv(a2, a3, a2);
2735           break;
2736         default:
2737           UNREACHABLE();
2738       }
2739       // Check that the *signed* result fits in a smi.
2740       __ Addu(a3, a2, Operand(0x40000000));
2741       __ Branch(&result_not_a_smi, lt, a3, Operand(zero_reg));
2742       __ SmiTag(v0, a2);
2743       __ Ret();
2744
2745       // Allocate new heap number for result.
2746       __ bind(&result_not_a_smi);
2747       Register result = t1;
2748       if (smi_operands) {
2749         __ AllocateHeapNumber(
2750             result, scratch1, scratch2, heap_number_map, gc_required);
2751       } else {
2752         GenerateHeapResultAllocation(
2753             masm, result, heap_number_map, scratch1, scratch2, gc_required);
2754       }
2755
2756       // a2: Answer as signed int32.
2757       // t1: Heap number to write answer into.
2758
2759       // Nothing can go wrong now, so move the heap number to v0, which is the
2760       // result.
2761       __ mov(v0, t1);
2762
2763       if (CpuFeatures::IsSupported(FPU)) {
2764         // Convert the int32 in a2 to the heap number in a0. As
2765         // mentioned above SHR needs to always produce a positive result.
2766         CpuFeatures::Scope scope(FPU);
2767         __ mtc1(a2, f0);
2768         if (op_ == Token::SHR) {
2769           __ Cvt_d_uw(f0, f0, f22);
2770         } else {
2771           __ cvt_d_w(f0, f0);
2772         }
2773         // ARM uses a workaround here because of the unaligned HeapNumber
2774         // kValueOffset. On MIPS this workaround is built into sdc1 so
2775         // there's no point in generating even more instructions.
2776         __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset));
2777         __ Ret();
2778       } else {
2779         // Tail call that writes the int32 in a2 to the heap number in v0, using
2780         // a3 and a0 as scratch. v0 is preserved and returned.
2781         WriteInt32ToHeapNumberStub stub(a2, v0, a3, a0);
2782         __ TailCallStub(&stub);
2783       }
2784       break;
2785     }
2786     default:
2787       UNREACHABLE();
2788   }
2789 }
2790
2791
2792 // Generate the smi code. If the operation on smis are successful this return is
2793 // generated. If the result is not a smi and heap number allocation is not
2794 // requested the code falls through. If number allocation is requested but a
2795 // heap number cannot be allocated the code jumps to the lable gc_required.
2796 void BinaryOpStub::GenerateSmiCode(
2797     MacroAssembler* masm,
2798     Label* use_runtime,
2799     Label* gc_required,
2800     SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
2801   Label not_smis;
2802
2803   Register left = a1;
2804   Register right = a0;
2805   Register scratch1 = t3;
2806   Register scratch2 = t5;
2807
2808   // Perform combined smi check on both operands.
2809   __ Or(scratch1, left, Operand(right));
2810   STATIC_ASSERT(kSmiTag == 0);
2811   __ JumpIfNotSmi(scratch1, &not_smis);
2812
2813   // If the smi-smi operation results in a smi return is generated.
2814   GenerateSmiSmiOperation(masm);
2815
2816   // If heap number results are possible generate the result in an allocated
2817   // heap number.
2818   if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) {
2819     GenerateFPOperation(masm, true, use_runtime, gc_required);
2820   }
2821   __ bind(&not_smis);
2822 }
2823
2824
2825 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
2826   Label not_smis, call_runtime;
2827
2828   if (result_type_ == BinaryOpIC::UNINITIALIZED ||
2829       result_type_ == BinaryOpIC::SMI) {
2830     // Only allow smi results.
2831     GenerateSmiCode(masm, &call_runtime, NULL, NO_HEAPNUMBER_RESULTS);
2832   } else {
2833     // Allow heap number result and don't make a transition if a heap number
2834     // cannot be allocated.
2835     GenerateSmiCode(masm,
2836                     &call_runtime,
2837                     &call_runtime,
2838                     ALLOW_HEAPNUMBER_RESULTS);
2839   }
2840
2841   // Code falls through if the result is not returned as either a smi or heap
2842   // number.
2843   GenerateTypeTransition(masm);
2844
2845   __ bind(&call_runtime);
2846   GenerateCallRuntime(masm);
2847 }
2848
2849
2850 void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
2851   ASSERT(operands_type_ == BinaryOpIC::STRING);
2852   // Try to add arguments as strings, otherwise, transition to the generic
2853   // BinaryOpIC type.
2854   GenerateAddStrings(masm);
2855   GenerateTypeTransition(masm);
2856 }
2857
2858
2859 void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
2860   Label call_runtime;
2861   ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING);
2862   ASSERT(op_ == Token::ADD);
2863   // If both arguments are strings, call the string add stub.
2864   // Otherwise, do a transition.
2865
2866   // Registers containing left and right operands respectively.
2867   Register left = a1;
2868   Register right = a0;
2869
2870   // Test if left operand is a string.
2871   __ JumpIfSmi(left, &call_runtime);
2872   __ GetObjectType(left, a2, a2);
2873   __ Branch(&call_runtime, ge, a2, Operand(FIRST_NONSTRING_TYPE));
2874
2875   // Test if right operand is a string.
2876   __ JumpIfSmi(right, &call_runtime);
2877   __ GetObjectType(right, a2, a2);
2878   __ Branch(&call_runtime, ge, a2, Operand(FIRST_NONSTRING_TYPE));
2879
2880   StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB);
2881   GenerateRegisterArgsPush(masm);
2882   __ TailCallStub(&string_add_stub);
2883
2884   __ bind(&call_runtime);
2885   GenerateTypeTransition(masm);
2886 }
2887
2888
2889 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
2890   ASSERT(operands_type_ == BinaryOpIC::INT32);
2891
2892   Register left = a1;
2893   Register right = a0;
2894   Register scratch1 = t3;
2895   Register scratch2 = t5;
2896   FPURegister double_scratch = f0;
2897   FPURegister single_scratch = f6;
2898
2899   Register heap_number_result = no_reg;
2900   Register heap_number_map = t2;
2901   __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
2902
2903   Label call_runtime;
2904   // Labels for type transition, used for wrong input or output types.
2905   // Both label are currently actually bound to the same position. We use two
2906   // different label to differentiate the cause leading to type transition.
2907   Label transition;
2908
2909   // Smi-smi fast case.
2910   Label skip;
2911   __ Or(scratch1, left, right);
2912   __ JumpIfNotSmi(scratch1, &skip);
2913   GenerateSmiSmiOperation(masm);
2914   // Fall through if the result is not a smi.
2915   __ bind(&skip);
2916
2917   switch (op_) {
2918     case Token::ADD:
2919     case Token::SUB:
2920     case Token::MUL:
2921     case Token::DIV:
2922     case Token::MOD: {
2923       // Load both operands and check that they are 32-bit integer.
2924       // Jump to type transition if they are not. The registers a0 and a1 (right
2925       // and left) are preserved for the runtime call.
2926       FloatingPointHelper::Destination destination =
2927           (CpuFeatures::IsSupported(FPU) && op_ != Token::MOD)
2928               ? FloatingPointHelper::kFPURegisters
2929               : FloatingPointHelper::kCoreRegisters;
2930
2931       FloatingPointHelper::LoadNumberAsInt32Double(masm,
2932                                                    right,
2933                                                    destination,
2934                                                    f14,
2935                                                    a2,
2936                                                    a3,
2937                                                    heap_number_map,
2938                                                    scratch1,
2939                                                    scratch2,
2940                                                    f2,
2941                                                    &transition);
2942       FloatingPointHelper::LoadNumberAsInt32Double(masm,
2943                                                    left,
2944                                                    destination,
2945                                                    f12,
2946                                                    t0,
2947                                                    t1,
2948                                                    heap_number_map,
2949                                                    scratch1,
2950                                                    scratch2,
2951                                                    f2,
2952                                                    &transition);
2953
2954       if (destination == FloatingPointHelper::kFPURegisters) {
2955         CpuFeatures::Scope scope(FPU);
2956         Label return_heap_number;
2957         switch (op_) {
2958           case Token::ADD:
2959             __ add_d(f10, f12, f14);
2960             break;
2961           case Token::SUB:
2962             __ sub_d(f10, f12, f14);
2963             break;
2964           case Token::MUL:
2965             __ mul_d(f10, f12, f14);
2966             break;
2967           case Token::DIV:
2968             __ div_d(f10, f12, f14);
2969             break;
2970           default:
2971             UNREACHABLE();
2972         }
2973
2974         if (op_ != Token::DIV) {
2975           // These operations produce an integer result.
2976           // Try to return a smi if we can.
2977           // Otherwise return a heap number if allowed, or jump to type
2978           // transition.
2979
2980           Register except_flag = scratch2;
2981           __ EmitFPUTruncate(kRoundToZero,
2982                              single_scratch,
2983                              f10,
2984                              scratch1,
2985                              except_flag);
2986
2987           if (result_type_ <= BinaryOpIC::INT32) {
2988             // If except_flag != 0, result does not fit in a 32-bit integer.
2989             __ Branch(&transition, ne, except_flag, Operand(zero_reg));
2990           }
2991
2992           // Check if the result fits in a smi.
2993           __ mfc1(scratch1, single_scratch);
2994           __ Addu(scratch2, scratch1, Operand(0x40000000));
2995           // If not try to return a heap number.
2996           __ Branch(&return_heap_number, lt, scratch2, Operand(zero_reg));
2997           // Check for minus zero. Return heap number for minus zero.
2998           Label not_zero;
2999           __ Branch(&not_zero, ne, scratch1, Operand(zero_reg));
3000           __ mfc1(scratch2, f11);
3001           __ And(scratch2, scratch2, HeapNumber::kSignMask);
3002           __ Branch(&return_heap_number, ne, scratch2, Operand(zero_reg));
3003           __ bind(&not_zero);
3004
3005           // Tag the result and return.
3006           __ SmiTag(v0, scratch1);
3007           __ Ret();
3008         } else {
3009           // DIV just falls through to allocating a heap number.
3010         }
3011
3012         __ bind(&return_heap_number);
3013         // Return a heap number, or fall through to type transition or runtime
3014         // call if we can't.
3015         if (result_type_ >= ((op_ == Token::DIV) ? BinaryOpIC::HEAP_NUMBER
3016                                                  : BinaryOpIC::INT32)) {
3017           // We are using FPU registers so s0 is available.
3018           heap_number_result = s0;
3019           GenerateHeapResultAllocation(masm,
3020                                        heap_number_result,
3021                                        heap_number_map,
3022                                        scratch1,
3023                                        scratch2,
3024                                        &call_runtime);
3025           __ mov(v0, heap_number_result);
3026           __ sdc1(f10, FieldMemOperand(v0, HeapNumber::kValueOffset));
3027           __ Ret();
3028         }
3029
3030         // A DIV operation expecting an integer result falls through
3031         // to type transition.
3032
3033       } else {
3034         // We preserved a0 and a1 to be able to call runtime.
3035         // Save the left value on the stack.
3036         __ Push(t1, t0);
3037
3038         Label pop_and_call_runtime;
3039
3040         // Allocate a heap number to store the result.
3041         heap_number_result = s0;
3042         GenerateHeapResultAllocation(masm,
3043                                      heap_number_result,
3044                                      heap_number_map,
3045                                      scratch1,
3046                                      scratch2,
3047                                      &pop_and_call_runtime);
3048
3049         // Load the left value from the value saved on the stack.
3050         __ Pop(a1, a0);
3051
3052         // Call the C function to handle the double operation.
3053         FloatingPointHelper::CallCCodeForDoubleOperation(
3054             masm, op_, heap_number_result, scratch1);
3055         if (FLAG_debug_code) {
3056           __ stop("Unreachable code.");
3057         }
3058
3059         __ bind(&pop_and_call_runtime);
3060         __ Drop(2);
3061         __ Branch(&call_runtime);
3062       }
3063
3064       break;
3065     }
3066
3067     case Token::BIT_OR:
3068     case Token::BIT_XOR:
3069     case Token::BIT_AND:
3070     case Token::SAR:
3071     case Token::SHR:
3072     case Token::SHL: {
3073       Label return_heap_number;
3074       Register scratch3 = t1;
3075       // Convert operands to 32-bit integers. Right in a2 and left in a3. The
3076       // registers a0 and a1 (right and left) are preserved for the runtime
3077       // call.
3078       FloatingPointHelper::LoadNumberAsInt32(masm,
3079                                              left,
3080                                              a3,
3081                                              heap_number_map,
3082                                              scratch1,
3083                                              scratch2,
3084                                              scratch3,
3085                                              f0,
3086                                              &transition);
3087       FloatingPointHelper::LoadNumberAsInt32(masm,
3088                                              right,
3089                                              a2,
3090                                              heap_number_map,
3091                                              scratch1,
3092                                              scratch2,
3093                                              scratch3,
3094                                              f0,
3095                                              &transition);
3096
3097       // The ECMA-262 standard specifies that, for shift operations, only the
3098       // 5 least significant bits of the shift value should be used.
3099       switch (op_) {
3100         case Token::BIT_OR:
3101           __ Or(a2, a3, Operand(a2));
3102           break;
3103         case Token::BIT_XOR:
3104           __ Xor(a2, a3, Operand(a2));
3105           break;
3106         case Token::BIT_AND:
3107           __ And(a2, a3, Operand(a2));
3108           break;
3109         case Token::SAR:
3110           __ And(a2, a2, Operand(0x1f));
3111           __ srav(a2, a3, a2);
3112           break;
3113         case Token::SHR:
3114           __ And(a2, a2, Operand(0x1f));
3115           __ srlv(a2, a3, a2);
3116           // SHR is special because it is required to produce a positive answer.
3117           // We only get a negative result if the shift value (a2) is 0.
3118           // This result cannot be respresented as a signed 32-bit integer, try
3119           // to return a heap number if we can.
3120           // The non FPU code does not support this special case, so jump to
3121           // runtime if we don't support it.
3122           if (CpuFeatures::IsSupported(FPU)) {
3123             __ Branch((result_type_ <= BinaryOpIC::INT32)
3124                         ? &transition
3125                         : &return_heap_number,
3126                        lt,
3127                        a2,
3128                        Operand(zero_reg));
3129           } else {
3130             __ Branch((result_type_ <= BinaryOpIC::INT32)
3131                         ? &transition
3132                         : &call_runtime,
3133                        lt,
3134                        a2,
3135                        Operand(zero_reg));
3136           }
3137           break;
3138         case Token::SHL:
3139           __ And(a2, a2, Operand(0x1f));
3140           __ sllv(a2, a3, a2);
3141           break;
3142         default:
3143           UNREACHABLE();
3144       }
3145
3146       // Check if the result fits in a smi.
3147       __ Addu(scratch1, a2, Operand(0x40000000));
3148       // If not try to return a heap number. (We know the result is an int32.)
3149       __ Branch(&return_heap_number, lt, scratch1, Operand(zero_reg));
3150       // Tag the result and return.
3151       __ SmiTag(v0, a2);
3152       __ Ret();
3153
3154       __ bind(&return_heap_number);
3155       heap_number_result = t1;
3156       GenerateHeapResultAllocation(masm,
3157                                    heap_number_result,
3158                                    heap_number_map,
3159                                    scratch1,
3160                                    scratch2,
3161                                    &call_runtime);
3162
3163       if (CpuFeatures::IsSupported(FPU)) {
3164         CpuFeatures::Scope scope(FPU);
3165
3166         if (op_ != Token::SHR) {
3167           // Convert the result to a floating point value.
3168           __ mtc1(a2, double_scratch);
3169           __ cvt_d_w(double_scratch, double_scratch);
3170         } else {
3171           // The result must be interpreted as an unsigned 32-bit integer.
3172           __ mtc1(a2, double_scratch);
3173           __ Cvt_d_uw(double_scratch, double_scratch, single_scratch);
3174         }
3175
3176         // Store the result.
3177         __ mov(v0, heap_number_result);
3178         __ sdc1(double_scratch, FieldMemOperand(v0, HeapNumber::kValueOffset));
3179         __ Ret();
3180       } else {
3181         // Tail call that writes the int32 in a2 to the heap number in v0, using
3182         // a3 and a0 as scratch. v0 is preserved and returned.
3183         __ mov(a0, t1);
3184         WriteInt32ToHeapNumberStub stub(a2, v0, a3, a0);
3185         __ TailCallStub(&stub);
3186       }
3187
3188       break;
3189     }
3190
3191     default:
3192       UNREACHABLE();
3193   }
3194
3195   // We never expect DIV to yield an integer result, so we always generate
3196   // type transition code for DIV operations expecting an integer result: the
3197   // code will fall through to this type transition.
3198   if (transition.is_linked() ||
3199       ((op_ == Token::DIV) && (result_type_ <= BinaryOpIC::INT32))) {
3200     __ bind(&transition);
3201     GenerateTypeTransition(masm);
3202   }
3203
3204   __ bind(&call_runtime);
3205   GenerateCallRuntime(masm);
3206 }
3207
3208
3209 void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
3210   Label call_runtime;
3211
3212   if (op_ == Token::ADD) {
3213     // Handle string addition here, because it is the only operation
3214     // that does not do a ToNumber conversion on the operands.
3215     GenerateAddStrings(masm);
3216   }
3217
3218   // Convert oddball arguments to numbers.
3219   Label check, done;
3220   __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
3221   __ Branch(&check, ne, a1, Operand(t0));
3222   if (Token::IsBitOp(op_)) {
3223     __ li(a1, Operand(Smi::FromInt(0)));
3224   } else {
3225     __ LoadRoot(a1, Heap::kNanValueRootIndex);
3226   }
3227   __ jmp(&done);
3228   __ bind(&check);
3229   __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
3230   __ Branch(&done, ne, a0, Operand(t0));
3231   if (Token::IsBitOp(op_)) {
3232     __ li(a0, Operand(Smi::FromInt(0)));
3233   } else {
3234     __ LoadRoot(a0, Heap::kNanValueRootIndex);
3235   }
3236   __ bind(&done);
3237
3238   GenerateHeapNumberStub(masm);
3239 }
3240
3241
3242 void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
3243   Label call_runtime;
3244   GenerateFPOperation(masm, false, &call_runtime, &call_runtime);
3245
3246   __ bind(&call_runtime);
3247   GenerateCallRuntime(masm);
3248 }
3249
3250
3251 void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
3252   Label call_runtime, call_string_add_or_runtime;
3253
3254   GenerateSmiCode(masm, &call_runtime, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
3255
3256   GenerateFPOperation(masm, false, &call_string_add_or_runtime, &call_runtime);
3257
3258   __ bind(&call_string_add_or_runtime);
3259   if (op_ == Token::ADD) {
3260     GenerateAddStrings(masm);
3261   }
3262
3263   __ bind(&call_runtime);
3264   GenerateCallRuntime(masm);
3265 }
3266
3267
3268 void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
3269   ASSERT(op_ == Token::ADD);
3270   Label left_not_string, call_runtime;
3271
3272   Register left = a1;
3273   Register right = a0;
3274
3275   // Check if left argument is a string.
3276   __ JumpIfSmi(left, &left_not_string);
3277   __ GetObjectType(left, a2, a2);
3278   __ Branch(&left_not_string, ge, a2, Operand(FIRST_NONSTRING_TYPE));
3279
3280   StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB);
3281   GenerateRegisterArgsPush(masm);
3282   __ TailCallStub(&string_add_left_stub);
3283
3284   // Left operand is not a string, test right.
3285   __ bind(&left_not_string);
3286   __ JumpIfSmi(right, &call_runtime);
3287   __ GetObjectType(right, a2, a2);
3288   __ Branch(&call_runtime, ge, a2, Operand(FIRST_NONSTRING_TYPE));
3289
3290   StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB);
3291   GenerateRegisterArgsPush(masm);
3292   __ TailCallStub(&string_add_right_stub);
3293
3294   // At least one argument is not a string.
3295   __ bind(&call_runtime);
3296 }
3297
3298
3299 void BinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
3300   GenerateRegisterArgsPush(masm);
3301   switch (op_) {
3302     case Token::ADD:
3303       __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION);
3304       break;
3305     case Token::SUB:
3306       __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION);
3307       break;
3308     case Token::MUL:
3309       __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION);
3310       break;
3311     case Token::DIV:
3312       __ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION);
3313       break;
3314     case Token::MOD:
3315       __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION);
3316       break;
3317     case Token::BIT_OR:
3318       __ InvokeBuiltin(Builtins::BIT_OR, JUMP_FUNCTION);
3319       break;
3320     case Token::BIT_AND:
3321       __ InvokeBuiltin(Builtins::BIT_AND, JUMP_FUNCTION);
3322       break;
3323     case Token::BIT_XOR:
3324       __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_FUNCTION);
3325       break;
3326     case Token::SAR:
3327       __ InvokeBuiltin(Builtins::SAR, JUMP_FUNCTION);
3328       break;
3329     case Token::SHR:
3330       __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION);
3331       break;
3332     case Token::SHL:
3333       __ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION);
3334       break;
3335     default:
3336       UNREACHABLE();
3337   }
3338 }
3339
3340
3341 void BinaryOpStub::GenerateHeapResultAllocation(
3342     MacroAssembler* masm,
3343     Register result,
3344     Register heap_number_map,
3345     Register scratch1,
3346     Register scratch2,
3347     Label* gc_required) {
3348
3349   // Code below will scratch result if allocation fails. To keep both arguments
3350   // intact for the runtime call result cannot be one of these.
3351   ASSERT(!result.is(a0) && !result.is(a1));
3352
3353   if (mode_ == OVERWRITE_LEFT || mode_ == OVERWRITE_RIGHT) {
3354     Label skip_allocation, allocated;
3355     Register overwritable_operand = mode_ == OVERWRITE_LEFT ? a1 : a0;
3356     // If the overwritable operand is already an object, we skip the
3357     // allocation of a heap number.
3358     __ JumpIfNotSmi(overwritable_operand, &skip_allocation);
3359     // Allocate a heap number for the result.
3360     __ AllocateHeapNumber(
3361         result, scratch1, scratch2, heap_number_map, gc_required);
3362     __ Branch(&allocated);
3363     __ bind(&skip_allocation);
3364     // Use object holding the overwritable operand for result.
3365     __ mov(result, overwritable_operand);
3366     __ bind(&allocated);
3367   } else {
3368     ASSERT(mode_ == NO_OVERWRITE);
3369     __ AllocateHeapNumber(
3370         result, scratch1, scratch2, heap_number_map, gc_required);
3371   }
3372 }
3373
3374
3375 void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
3376   __ Push(a1, a0);
3377 }
3378
3379
3380
3381 void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
3382   // Untagged case: double input in f4, double result goes
3383   //   into f4.
3384   // Tagged case: tagged input on top of stack and in a0,
3385   //   tagged result (heap number) goes into v0.
3386
3387   Label input_not_smi;
3388   Label loaded;
3389   Label calculate;
3390   Label invalid_cache;
3391   const Register scratch0 = t5;
3392   const Register scratch1 = t3;
3393   const Register cache_entry = a0;
3394   const bool tagged = (argument_type_ == TAGGED);
3395
3396   if (CpuFeatures::IsSupported(FPU)) {
3397     CpuFeatures::Scope scope(FPU);
3398
3399     if (tagged) {
3400       // Argument is a number and is on stack and in a0.
3401       // Load argument and check if it is a smi.
3402       __ JumpIfNotSmi(a0, &input_not_smi);
3403
3404       // Input is a smi. Convert to double and load the low and high words
3405       // of the double into a2, a3.
3406       __ sra(t0, a0, kSmiTagSize);
3407       __ mtc1(t0, f4);
3408       __ cvt_d_w(f4, f4);
3409       __ Move(a2, a3, f4);
3410       __ Branch(&loaded);
3411
3412       __ bind(&input_not_smi);
3413       // Check if input is a HeapNumber.
3414       __ CheckMap(a0,
3415                   a1,
3416                   Heap::kHeapNumberMapRootIndex,
3417                   &calculate,
3418                   DONT_DO_SMI_CHECK);
3419       // Input is a HeapNumber. Store the
3420       // low and high words into a2, a3.
3421       __ lw(a2, FieldMemOperand(a0, HeapNumber::kValueOffset));
3422       __ lw(a3, FieldMemOperand(a0, HeapNumber::kValueOffset + 4));
3423     } else {
3424       // Input is untagged double in f4. Output goes to f4.
3425       __ Move(a2, a3, f4);
3426     }
3427     __ bind(&loaded);
3428     // a2 = low 32 bits of double value.
3429     // a3 = high 32 bits of double value.
3430     // Compute hash (the shifts are arithmetic):
3431     //   h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
3432     __ Xor(a1, a2, a3);
3433     __ sra(t0, a1, 16);
3434     __ Xor(a1, a1, t0);
3435     __ sra(t0, a1, 8);
3436     __ Xor(a1, a1, t0);
3437     ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize));
3438     __ And(a1, a1, Operand(TranscendentalCache::SubCache::kCacheSize - 1));
3439
3440     // a2 = low 32 bits of double value.
3441     // a3 = high 32 bits of double value.
3442     // a1 = TranscendentalCache::hash(double value).
3443     __ li(cache_entry, Operand(
3444         ExternalReference::transcendental_cache_array_address(
3445             masm->isolate())));
3446     // a0 points to cache array.
3447     __ lw(cache_entry, MemOperand(cache_entry, type_ * sizeof(
3448         Isolate::Current()->transcendental_cache()->caches_[0])));
3449     // a0 points to the cache for the type type_.
3450     // If NULL, the cache hasn't been initialized yet, so go through runtime.
3451     __ Branch(&invalid_cache, eq, cache_entry, Operand(zero_reg));
3452
3453 #ifdef DEBUG
3454     // Check that the layout of cache elements match expectations.
3455     { TranscendentalCache::SubCache::Element test_elem[2];
3456       char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
3457       char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
3458       char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
3459       char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
3460       char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
3461       CHECK_EQ(12, elem2_start - elem_start);  // Two uint_32's and a pointer.
3462       CHECK_EQ(0, elem_in0 - elem_start);
3463       CHECK_EQ(kIntSize, elem_in1 - elem_start);
3464       CHECK_EQ(2 * kIntSize, elem_out - elem_start);
3465     }
3466 #endif
3467
3468     // Find the address of the a1'st entry in the cache, i.e., &a0[a1*12].
3469     __ sll(t0, a1, 1);
3470     __ Addu(a1, a1, t0);
3471     __ sll(t0, a1, 2);
3472     __ Addu(cache_entry, cache_entry, t0);
3473
3474     // Check if cache matches: Double value is stored in uint32_t[2] array.
3475     __ lw(t0, MemOperand(cache_entry, 0));
3476     __ lw(t1, MemOperand(cache_entry, 4));
3477     __ lw(t2, MemOperand(cache_entry, 8));
3478     __ Branch(&calculate, ne, a2, Operand(t0));
3479     __ Branch(&calculate, ne, a3, Operand(t1));
3480     // Cache hit. Load result, cleanup and return.
3481     Counters* counters = masm->isolate()->counters();
3482     __ IncrementCounter(
3483         counters->transcendental_cache_hit(), 1, scratch0, scratch1);
3484     if (tagged) {
3485       // Pop input value from stack and load result into v0.
3486       __ Drop(1);
3487       __ mov(v0, t2);
3488     } else {
3489       // Load result into f4.
3490       __ ldc1(f4, FieldMemOperand(t2, HeapNumber::kValueOffset));
3491     }
3492     __ Ret();
3493   }  // if (CpuFeatures::IsSupported(FPU))
3494
3495   __ bind(&calculate);
3496   Counters* counters = masm->isolate()->counters();
3497   __ IncrementCounter(
3498       counters->transcendental_cache_miss(), 1, scratch0, scratch1);
3499   if (tagged) {
3500     __ bind(&invalid_cache);
3501     __ TailCallExternalReference(ExternalReference(RuntimeFunction(),
3502                                                    masm->isolate()),
3503                                  1,
3504                                  1);
3505   } else {
3506     if (!CpuFeatures::IsSupported(FPU)) UNREACHABLE();
3507     CpuFeatures::Scope scope(FPU);
3508
3509     Label no_update;
3510     Label skip_cache;
3511     const Register heap_number_map = t2;
3512
3513     // Call C function to calculate the result and update the cache.
3514     // Register a0 holds precalculated cache entry address; preserve
3515     // it on the stack and pop it into register cache_entry after the
3516     // call.
3517     __ Push(cache_entry, a2, a3);
3518     GenerateCallCFunction(masm, scratch0);
3519     __ GetCFunctionDoubleResult(f4);
3520
3521     // Try to update the cache. If we cannot allocate a
3522     // heap number, we return the result without updating.
3523     __ Pop(cache_entry, a2, a3);
3524     __ LoadRoot(t1, Heap::kHeapNumberMapRootIndex);
3525     __ AllocateHeapNumber(t2, scratch0, scratch1, t1, &no_update);
3526     __ sdc1(f4, FieldMemOperand(t2, HeapNumber::kValueOffset));
3527
3528     __ sw(a2, MemOperand(cache_entry, 0 * kPointerSize));
3529     __ sw(a3, MemOperand(cache_entry, 1 * kPointerSize));
3530     __ sw(t2, MemOperand(cache_entry, 2 * kPointerSize));
3531
3532     __ Ret(USE_DELAY_SLOT);
3533     __ mov(v0, cache_entry);
3534
3535     __ bind(&invalid_cache);
3536     // The cache is invalid. Call runtime which will recreate the
3537     // cache.
3538     __ LoadRoot(t1, Heap::kHeapNumberMapRootIndex);
3539     __ AllocateHeapNumber(a0, scratch0, scratch1, t1, &skip_cache);
3540     __ sdc1(f4, FieldMemOperand(a0, HeapNumber::kValueOffset));
3541     {
3542       FrameScope scope(masm, StackFrame::INTERNAL);
3543       __ push(a0);
3544       __ CallRuntime(RuntimeFunction(), 1);
3545     }
3546     __ ldc1(f4, FieldMemOperand(v0, HeapNumber::kValueOffset));
3547     __ Ret();
3548
3549     __ bind(&skip_cache);
3550     // Call C function to calculate the result and answer directly
3551     // without updating the cache.
3552     GenerateCallCFunction(masm, scratch0);
3553     __ GetCFunctionDoubleResult(f4);
3554     __ bind(&no_update);
3555
3556     // We return the value in f4 without adding it to the cache, but
3557     // we cause a scavenging GC so that future allocations will succeed.
3558     {
3559       FrameScope scope(masm, StackFrame::INTERNAL);
3560
3561       // Allocate an aligned object larger than a HeapNumber.
3562       ASSERT(4 * kPointerSize >= HeapNumber::kSize);
3563       __ li(scratch0, Operand(4 * kPointerSize));
3564       __ push(scratch0);
3565       __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace);
3566     }
3567     __ Ret();
3568   }
3569 }
3570
3571
3572 void TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm,
3573                                                     Register scratch) {
3574   __ push(ra);
3575   __ PrepareCallCFunction(2, scratch);
3576   if (IsMipsSoftFloatABI) {
3577     __ Move(a0, a1, f4);
3578   } else {
3579     __ mov_d(f12, f4);
3580   }
3581   AllowExternalCallThatCantCauseGC scope(masm);
3582   Isolate* isolate = masm->isolate();
3583   switch (type_) {
3584     case TranscendentalCache::SIN:
3585       __ CallCFunction(
3586           ExternalReference::math_sin_double_function(isolate),
3587           0, 1);
3588       break;
3589     case TranscendentalCache::COS:
3590       __ CallCFunction(
3591           ExternalReference::math_cos_double_function(isolate),
3592           0, 1);
3593       break;
3594     case TranscendentalCache::TAN:
3595       __ CallCFunction(ExternalReference::math_tan_double_function(isolate),
3596           0, 1);
3597       break;
3598     case TranscendentalCache::LOG:
3599       __ CallCFunction(
3600           ExternalReference::math_log_double_function(isolate),
3601           0, 1);
3602       break;
3603     default:
3604       UNIMPLEMENTED();
3605       break;
3606   }
3607   __ pop(ra);
3608 }
3609
3610
3611 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
3612   switch (type_) {
3613     // Add more cases when necessary.
3614     case TranscendentalCache::SIN: return Runtime::kMath_sin;
3615     case TranscendentalCache::COS: return Runtime::kMath_cos;
3616     case TranscendentalCache::TAN: return Runtime::kMath_tan;
3617     case TranscendentalCache::LOG: return Runtime::kMath_log;
3618     default:
3619       UNIMPLEMENTED();
3620       return Runtime::kAbort;
3621   }
3622 }
3623
3624
3625 void StackCheckStub::Generate(MacroAssembler* masm) {
3626   __ TailCallRuntime(Runtime::kStackGuard, 0, 1);
3627 }
3628
3629
3630 void InterruptStub::Generate(MacroAssembler* masm) {
3631   __ TailCallRuntime(Runtime::kInterrupt, 0, 1);
3632 }
3633
3634
3635 void MathPowStub::Generate(MacroAssembler* masm) {
3636   CpuFeatures::Scope fpu_scope(FPU);
3637   const Register base = a1;
3638   const Register exponent = a2;
3639   const Register heapnumbermap = t1;
3640   const Register heapnumber = v0;
3641   const DoubleRegister double_base = f2;
3642   const DoubleRegister double_exponent = f4;
3643   const DoubleRegister double_result = f0;
3644   const DoubleRegister double_scratch = f6;
3645   const FPURegister single_scratch = f8;
3646   const Register scratch = t5;
3647   const Register scratch2 = t3;
3648
3649   Label call_runtime, done, int_exponent;
3650   if (exponent_type_ == ON_STACK) {
3651     Label base_is_smi, unpack_exponent;
3652     // The exponent and base are supplied as arguments on the stack.
3653     // This can only happen if the stub is called from non-optimized code.
3654     // Load input parameters from stack to double registers.
3655     __ lw(base, MemOperand(sp, 1 * kPointerSize));
3656     __ lw(exponent, MemOperand(sp, 0 * kPointerSize));
3657
3658     __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex);
3659
3660     __ UntagAndJumpIfSmi(scratch, base, &base_is_smi);
3661     __ lw(scratch, FieldMemOperand(base, JSObject::kMapOffset));
3662     __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap));
3663
3664     __ ldc1(double_base, FieldMemOperand(base, HeapNumber::kValueOffset));
3665     __ jmp(&unpack_exponent);
3666
3667     __ bind(&base_is_smi);
3668     __ mtc1(scratch, single_scratch);
3669     __ cvt_d_w(double_base, single_scratch);
3670     __ bind(&unpack_exponent);
3671
3672     __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent);
3673
3674     __ lw(scratch, FieldMemOperand(exponent, JSObject::kMapOffset));
3675     __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap));
3676     __ ldc1(double_exponent,
3677             FieldMemOperand(exponent, HeapNumber::kValueOffset));
3678   } else if (exponent_type_ == TAGGED) {
3679     // Base is already in double_base.
3680     __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent);
3681
3682     __ ldc1(double_exponent,
3683             FieldMemOperand(exponent, HeapNumber::kValueOffset));
3684   }
3685
3686   if (exponent_type_ != INTEGER) {
3687     Label int_exponent_convert;
3688     // Detect integer exponents stored as double.
3689     __ EmitFPUTruncate(kRoundToMinusInf,
3690                        single_scratch,
3691                        double_exponent,
3692                        scratch,
3693                        scratch2,
3694                        kCheckForInexactConversion);
3695     // scratch2 == 0 means there was no conversion error.
3696     __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg));
3697
3698     if (exponent_type_ == ON_STACK) {
3699       // Detect square root case.  Crankshaft detects constant +/-0.5 at
3700       // compile time and uses DoMathPowHalf instead.  We then skip this check
3701       // for non-constant cases of +/-0.5 as these hardly occur.
3702       Label not_plus_half;
3703
3704       // Test for 0.5.
3705       __ Move(double_scratch, 0.5);
3706       __ BranchF(USE_DELAY_SLOT,
3707                  &not_plus_half,
3708                  NULL,
3709                  ne,
3710                  double_exponent,
3711                  double_scratch);
3712       // double_scratch can be overwritten in the delay slot.
3713       // Calculates square root of base.  Check for the special case of
3714       // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13).
3715       __ Move(double_scratch, -V8_INFINITY);
3716       __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch);
3717       __ neg_d(double_result, double_scratch);
3718
3719       // Add +0 to convert -0 to +0.
3720       __ add_d(double_scratch, double_base, kDoubleRegZero);
3721       __ sqrt_d(double_result, double_scratch);
3722       __ jmp(&done);
3723
3724       __ bind(&not_plus_half);
3725       __ Move(double_scratch, -0.5);
3726       __ BranchF(USE_DELAY_SLOT,
3727                  &call_runtime,
3728                  NULL,
3729                  ne,
3730                  double_exponent,
3731                  double_scratch);
3732       // double_scratch can be overwritten in the delay slot.
3733       // Calculates square root of base.  Check for the special case of
3734       // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13).
3735       __ Move(double_scratch, -V8_INFINITY);
3736       __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch);
3737       __ Move(double_result, kDoubleRegZero);
3738
3739       // Add +0 to convert -0 to +0.
3740       __ add_d(double_scratch, double_base, kDoubleRegZero);
3741       __ Move(double_result, 1);
3742       __ sqrt_d(double_scratch, double_scratch);
3743       __ div_d(double_result, double_result, double_scratch);
3744       __ jmp(&done);
3745     }
3746
3747     __ push(ra);
3748     {
3749       AllowExternalCallThatCantCauseGC scope(masm);
3750       __ PrepareCallCFunction(0, 2, scratch);
3751       __ SetCallCDoubleArguments(double_base, double_exponent);
3752       __ CallCFunction(
3753           ExternalReference::power_double_double_function(masm->isolate()),
3754           0, 2);
3755     }
3756     __ pop(ra);
3757     __ GetCFunctionDoubleResult(double_result);
3758     __ jmp(&done);
3759
3760     __ bind(&int_exponent_convert);
3761     __ mfc1(scratch, single_scratch);
3762   }
3763
3764   // Calculate power with integer exponent.
3765   __ bind(&int_exponent);
3766
3767   // Get two copies of exponent in the registers scratch and exponent.
3768   if (exponent_type_ == INTEGER) {
3769     __ mov(scratch, exponent);
3770   } else {
3771     // Exponent has previously been stored into scratch as untagged integer.
3772     __ mov(exponent, scratch);
3773   }
3774
3775   __ mov_d(double_scratch, double_base);  // Back up base.
3776   __ Move(double_result, 1.0);
3777
3778   // Get absolute value of exponent.
3779   Label positive_exponent;
3780   __ Branch(&positive_exponent, ge, scratch, Operand(zero_reg));
3781   __ Subu(scratch, zero_reg, scratch);
3782   __ bind(&positive_exponent);
3783
3784   Label while_true, no_carry, loop_end;
3785   __ bind(&while_true);
3786
3787   __ And(scratch2, scratch, 1);
3788
3789   __ Branch(&no_carry, eq, scratch2, Operand(zero_reg));
3790   __ mul_d(double_result, double_result, double_scratch);
3791   __ bind(&no_carry);
3792
3793   __ sra(scratch, scratch, 1);
3794
3795   __ Branch(&loop_end, eq, scratch, Operand(zero_reg));
3796   __ mul_d(double_scratch, double_scratch, double_scratch);
3797
3798   __ Branch(&while_true);
3799
3800   __ bind(&loop_end);
3801
3802   __ Branch(&done, ge, exponent, Operand(zero_reg));
3803   __ Move(double_scratch, 1.0);
3804   __ div_d(double_result, double_scratch, double_result);
3805   // Test whether result is zero.  Bail out to check for subnormal result.
3806   // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
3807   __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero);
3808
3809   // double_exponent may not contain the exponent value if the input was a
3810   // smi.  We set it with exponent value before bailing out.
3811   __ mtc1(exponent, single_scratch);
3812   __ cvt_d_w(double_exponent, single_scratch);
3813
3814   // Returning or bailing out.
3815   Counters* counters = masm->isolate()->counters();
3816   if (exponent_type_ == ON_STACK) {
3817     // The arguments are still on the stack.
3818     __ bind(&call_runtime);
3819     __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1);
3820
3821     // The stub is called from non-optimized code, which expects the result
3822     // as heap number in exponent.
3823     __ bind(&done);
3824     __ AllocateHeapNumber(
3825         heapnumber, scratch, scratch2, heapnumbermap, &call_runtime);
3826     __ sdc1(double_result,
3827             FieldMemOperand(heapnumber, HeapNumber::kValueOffset));
3828     ASSERT(heapnumber.is(v0));
3829     __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2);
3830     __ DropAndRet(2);
3831   } else {
3832     __ push(ra);
3833     {
3834       AllowExternalCallThatCantCauseGC scope(masm);
3835       __ PrepareCallCFunction(0, 2, scratch);
3836       __ SetCallCDoubleArguments(double_base, double_exponent);
3837       __ CallCFunction(
3838           ExternalReference::power_double_double_function(masm->isolate()),
3839           0, 2);
3840     }
3841     __ pop(ra);
3842     __ GetCFunctionDoubleResult(double_result);
3843
3844     __ bind(&done);
3845     __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2);
3846     __ Ret();
3847   }
3848 }
3849
3850
3851 bool CEntryStub::NeedsImmovableCode() {
3852   return true;
3853 }
3854
3855
3856 bool CEntryStub::IsPregenerated() {
3857   return (!save_doubles_ || ISOLATE->fp_stubs_generated()) &&
3858           result_size_ == 1;
3859 }
3860
3861
3862 void CodeStub::GenerateStubsAheadOfTime() {
3863   CEntryStub::GenerateAheadOfTime();
3864   WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime();
3865   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime();
3866   RecordWriteStub::GenerateFixedRegStubsAheadOfTime();
3867 }
3868
3869
3870 void CodeStub::GenerateFPStubs() {
3871   CEntryStub save_doubles(1, kSaveFPRegs);
3872   Handle<Code> code = save_doubles.GetCode();
3873   code->set_is_pregenerated(true);
3874   StoreBufferOverflowStub stub(kSaveFPRegs);
3875   stub.GetCode()->set_is_pregenerated(true);
3876   code->GetIsolate()->set_fp_stubs_generated(true);
3877 }
3878
3879
3880 void CEntryStub::GenerateAheadOfTime() {
3881   CEntryStub stub(1, kDontSaveFPRegs);
3882   Handle<Code> code = stub.GetCode();
3883   code->set_is_pregenerated(true);
3884 }
3885
3886
3887 void CEntryStub::GenerateCore(MacroAssembler* masm,
3888                               Label* throw_normal_exception,
3889                               Label* throw_termination_exception,
3890                               Label* throw_out_of_memory_exception,
3891                               bool do_gc,
3892                               bool always_allocate) {
3893   // v0: result parameter for PerformGC, if any
3894   // s0: number of arguments including receiver (C callee-saved)
3895   // s1: pointer to the first argument          (C callee-saved)
3896   // s2: pointer to builtin function            (C callee-saved)
3897
3898   Isolate* isolate = masm->isolate();
3899
3900   if (do_gc) {
3901     // Move result passed in v0 into a0 to call PerformGC.
3902     __ mov(a0, v0);
3903     __ PrepareCallCFunction(1, 0, a1);
3904     __ CallCFunction(ExternalReference::perform_gc_function(isolate), 1, 0);
3905   }
3906
3907   ExternalReference scope_depth =
3908       ExternalReference::heap_always_allocate_scope_depth(isolate);
3909   if (always_allocate) {
3910     __ li(a0, Operand(scope_depth));
3911     __ lw(a1, MemOperand(a0));
3912     __ Addu(a1, a1, Operand(1));
3913     __ sw(a1, MemOperand(a0));
3914   }
3915
3916   // Prepare arguments for C routine.
3917   // a0 = argc
3918   __ mov(a0, s0);
3919   // a1 = argv (set in the delay slot after find_ra below).
3920
3921   // We are calling compiled C/C++ code. a0 and a1 hold our two arguments. We
3922   // also need to reserve the 4 argument slots on the stack.
3923
3924   __ AssertStackIsAligned();
3925
3926   __ li(a2, Operand(ExternalReference::isolate_address()));
3927
3928   // To let the GC traverse the return address of the exit frames, we need to
3929   // know where the return address is. The CEntryStub is unmovable, so
3930   // we can store the address on the stack to be able to find it again and
3931   // we never have to restore it, because it will not change.
3932   { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm);
3933     // This branch-and-link sequence is needed to find the current PC on mips,
3934     // saved to the ra register.
3935     // Use masm-> here instead of the double-underscore macro since extra
3936     // coverage code can interfere with the proper calculation of ra.
3937     Label find_ra;
3938     masm->bal(&find_ra);  // bal exposes branch delay slot.
3939     masm->mov(a1, s1);
3940     masm->bind(&find_ra);
3941
3942     // Adjust the value in ra to point to the correct return location, 2nd
3943     // instruction past the real call into C code (the jalr(t9)), and push it.
3944     // This is the return address of the exit frame.
3945     const int kNumInstructionsToJump = 5;
3946     masm->Addu(ra, ra, kNumInstructionsToJump * kPointerSize);
3947     masm->sw(ra, MemOperand(sp));  // This spot was reserved in EnterExitFrame.
3948     // Stack space reservation moved to the branch delay slot below.
3949     // Stack is still aligned.
3950
3951     // Call the C routine.
3952     masm->mov(t9, s2);  // Function pointer to t9 to conform to ABI for PIC.
3953     masm->jalr(t9);
3954     // Set up sp in the delay slot.
3955     masm->addiu(sp, sp, -kCArgsSlotsSize);
3956     // Make sure the stored 'ra' points to this position.
3957     ASSERT_EQ(kNumInstructionsToJump,
3958               masm->InstructionsGeneratedSince(&find_ra));
3959   }
3960
3961   if (always_allocate) {
3962     // It's okay to clobber a2 and a3 here. v0 & v1 contain result.
3963     __ li(a2, Operand(scope_depth));
3964     __ lw(a3, MemOperand(a2));
3965     __ Subu(a3, a3, Operand(1));
3966     __ sw(a3, MemOperand(a2));
3967   }
3968
3969   // Check for failure result.
3970   Label failure_returned;
3971   STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
3972   __ addiu(a2, v0, 1);
3973   __ andi(t0, a2, kFailureTagMask);
3974   __ Branch(USE_DELAY_SLOT, &failure_returned, eq, t0, Operand(zero_reg));
3975   // Restore stack (remove arg slots) in branch delay slot.
3976   __ addiu(sp, sp, kCArgsSlotsSize);
3977
3978
3979   // Exit C frame and return.
3980   // v0:v1: result
3981   // sp: stack pointer
3982   // fp: frame pointer
3983   __ LeaveExitFrame(save_doubles_, s0, true);
3984
3985   // Check if we should retry or throw exception.
3986   Label retry;
3987   __ bind(&failure_returned);
3988   STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
3989   __ andi(t0, v0, ((1 << kFailureTypeTagSize) - 1) << kFailureTagSize);
3990   __ Branch(&retry, eq, t0, Operand(zero_reg));
3991
3992   // Special handling of out of memory exceptions.
3993   Failure* out_of_memory = Failure::OutOfMemoryException();
3994   __ Branch(USE_DELAY_SLOT,
3995             throw_out_of_memory_exception,
3996             eq,
3997             v0,
3998             Operand(reinterpret_cast<int32_t>(out_of_memory)));
3999   // If we throw the OOM exception, the value of a3 doesn't matter.
4000   // Any instruction can be in the delay slot that's not a jump.
4001
4002   // Retrieve the pending exception and clear the variable.
4003   __ LoadRoot(a3, Heap::kTheHoleValueRootIndex);
4004   __ li(t0, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
4005                                       isolate)));
4006   __ lw(v0, MemOperand(t0));
4007   __ sw(a3, MemOperand(t0));
4008
4009   // Special handling of termination exceptions which are uncatchable
4010   // by javascript code.
4011   __ LoadRoot(t0, Heap::kTerminationExceptionRootIndex);
4012   __ Branch(throw_termination_exception, eq, v0, Operand(t0));
4013
4014   // Handle normal exception.
4015   __ jmp(throw_normal_exception);
4016
4017   __ bind(&retry);
4018   // Last failure (v0) will be moved to (a0) for parameter when retrying.
4019 }
4020
4021
4022 void CEntryStub::Generate(MacroAssembler* masm) {
4023   // Called from JavaScript; parameters are on stack as if calling JS function
4024   // s0: number of arguments including receiver
4025   // s1: size of arguments excluding receiver
4026   // s2: pointer to builtin function
4027   // fp: frame pointer    (restored after C call)
4028   // sp: stack pointer    (restored as callee's sp after C call)
4029   // cp: current context  (C callee-saved)
4030
4031   // NOTE: Invocations of builtins may return failure objects
4032   // instead of a proper result. The builtin entry handles
4033   // this by performing a garbage collection and retrying the
4034   // builtin once.
4035
4036   // NOTE: s0-s2 hold the arguments of this function instead of a0-a2.
4037   // The reason for this is that these arguments would need to be saved anyway
4038   // so it's faster to set them up directly.
4039   // See MacroAssembler::PrepareCEntryArgs and PrepareCEntryFunction.
4040
4041   // Compute the argv pointer in a callee-saved register.
4042   __ Addu(s1, sp, s1);
4043
4044   // Enter the exit frame that transitions from JavaScript to C++.
4045   FrameScope scope(masm, StackFrame::MANUAL);
4046   __ EnterExitFrame(save_doubles_);
4047
4048   // s0: number of arguments (C callee-saved)
4049   // s1: pointer to first argument (C callee-saved)
4050   // s2: pointer to builtin function (C callee-saved)
4051
4052   Label throw_normal_exception;
4053   Label throw_termination_exception;
4054   Label throw_out_of_memory_exception;
4055
4056   // Call into the runtime system.
4057   GenerateCore(masm,
4058                &throw_normal_exception,
4059                &throw_termination_exception,
4060                &throw_out_of_memory_exception,
4061                false,
4062                false);
4063
4064   // Do space-specific GC and retry runtime call.
4065   GenerateCore(masm,
4066                &throw_normal_exception,
4067                &throw_termination_exception,
4068                &throw_out_of_memory_exception,
4069                true,
4070                false);
4071
4072   // Do full GC and retry runtime call one final time.
4073   Failure* failure = Failure::InternalError();
4074   __ li(v0, Operand(reinterpret_cast<int32_t>(failure)));
4075   GenerateCore(masm,
4076                &throw_normal_exception,
4077                &throw_termination_exception,
4078                &throw_out_of_memory_exception,
4079                true,
4080                true);
4081
4082   __ bind(&throw_out_of_memory_exception);
4083   // Set external caught exception to false.
4084   Isolate* isolate = masm->isolate();
4085   ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress,
4086                                     isolate);
4087   __ li(a0, Operand(false, RelocInfo::NONE));
4088   __ li(a2, Operand(external_caught));
4089   __ sw(a0, MemOperand(a2));
4090
4091   // Set pending exception and v0 to out of memory exception.
4092   Failure* out_of_memory = Failure::OutOfMemoryException();
4093   __ li(v0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
4094   __ li(a2, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
4095                                       isolate)));
4096   __ sw(v0, MemOperand(a2));
4097   // Fall through to the next label.
4098
4099   __ bind(&throw_termination_exception);
4100   __ ThrowUncatchable(v0);
4101
4102   __ bind(&throw_normal_exception);
4103   __ Throw(v0);
4104 }
4105
4106
4107 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
4108   Label invoke, handler_entry, exit;
4109   Isolate* isolate = masm->isolate();
4110
4111   // Registers:
4112   // a0: entry address
4113   // a1: function
4114   // a2: receiver
4115   // a3: argc
4116   //
4117   // Stack:
4118   // 4 args slots
4119   // args
4120
4121   // Save callee saved registers on the stack.
4122   __ MultiPush(kCalleeSaved | ra.bit());
4123
4124   if (CpuFeatures::IsSupported(FPU)) {
4125     CpuFeatures::Scope scope(FPU);
4126     // Save callee-saved FPU registers.
4127     __ MultiPushFPU(kCalleeSavedFPU);
4128     // Set up the reserved register for 0.0.
4129     __ Move(kDoubleRegZero, 0.0);
4130   }
4131
4132
4133   // Load argv in s0 register.
4134   int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize;
4135   if (CpuFeatures::IsSupported(FPU)) {
4136     offset_to_argv += kNumCalleeSavedFPU * kDoubleSize;
4137   }
4138
4139   __ InitializeRootRegister();
4140   __ lw(s0, MemOperand(sp, offset_to_argv + kCArgsSlotsSize));
4141
4142   // We build an EntryFrame.
4143   __ li(t3, Operand(-1));  // Push a bad frame pointer to fail if it is used.
4144   int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
4145   __ li(t2, Operand(Smi::FromInt(marker)));
4146   __ li(t1, Operand(Smi::FromInt(marker)));
4147   __ li(t0, Operand(ExternalReference(Isolate::kCEntryFPAddress,
4148                                       isolate)));
4149   __ lw(t0, MemOperand(t0));
4150   __ Push(t3, t2, t1, t0);
4151   // Set up frame pointer for the frame to be pushed.
4152   __ addiu(fp, sp, -EntryFrameConstants::kCallerFPOffset);
4153
4154   // Registers:
4155   // a0: entry_address
4156   // a1: function
4157   // a2: receiver_pointer
4158   // a3: argc
4159   // s0: argv
4160   //
4161   // Stack:
4162   // caller fp          |
4163   // function slot      | entry frame
4164   // context slot       |
4165   // bad fp (0xff...f)  |
4166   // callee saved registers + ra
4167   // 4 args slots
4168   // args
4169
4170   // If this is the outermost JS call, set js_entry_sp value.
4171   Label non_outermost_js;
4172   ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate);
4173   __ li(t1, Operand(ExternalReference(js_entry_sp)));
4174   __ lw(t2, MemOperand(t1));
4175   __ Branch(&non_outermost_js, ne, t2, Operand(zero_reg));
4176   __ sw(fp, MemOperand(t1));
4177   __ li(t0, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
4178   Label cont;
4179   __ b(&cont);
4180   __ nop();   // Branch delay slot nop.
4181   __ bind(&non_outermost_js);
4182   __ li(t0, Operand(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)));
4183   __ bind(&cont);
4184   __ push(t0);
4185
4186   // Jump to a faked try block that does the invoke, with a faked catch
4187   // block that sets the pending exception.
4188   __ jmp(&invoke);
4189   __ bind(&handler_entry);
4190   handler_offset_ = handler_entry.pos();
4191   // Caught exception: Store result (exception) in the pending exception
4192   // field in the JSEnv and return a failure sentinel.  Coming in here the
4193   // fp will be invalid because the PushTryHandler below sets it to 0 to
4194   // signal the existence of the JSEntry frame.
4195   __ li(t0, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
4196                                       isolate)));
4197   __ sw(v0, MemOperand(t0));  // We come back from 'invoke'. result is in v0.
4198   __ li(v0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));
4199   __ b(&exit);  // b exposes branch delay slot.
4200   __ nop();   // Branch delay slot nop.
4201
4202   // Invoke: Link this frame into the handler chain.  There's only one
4203   // handler block in this code object, so its index is 0.
4204   __ bind(&invoke);
4205   __ PushTryHandler(StackHandler::JS_ENTRY, 0);
4206   // If an exception not caught by another handler occurs, this handler
4207   // returns control to the code after the bal(&invoke) above, which
4208   // restores all kCalleeSaved registers (including cp and fp) to their
4209   // saved values before returning a failure to C.
4210
4211   // Clear any pending exceptions.
4212   __ LoadRoot(t1, Heap::kTheHoleValueRootIndex);
4213   __ li(t0, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
4214                                       isolate)));
4215   __ sw(t1, MemOperand(t0));
4216
4217   // Invoke the function by calling through JS entry trampoline builtin.
4218   // Notice that we cannot store a reference to the trampoline code directly in
4219   // this stub, because runtime stubs are not traversed when doing GC.
4220
4221   // Registers:
4222   // a0: entry_address
4223   // a1: function
4224   // a2: receiver_pointer
4225   // a3: argc
4226   // s0: argv
4227   //
4228   // Stack:
4229   // handler frame
4230   // entry frame
4231   // callee saved registers + ra
4232   // 4 args slots
4233   // args
4234
4235   if (is_construct) {
4236     ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
4237                                       isolate);
4238     __ li(t0, Operand(construct_entry));
4239   } else {
4240     ExternalReference entry(Builtins::kJSEntryTrampoline, masm->isolate());
4241     __ li(t0, Operand(entry));
4242   }
4243   __ lw(t9, MemOperand(t0));  // Deref address.
4244
4245   // Call JSEntryTrampoline.
4246   __ addiu(t9, t9, Code::kHeaderSize - kHeapObjectTag);
4247   __ Call(t9);
4248
4249   // Unlink this frame from the handler chain.
4250   __ PopTryHandler();
4251
4252   __ bind(&exit);  // v0 holds result
4253   // Check if the current stack frame is marked as the outermost JS frame.
4254   Label non_outermost_js_2;
4255   __ pop(t1);
4256   __ Branch(&non_outermost_js_2,
4257             ne,
4258             t1,
4259             Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
4260   __ li(t1, Operand(ExternalReference(js_entry_sp)));
4261   __ sw(zero_reg, MemOperand(t1));
4262   __ bind(&non_outermost_js_2);
4263
4264   // Restore the top frame descriptors from the stack.
4265   __ pop(t1);
4266   __ li(t0, Operand(ExternalReference(Isolate::kCEntryFPAddress,
4267                                       isolate)));
4268   __ sw(t1, MemOperand(t0));
4269
4270   // Reset the stack to the callee saved registers.
4271   __ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset);
4272
4273   if (CpuFeatures::IsSupported(FPU)) {
4274     CpuFeatures::Scope scope(FPU);
4275     // Restore callee-saved fpu registers.
4276     __ MultiPopFPU(kCalleeSavedFPU);
4277   }
4278
4279   // Restore callee saved registers from the stack.
4280   __ MultiPop(kCalleeSaved | ra.bit());
4281   // Return.
4282   __ Jump(ra);
4283 }
4284
4285
4286 // Uses registers a0 to t0.
4287 // Expected input (depending on whether args are in registers or on the stack):
4288 // * object: a0 or at sp + 1 * kPointerSize.
4289 // * function: a1 or at sp.
4290 //
4291 // An inlined call site may have been generated before calling this stub.
4292 // In this case the offset to the inline site to patch is passed on the stack,
4293 // in the safepoint slot for register t0.
4294 void InstanceofStub::Generate(MacroAssembler* masm) {
4295   // Call site inlining and patching implies arguments in registers.
4296   ASSERT(HasArgsInRegisters() || !HasCallSiteInlineCheck());
4297   // ReturnTrueFalse is only implemented for inlined call sites.
4298   ASSERT(!ReturnTrueFalseObject() || HasCallSiteInlineCheck());
4299
4300   // Fixed register usage throughout the stub:
4301   const Register object = a0;  // Object (lhs).
4302   Register map = a3;  // Map of the object.
4303   const Register function = a1;  // Function (rhs).
4304   const Register prototype = t0;  // Prototype of the function.
4305   const Register inline_site = t5;
4306   const Register scratch = a2;
4307
4308   const int32_t kDeltaToLoadBoolResult = 5 * kPointerSize;
4309
4310   Label slow, loop, is_instance, is_not_instance, not_js_object;
4311
4312   if (!HasArgsInRegisters()) {
4313     __ lw(object, MemOperand(sp, 1 * kPointerSize));
4314     __ lw(function, MemOperand(sp, 0));
4315   }
4316
4317   // Check that the left hand is a JS object and load map.
4318   __ JumpIfSmi(object, &not_js_object);
4319   __ IsObjectJSObjectType(object, map, scratch, &not_js_object);
4320
4321   // If there is a call site cache don't look in the global cache, but do the
4322   // real lookup and update the call site cache.
4323   if (!HasCallSiteInlineCheck()) {
4324     Label miss;
4325     __ LoadRoot(at, Heap::kInstanceofCacheFunctionRootIndex);
4326     __ Branch(&miss, ne, function, Operand(at));
4327     __ LoadRoot(at, Heap::kInstanceofCacheMapRootIndex);
4328     __ Branch(&miss, ne, map, Operand(at));
4329     __ LoadRoot(v0, Heap::kInstanceofCacheAnswerRootIndex);
4330     __ DropAndRet(HasArgsInRegisters() ? 0 : 2);
4331
4332     __ bind(&miss);
4333   }
4334
4335   // Get the prototype of the function.
4336   __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true);
4337
4338   // Check that the function prototype is a JS object.
4339   __ JumpIfSmi(prototype, &slow);
4340   __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
4341
4342   // Update the global instanceof or call site inlined cache with the current
4343   // map and function. The cached answer will be set when it is known below.
4344   if (!HasCallSiteInlineCheck()) {
4345     __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
4346     __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex);
4347   } else {
4348     ASSERT(HasArgsInRegisters());
4349     // Patch the (relocated) inlined map check.
4350
4351     // The offset was stored in t0 safepoint slot.
4352     // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal).
4353     __ LoadFromSafepointRegisterSlot(scratch, t0);
4354     __ Subu(inline_site, ra, scratch);
4355     // Get the map location in scratch and patch it.
4356     __ GetRelocatedValue(inline_site, scratch, v1);  // v1 used as scratch.
4357     __ sw(map, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
4358   }
4359
4360   // Register mapping: a3 is object map and t0 is function prototype.
4361   // Get prototype of object into a2.
4362   __ lw(scratch, FieldMemOperand(map, Map::kPrototypeOffset));
4363
4364   // We don't need map any more. Use it as a scratch register.
4365   Register scratch2 = map;
4366   map = no_reg;
4367
4368   // Loop through the prototype chain looking for the function prototype.
4369   __ LoadRoot(scratch2, Heap::kNullValueRootIndex);
4370   __ bind(&loop);
4371   __ Branch(&is_instance, eq, scratch, Operand(prototype));
4372   __ Branch(&is_not_instance, eq, scratch, Operand(scratch2));
4373   __ lw(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset));
4374   __ lw(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset));
4375   __ Branch(&loop);
4376
4377   __ bind(&is_instance);
4378   ASSERT(Smi::FromInt(0) == 0);
4379   if (!HasCallSiteInlineCheck()) {
4380     __ mov(v0, zero_reg);
4381     __ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex);
4382   } else {
4383     // Patch the call site to return true.
4384     __ LoadRoot(v0, Heap::kTrueValueRootIndex);
4385     __ Addu(inline_site, inline_site, Operand(kDeltaToLoadBoolResult));
4386     // Get the boolean result location in scratch and patch it.
4387     __ PatchRelocatedValue(inline_site, scratch, v0);
4388
4389     if (!ReturnTrueFalseObject()) {
4390       ASSERT_EQ(Smi::FromInt(0), 0);
4391       __ mov(v0, zero_reg);
4392     }
4393   }
4394   __ DropAndRet(HasArgsInRegisters() ? 0 : 2);
4395
4396   __ bind(&is_not_instance);
4397   if (!HasCallSiteInlineCheck()) {
4398     __ li(v0, Operand(Smi::FromInt(1)));
4399     __ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex);
4400   } else {
4401     // Patch the call site to return false.
4402     __ LoadRoot(v0, Heap::kFalseValueRootIndex);
4403     __ Addu(inline_site, inline_site, Operand(kDeltaToLoadBoolResult));
4404     // Get the boolean result location in scratch and patch it.
4405     __ PatchRelocatedValue(inline_site, scratch, v0);
4406
4407     if (!ReturnTrueFalseObject()) {
4408       __ li(v0, Operand(Smi::FromInt(1)));
4409     }
4410   }
4411
4412   __ DropAndRet(HasArgsInRegisters() ? 0 : 2);
4413
4414   Label object_not_null, object_not_null_or_smi;
4415   __ bind(&not_js_object);
4416   // Before null, smi and string value checks, check that the rhs is a function
4417   // as for a non-function rhs an exception needs to be thrown.
4418   __ JumpIfSmi(function, &slow);
4419   __ GetObjectType(function, scratch2, scratch);
4420   __ Branch(&slow, ne, scratch, Operand(JS_FUNCTION_TYPE));
4421
4422   // Null is not instance of anything.
4423   __ Branch(&object_not_null,
4424             ne,
4425             scratch,
4426             Operand(masm->isolate()->factory()->null_value()));
4427   __ li(v0, Operand(Smi::FromInt(1)));
4428   __ DropAndRet(HasArgsInRegisters() ? 0 : 2);
4429
4430   __ bind(&object_not_null);
4431   // Smi values are not instances of anything.
4432   __ JumpIfNotSmi(object, &object_not_null_or_smi);
4433   __ li(v0, Operand(Smi::FromInt(1)));
4434   __ DropAndRet(HasArgsInRegisters() ? 0 : 2);
4435
4436   __ bind(&object_not_null_or_smi);
4437   // String values are not instances of anything.
4438   __ IsObjectJSStringType(object, scratch, &slow);
4439   __ li(v0, Operand(Smi::FromInt(1)));
4440   __ DropAndRet(HasArgsInRegisters() ? 0 : 2);
4441
4442   // Slow-case.  Tail call builtin.
4443   __ bind(&slow);
4444   if (!ReturnTrueFalseObject()) {
4445     if (HasArgsInRegisters()) {
4446       __ Push(a0, a1);
4447     }
4448   __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
4449   } else {
4450     {
4451       FrameScope scope(masm, StackFrame::INTERNAL);
4452       __ Push(a0, a1);
4453       __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
4454     }
4455     __ mov(a0, v0);
4456     __ LoadRoot(v0, Heap::kTrueValueRootIndex);
4457     __ DropAndRet(HasArgsInRegisters() ? 0 : 2, eq, a0, Operand(zero_reg));
4458     __ LoadRoot(v0, Heap::kFalseValueRootIndex);
4459     __ DropAndRet(HasArgsInRegisters() ? 0 : 2);
4460   }
4461 }
4462
4463
4464 Register InstanceofStub::left() { return a0; }
4465
4466
4467 Register InstanceofStub::right() { return a1; }
4468
4469
4470 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
4471   // The displacement is the offset of the last parameter (if any)
4472   // relative to the frame pointer.
4473   const int kDisplacement =
4474       StandardFrameConstants::kCallerSPOffset - kPointerSize;
4475
4476   // Check that the key is a smiGenerateReadElement.
4477   Label slow;
4478   __ JumpIfNotSmi(a1, &slow);
4479
4480   // Check if the calling frame is an arguments adaptor frame.
4481   Label adaptor;
4482   __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
4483   __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset));
4484   __ Branch(&adaptor,
4485             eq,
4486             a3,
4487             Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
4488
4489   // Check index (a1) against formal parameters count limit passed in
4490   // through register a0. Use unsigned comparison to get negative
4491   // check for free.
4492   __ Branch(&slow, hs, a1, Operand(a0));
4493
4494   // Read the argument from the stack and return it.
4495   __ subu(a3, a0, a1);
4496   __ sll(t3, a3, kPointerSizeLog2 - kSmiTagSize);
4497   __ Addu(a3, fp, Operand(t3));
4498   __ lw(v0, MemOperand(a3, kDisplacement));
4499   __ Ret();
4500
4501   // Arguments adaptor case: Check index (a1) against actual arguments
4502   // limit found in the arguments adaptor frame. Use unsigned
4503   // comparison to get negative check for free.
4504   __ bind(&adaptor);
4505   __ lw(a0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
4506   __ Branch(&slow, Ugreater_equal, a1, Operand(a0));
4507
4508   // Read the argument from the adaptor frame and return it.
4509   __ subu(a3, a0, a1);
4510   __ sll(t3, a3, kPointerSizeLog2 - kSmiTagSize);
4511   __ Addu(a3, a2, Operand(t3));
4512   __ lw(v0, MemOperand(a3, kDisplacement));
4513   __ Ret();
4514
4515   // Slow-case: Handle non-smi or out-of-bounds access to arguments
4516   // by calling the runtime system.
4517   __ bind(&slow);
4518   __ push(a1);
4519   __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
4520 }
4521
4522
4523 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
4524   // sp[0] : number of parameters
4525   // sp[4] : receiver displacement
4526   // sp[8] : function
4527   // Check if the calling frame is an arguments adaptor frame.
4528   Label runtime;
4529   __ lw(a3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
4530   __ lw(a2, MemOperand(a3, StandardFrameConstants::kContextOffset));
4531   __ Branch(&runtime,
4532             ne,
4533             a2,
4534             Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
4535
4536   // Patch the arguments.length and the parameters pointer in the current frame.
4537   __ lw(a2, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset));
4538   __ sw(a2, MemOperand(sp, 0 * kPointerSize));
4539   __ sll(t3, a2, 1);
4540   __ Addu(a3, a3, Operand(t3));
4541   __ addiu(a3, a3, StandardFrameConstants::kCallerSPOffset);
4542   __ sw(a3, MemOperand(sp, 1 * kPointerSize));
4543
4544   __ bind(&runtime);
4545   __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
4546 }
4547
4548
4549 void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
4550   // Stack layout:
4551   //  sp[0] : number of parameters (tagged)
4552   //  sp[4] : address of receiver argument
4553   //  sp[8] : function
4554   // Registers used over whole function:
4555   //  t2 : allocated object (tagged)
4556   //  t5 : mapped parameter count (tagged)
4557
4558   __ lw(a1, MemOperand(sp, 0 * kPointerSize));
4559   // a1 = parameter count (tagged)
4560
4561   // Check if the calling frame is an arguments adaptor frame.
4562   Label runtime;
4563   Label adaptor_frame, try_allocate;
4564   __ lw(a3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
4565   __ lw(a2, MemOperand(a3, StandardFrameConstants::kContextOffset));
4566   __ Branch(&adaptor_frame,
4567             eq,
4568             a2,
4569             Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
4570
4571   // No adaptor, parameter count = argument count.
4572   __ mov(a2, a1);
4573   __ b(&try_allocate);
4574   __ nop();   // Branch delay slot nop.
4575
4576   // We have an adaptor frame. Patch the parameters pointer.
4577   __ bind(&adaptor_frame);
4578   __ lw(a2, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset));
4579   __ sll(t6, a2, 1);
4580   __ Addu(a3, a3, Operand(t6));
4581   __ Addu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset));
4582   __ sw(a3, MemOperand(sp, 1 * kPointerSize));
4583
4584   // a1 = parameter count (tagged)
4585   // a2 = argument count (tagged)
4586   // Compute the mapped parameter count = min(a1, a2) in a1.
4587   Label skip_min;
4588   __ Branch(&skip_min, lt, a1, Operand(a2));
4589   __ mov(a1, a2);
4590   __ bind(&skip_min);
4591
4592   __ bind(&try_allocate);
4593
4594   // Compute the sizes of backing store, parameter map, and arguments object.
4595   // 1. Parameter map, has 2 extra words containing context and backing store.
4596   const int kParameterMapHeaderSize =
4597       FixedArray::kHeaderSize + 2 * kPointerSize;
4598   // If there are no mapped parameters, we do not need the parameter_map.
4599   Label param_map_size;
4600   ASSERT_EQ(0, Smi::FromInt(0));
4601   __ Branch(USE_DELAY_SLOT, &param_map_size, eq, a1, Operand(zero_reg));
4602   __ mov(t5, zero_reg);  // In delay slot: param map size = 0 when a1 == 0.
4603   __ sll(t5, a1, 1);
4604   __ addiu(t5, t5, kParameterMapHeaderSize);
4605   __ bind(&param_map_size);
4606
4607   // 2. Backing store.
4608   __ sll(t6, a2, 1);
4609   __ Addu(t5, t5, Operand(t6));
4610   __ Addu(t5, t5, Operand(FixedArray::kHeaderSize));
4611
4612   // 3. Arguments object.
4613   __ Addu(t5, t5, Operand(Heap::kArgumentsObjectSize));
4614
4615   // Do the allocation of all three objects in one go.
4616   __ AllocateInNewSpace(t5, v0, a3, t0, &runtime, TAG_OBJECT);
4617
4618   // v0 = address of new object(s) (tagged)
4619   // a2 = argument count (tagged)
4620   // Get the arguments boilerplate from the current (global) context into t0.
4621   const int kNormalOffset =
4622       Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX);
4623   const int kAliasedOffset =
4624       Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX);
4625
4626   __ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
4627   __ lw(t0, FieldMemOperand(t0, GlobalObject::kGlobalContextOffset));
4628   Label skip2_ne, skip2_eq;
4629   __ Branch(&skip2_ne, ne, a1, Operand(zero_reg));
4630   __ lw(t0, MemOperand(t0, kNormalOffset));
4631   __ bind(&skip2_ne);
4632
4633   __ Branch(&skip2_eq, eq, a1, Operand(zero_reg));
4634   __ lw(t0, MemOperand(t0, kAliasedOffset));
4635   __ bind(&skip2_eq);
4636
4637   // v0 = address of new object (tagged)
4638   // a1 = mapped parameter count (tagged)
4639   // a2 = argument count (tagged)
4640   // t0 = address of boilerplate object (tagged)
4641   // Copy the JS object part.
4642   for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
4643     __ lw(a3, FieldMemOperand(t0, i));
4644     __ sw(a3, FieldMemOperand(v0, i));
4645   }
4646
4647   // Set up the callee in-object property.
4648   STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
4649   __ lw(a3, MemOperand(sp, 2 * kPointerSize));
4650   const int kCalleeOffset = JSObject::kHeaderSize +
4651       Heap::kArgumentsCalleeIndex * kPointerSize;
4652   __ sw(a3, FieldMemOperand(v0, kCalleeOffset));
4653
4654   // Use the length (smi tagged) and set that as an in-object property too.
4655   STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
4656   const int kLengthOffset = JSObject::kHeaderSize +
4657       Heap::kArgumentsLengthIndex * kPointerSize;
4658   __ sw(a2, FieldMemOperand(v0, kLengthOffset));
4659
4660   // Set up the elements pointer in the allocated arguments object.
4661   // If we allocated a parameter map, t0 will point there, otherwise
4662   // it will point to the backing store.
4663   __ Addu(t0, v0, Operand(Heap::kArgumentsObjectSize));
4664   __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset));
4665
4666   // v0 = address of new object (tagged)
4667   // a1 = mapped parameter count (tagged)
4668   // a2 = argument count (tagged)
4669   // t0 = address of parameter map or backing store (tagged)
4670   // Initialize parameter map. If there are no mapped arguments, we're done.
4671   Label skip_parameter_map;
4672   Label skip3;
4673   __ Branch(&skip3, ne, a1, Operand(Smi::FromInt(0)));
4674   // Move backing store address to a3, because it is
4675   // expected there when filling in the unmapped arguments.
4676   __ mov(a3, t0);
4677   __ bind(&skip3);
4678
4679   __ Branch(&skip_parameter_map, eq, a1, Operand(Smi::FromInt(0)));
4680
4681   __ LoadRoot(t2, Heap::kNonStrictArgumentsElementsMapRootIndex);
4682   __ sw(t2, FieldMemOperand(t0, FixedArray::kMapOffset));
4683   __ Addu(t2, a1, Operand(Smi::FromInt(2)));
4684   __ sw(t2, FieldMemOperand(t0, FixedArray::kLengthOffset));
4685   __ sw(cp, FieldMemOperand(t0, FixedArray::kHeaderSize + 0 * kPointerSize));
4686   __ sll(t6, a1, 1);
4687   __ Addu(t2, t0, Operand(t6));
4688   __ Addu(t2, t2, Operand(kParameterMapHeaderSize));
4689   __ sw(t2, FieldMemOperand(t0, FixedArray::kHeaderSize + 1 * kPointerSize));
4690
4691   // Copy the parameter slots and the holes in the arguments.
4692   // We need to fill in mapped_parameter_count slots. They index the context,
4693   // where parameters are stored in reverse order, at
4694   //   MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
4695   // The mapped parameter thus need to get indices
4696   //   MIN_CONTEXT_SLOTS+parameter_count-1 ..
4697   //       MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
4698   // We loop from right to left.
4699   Label parameters_loop, parameters_test;
4700   __ mov(t2, a1);
4701   __ lw(t5, MemOperand(sp, 0 * kPointerSize));
4702   __ Addu(t5, t5, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
4703   __ Subu(t5, t5, Operand(a1));
4704   __ LoadRoot(t3, Heap::kTheHoleValueRootIndex);
4705   __ sll(t6, t2, 1);
4706   __ Addu(a3, t0, Operand(t6));
4707   __ Addu(a3, a3, Operand(kParameterMapHeaderSize));
4708
4709   // t2 = loop variable (tagged)
4710   // a1 = mapping index (tagged)
4711   // a3 = address of backing store (tagged)
4712   // t0 = address of parameter map (tagged)
4713   // t1 = temporary scratch (a.o., for address calculation)
4714   // t3 = the hole value
4715   __ jmp(&parameters_test);
4716
4717   __ bind(&parameters_loop);
4718   __ Subu(t2, t2, Operand(Smi::FromInt(1)));
4719   __ sll(t1, t2, 1);
4720   __ Addu(t1, t1, Operand(kParameterMapHeaderSize - kHeapObjectTag));
4721   __ Addu(t6, t0, t1);
4722   __ sw(t5, MemOperand(t6));
4723   __ Subu(t1, t1, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
4724   __ Addu(t6, a3, t1);
4725   __ sw(t3, MemOperand(t6));
4726   __ Addu(t5, t5, Operand(Smi::FromInt(1)));
4727   __ bind(&parameters_test);
4728   __ Branch(&parameters_loop, ne, t2, Operand(Smi::FromInt(0)));
4729
4730   __ bind(&skip_parameter_map);
4731   // a2 = argument count (tagged)
4732   // a3 = address of backing store (tagged)
4733   // t1 = scratch
4734   // Copy arguments header and remaining slots (if there are any).
4735   __ LoadRoot(t1, Heap::kFixedArrayMapRootIndex);
4736   __ sw(t1, FieldMemOperand(a3, FixedArray::kMapOffset));
4737   __ sw(a2, FieldMemOperand(a3, FixedArray::kLengthOffset));
4738
4739   Label arguments_loop, arguments_test;
4740   __ mov(t5, a1);
4741   __ lw(t0, MemOperand(sp, 1 * kPointerSize));
4742   __ sll(t6, t5, 1);
4743   __ Subu(t0, t0, Operand(t6));
4744   __ jmp(&arguments_test);
4745
4746   __ bind(&arguments_loop);
4747   __ Subu(t0, t0, Operand(kPointerSize));
4748   __ lw(t2, MemOperand(t0, 0));
4749   __ sll(t6, t5, 1);
4750   __ Addu(t1, a3, Operand(t6));
4751   __ sw(t2, FieldMemOperand(t1, FixedArray::kHeaderSize));
4752   __ Addu(t5, t5, Operand(Smi::FromInt(1)));
4753
4754   __ bind(&arguments_test);
4755   __ Branch(&arguments_loop, lt, t5, Operand(a2));
4756
4757   // Return and remove the on-stack parameters.
4758   __ DropAndRet(3);
4759
4760   // Do the runtime call to allocate the arguments object.
4761   // a2 = argument count (tagged)
4762   __ bind(&runtime);
4763   __ sw(a2, MemOperand(sp, 0 * kPointerSize));  // Patch argument count.
4764   __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
4765 }
4766
4767
4768 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
4769   // sp[0] : number of parameters
4770   // sp[4] : receiver displacement
4771   // sp[8] : function
4772   // Check if the calling frame is an arguments adaptor frame.
4773   Label adaptor_frame, try_allocate, runtime;
4774   __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
4775   __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset));
4776   __ Branch(&adaptor_frame,
4777             eq,
4778             a3,
4779             Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
4780
4781   // Get the length from the frame.
4782   __ lw(a1, MemOperand(sp, 0));
4783   __ Branch(&try_allocate);
4784
4785   // Patch the arguments.length and the parameters pointer.
4786   __ bind(&adaptor_frame);
4787   __ lw(a1, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
4788   __ sw(a1, MemOperand(sp, 0));
4789   __ sll(at, a1, kPointerSizeLog2 - kSmiTagSize);
4790   __ Addu(a3, a2, Operand(at));
4791
4792   __ Addu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset));
4793   __ sw(a3, MemOperand(sp, 1 * kPointerSize));
4794
4795   // Try the new space allocation. Start out with computing the size
4796   // of the arguments object and the elements array in words.
4797   Label add_arguments_object;
4798   __ bind(&try_allocate);
4799   __ Branch(&add_arguments_object, eq, a1, Operand(zero_reg));
4800   __ srl(a1, a1, kSmiTagSize);
4801
4802   __ Addu(a1, a1, Operand(FixedArray::kHeaderSize / kPointerSize));
4803   __ bind(&add_arguments_object);
4804   __ Addu(a1, a1, Operand(Heap::kArgumentsObjectSizeStrict / kPointerSize));
4805
4806   // Do the allocation of both objects in one go.
4807   __ AllocateInNewSpace(a1,
4808                         v0,
4809                         a2,
4810                         a3,
4811                         &runtime,
4812                         static_cast<AllocationFlags>(TAG_OBJECT |
4813                                                      SIZE_IN_WORDS));
4814
4815   // Get the arguments boilerplate from the current (global) context.
4816   __ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
4817   __ lw(t0, FieldMemOperand(t0, GlobalObject::kGlobalContextOffset));
4818   __ lw(t0, MemOperand(t0, Context::SlotOffset(
4819       Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX)));
4820
4821   // Copy the JS object part.
4822   __ CopyFields(v0, t0, a3.bit(), JSObject::kHeaderSize / kPointerSize);
4823
4824   // Get the length (smi tagged) and set that as an in-object property too.
4825   STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
4826   __ lw(a1, MemOperand(sp, 0 * kPointerSize));
4827   __ sw(a1, FieldMemOperand(v0, JSObject::kHeaderSize +
4828       Heap::kArgumentsLengthIndex * kPointerSize));
4829
4830   Label done;
4831   __ Branch(&done, eq, a1, Operand(zero_reg));
4832
4833   // Get the parameters pointer from the stack.
4834   __ lw(a2, MemOperand(sp, 1 * kPointerSize));
4835
4836   // Set up the elements pointer in the allocated arguments object and
4837   // initialize the header in the elements fixed array.
4838   __ Addu(t0, v0, Operand(Heap::kArgumentsObjectSizeStrict));
4839   __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset));
4840   __ LoadRoot(a3, Heap::kFixedArrayMapRootIndex);
4841   __ sw(a3, FieldMemOperand(t0, FixedArray::kMapOffset));
4842   __ sw(a1, FieldMemOperand(t0, FixedArray::kLengthOffset));
4843   // Untag the length for the loop.
4844   __ srl(a1, a1, kSmiTagSize);
4845
4846   // Copy the fixed array slots.
4847   Label loop;
4848   // Set up t0 to point to the first array slot.
4849   __ Addu(t0, t0, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4850   __ bind(&loop);
4851   // Pre-decrement a2 with kPointerSize on each iteration.
4852   // Pre-decrement in order to skip receiver.
4853   __ Addu(a2, a2, Operand(-kPointerSize));
4854   __ lw(a3, MemOperand(a2));
4855   // Post-increment t0 with kPointerSize on each iteration.
4856   __ sw(a3, MemOperand(t0));
4857   __ Addu(t0, t0, Operand(kPointerSize));
4858   __ Subu(a1, a1, Operand(1));
4859   __ Branch(&loop, ne, a1, Operand(zero_reg));
4860
4861   // Return and remove the on-stack parameters.
4862   __ bind(&done);
4863   __ DropAndRet(3);
4864
4865   // Do the runtime call to allocate the arguments object.
4866   __ bind(&runtime);
4867   __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1);
4868 }
4869
4870
4871 void RegExpExecStub::Generate(MacroAssembler* masm) {
4872   // Just jump directly to runtime if native RegExp is not selected at compile
4873   // time or if regexp entry in generated code is turned off runtime switch or
4874   // at compilation.
4875 #ifdef V8_INTERPRETED_REGEXP
4876   __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
4877 #else  // V8_INTERPRETED_REGEXP
4878
4879   // Stack frame on entry.
4880   //  sp[0]: last_match_info (expected JSArray)
4881   //  sp[4]: previous index
4882   //  sp[8]: subject string
4883   //  sp[12]: JSRegExp object
4884
4885   const int kLastMatchInfoOffset = 0 * kPointerSize;
4886   const int kPreviousIndexOffset = 1 * kPointerSize;
4887   const int kSubjectOffset = 2 * kPointerSize;
4888   const int kJSRegExpOffset = 3 * kPointerSize;
4889
4890   Isolate* isolate = masm->isolate();
4891
4892   Label runtime, invoke_regexp;
4893
4894   // Allocation of registers for this function. These are in callee save
4895   // registers and will be preserved by the call to the native RegExp code, as
4896   // this code is called using the normal C calling convention. When calling
4897   // directly from generated code the native RegExp code will not do a GC and
4898   // therefore the content of these registers are safe to use after the call.
4899   // MIPS - using s0..s2, since we are not using CEntry Stub.
4900   Register subject = s0;
4901   Register regexp_data = s1;
4902   Register last_match_info_elements = s2;
4903
4904   // Ensure that a RegExp stack is allocated.
4905   ExternalReference address_of_regexp_stack_memory_address =
4906       ExternalReference::address_of_regexp_stack_memory_address(
4907           isolate);
4908   ExternalReference address_of_regexp_stack_memory_size =
4909       ExternalReference::address_of_regexp_stack_memory_size(isolate);
4910   __ li(a0, Operand(address_of_regexp_stack_memory_size));
4911   __ lw(a0, MemOperand(a0, 0));
4912   __ Branch(&runtime, eq, a0, Operand(zero_reg));
4913
4914   // Check that the first argument is a JSRegExp object.
4915   __ lw(a0, MemOperand(sp, kJSRegExpOffset));
4916   STATIC_ASSERT(kSmiTag == 0);
4917   __ JumpIfSmi(a0, &runtime);
4918   __ GetObjectType(a0, a1, a1);
4919   __ Branch(&runtime, ne, a1, Operand(JS_REGEXP_TYPE));
4920
4921   // Check that the RegExp has been compiled (data contains a fixed array).
4922   __ lw(regexp_data, FieldMemOperand(a0, JSRegExp::kDataOffset));
4923   if (FLAG_debug_code) {
4924     __ And(t0, regexp_data, Operand(kSmiTagMask));
4925     __ Check(nz,
4926              "Unexpected type for RegExp data, FixedArray expected",
4927              t0,
4928              Operand(zero_reg));
4929     __ GetObjectType(regexp_data, a0, a0);
4930     __ Check(eq,
4931              "Unexpected type for RegExp data, FixedArray expected",
4932              a0,
4933              Operand(FIXED_ARRAY_TYPE));
4934   }
4935
4936   // regexp_data: RegExp data (FixedArray)
4937   // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
4938   __ lw(a0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
4939   __ Branch(&runtime, ne, a0, Operand(Smi::FromInt(JSRegExp::IRREGEXP)));
4940
4941   // regexp_data: RegExp data (FixedArray)
4942   // Check that the number of captures fit in the static offsets vector buffer.
4943   __ lw(a2,
4944          FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
4945   // Calculate number of capture registers (number_of_captures + 1) * 2. This
4946   // uses the asumption that smis are 2 * their untagged value.
4947   STATIC_ASSERT(kSmiTag == 0);
4948   STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
4949   __ Addu(a2, a2, Operand(2));  // a2 was a smi.
4950   // Check that the static offsets vector buffer is large enough.
4951   __ Branch(&runtime, hi, a2, Operand(OffsetsVector::kStaticOffsetsVectorSize));
4952
4953   // a2: Number of capture registers
4954   // regexp_data: RegExp data (FixedArray)
4955   // Check that the second argument is a string.
4956   __ lw(subject, MemOperand(sp, kSubjectOffset));
4957   __ JumpIfSmi(subject, &runtime);
4958   __ GetObjectType(subject, a0, a0);
4959   __ And(a0, a0, Operand(kIsNotStringMask));
4960   STATIC_ASSERT(kStringTag == 0);
4961   __ Branch(&runtime, ne, a0, Operand(zero_reg));
4962
4963   // Get the length of the string to r3.
4964   __ lw(a3, FieldMemOperand(subject, String::kLengthOffset));
4965
4966   // a2: Number of capture registers
4967   // a3: Length of subject string as a smi
4968   // subject: Subject string
4969   // regexp_data: RegExp data (FixedArray)
4970   // Check that the third argument is a positive smi less than the subject
4971   // string length. A negative value will be greater (unsigned comparison).
4972   __ lw(a0, MemOperand(sp, kPreviousIndexOffset));
4973   __ JumpIfNotSmi(a0, &runtime);
4974   __ Branch(&runtime, ls, a3, Operand(a0));
4975
4976   // a2: Number of capture registers
4977   // subject: Subject string
4978   // regexp_data: RegExp data (FixedArray)
4979   // Check that the fourth object is a JSArray object.
4980   __ lw(a0, MemOperand(sp, kLastMatchInfoOffset));
4981   __ JumpIfSmi(a0, &runtime);
4982   __ GetObjectType(a0, a1, a1);
4983   __ Branch(&runtime, ne, a1, Operand(JS_ARRAY_TYPE));
4984   // Check that the JSArray is in fast case.
4985   __ lw(last_match_info_elements,
4986          FieldMemOperand(a0, JSArray::kElementsOffset));
4987   __ lw(a0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
4988   __ Branch(&runtime, ne, a0, Operand(
4989       isolate->factory()->fixed_array_map()));
4990   // Check that the last match info has space for the capture registers and the
4991   // additional information.
4992   __ lw(a0,
4993          FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
4994   __ Addu(a2, a2, Operand(RegExpImpl::kLastMatchOverhead));
4995   __ sra(at, a0, kSmiTagSize);  // Untag length for comparison.
4996   __ Branch(&runtime, gt, a2, Operand(at));
4997
4998   // Reset offset for possibly sliced string.
4999   __ mov(t0, zero_reg);
5000   // subject: Subject string
5001   // regexp_data: RegExp data (FixedArray)
5002   // Check the representation and encoding of the subject string.
5003   Label seq_string;
5004   __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
5005   __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
5006   // First check for flat string.  None of the following string type tests will
5007   // succeed if subject is not a string or a short external string.
5008   __ And(a1,
5009          a0,
5010          Operand(kIsNotStringMask |
5011                  kStringRepresentationMask |
5012                  kShortExternalStringMask));
5013   STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
5014   __ Branch(&seq_string, eq, a1, Operand(zero_reg));
5015
5016   // subject: Subject string
5017   // a0: instance type if Subject string
5018   // regexp_data: RegExp data (FixedArray)
5019   // a1: whether subject is a string and if yes, its string representation
5020   // Check for flat cons string or sliced string.
5021   // A flat cons string is a cons string where the second part is the empty
5022   // string. In that case the subject string is just the first part of the cons
5023   // string. Also in this case the first part of the cons string is known to be
5024   // a sequential string or an external string.
5025   // In the case of a sliced string its offset has to be taken into account.
5026   Label cons_string, external_string, check_encoding;
5027   STATIC_ASSERT(kConsStringTag < kExternalStringTag);
5028   STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
5029   STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
5030   STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
5031   __ Branch(&cons_string, lt, a1, Operand(kExternalStringTag));
5032   __ Branch(&external_string, eq, a1, Operand(kExternalStringTag));
5033
5034   // Catch non-string subject or short external string.
5035   STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
5036   __ And(at, a1, Operand(kIsNotStringMask | kShortExternalStringMask));
5037   __ Branch(&runtime, ne, at, Operand(zero_reg));
5038
5039   // String is sliced.
5040   __ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
5041   __ sra(t0, t0, kSmiTagSize);
5042   __ lw(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
5043   // t5: offset of sliced string, smi-tagged.
5044   __ jmp(&check_encoding);
5045   // String is a cons string, check whether it is flat.
5046   __ bind(&cons_string);
5047   __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset));
5048   __ LoadRoot(a1, Heap::kEmptyStringRootIndex);
5049   __ Branch(&runtime, ne, a0, Operand(a1));
5050   __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
5051   // Is first part of cons or parent of slice a flat string?
5052   __ bind(&check_encoding);
5053   __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
5054   __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
5055   STATIC_ASSERT(kSeqStringTag == 0);
5056   __ And(at, a0, Operand(kStringRepresentationMask));
5057   __ Branch(&external_string, ne, at, Operand(zero_reg));
5058
5059   __ bind(&seq_string);
5060   // subject: Subject string
5061   // regexp_data: RegExp data (FixedArray)
5062   // a0: Instance type of subject string
5063   STATIC_ASSERT(kStringEncodingMask == 4);
5064   STATIC_ASSERT(kAsciiStringTag == 4);
5065   STATIC_ASSERT(kTwoByteStringTag == 0);
5066   // Find the code object based on the assumptions above.
5067   __ And(a0, a0, Operand(kStringEncodingMask));  // Non-zero for ASCII.
5068   __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset));
5069   __ sra(a3, a0, 2);  // a3 is 1 for ASCII, 0 for UC16 (used below).
5070   __ lw(t1, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset));
5071   __ Movz(t9, t1, a0);  // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset.
5072
5073   // Check that the irregexp code has been generated for the actual string
5074   // encoding. If it has, the field contains a code object otherwise it contains
5075   // a smi (code flushing support).
5076   __ JumpIfSmi(t9, &runtime);
5077
5078   // a3: encoding of subject string (1 if ASCII, 0 if two_byte);
5079   // t9: code
5080   // subject: Subject string
5081   // regexp_data: RegExp data (FixedArray)
5082   // Load used arguments before starting to push arguments for call to native
5083   // RegExp code to avoid handling changing stack height.
5084   __ lw(a1, MemOperand(sp, kPreviousIndexOffset));
5085   __ sra(a1, a1, kSmiTagSize);  // Untag the Smi.
5086
5087   // a1: previous index
5088   // a3: encoding of subject string (1 if ASCII, 0 if two_byte);
5089   // t9: code
5090   // subject: Subject string
5091   // regexp_data: RegExp data (FixedArray)
5092   // All checks done. Now push arguments for native regexp code.
5093   __ IncrementCounter(isolate->counters()->regexp_entry_native(),
5094                       1, a0, a2);
5095
5096   // Isolates: note we add an additional parameter here (isolate pointer).
5097   const int kRegExpExecuteArguments = 8;
5098   const int kParameterRegisters = 4;
5099   __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
5100
5101   // Stack pointer now points to cell where return address is to be written.
5102   // Arguments are before that on the stack or in registers, meaning we
5103   // treat the return address as argument 5. Thus every argument after that
5104   // needs to be shifted back by 1. Since DirectCEntryStub will handle
5105   // allocating space for the c argument slots, we don't need to calculate
5106   // that into the argument positions on the stack. This is how the stack will
5107   // look (sp meaning the value of sp at this moment):
5108   // [sp + 4] - Argument 8
5109   // [sp + 3] - Argument 7
5110   // [sp + 2] - Argument 6
5111   // [sp + 1] - Argument 5
5112   // [sp + 0] - saved ra
5113
5114   // Argument 8: Pass current isolate address.
5115   // CFunctionArgumentOperand handles MIPS stack argument slots.
5116   __ li(a0, Operand(ExternalReference::isolate_address()));
5117   __ sw(a0, MemOperand(sp, 4 * kPointerSize));
5118
5119   // Argument 7: Indicate that this is a direct call from JavaScript.
5120   __ li(a0, Operand(1));
5121   __ sw(a0, MemOperand(sp, 3 * kPointerSize));
5122
5123   // Argument 6: Start (high end) of backtracking stack memory area.
5124   __ li(a0, Operand(address_of_regexp_stack_memory_address));
5125   __ lw(a0, MemOperand(a0, 0));
5126   __ li(a2, Operand(address_of_regexp_stack_memory_size));
5127   __ lw(a2, MemOperand(a2, 0));
5128   __ addu(a0, a0, a2);
5129   __ sw(a0, MemOperand(sp, 2 * kPointerSize));
5130
5131   // Argument 5: static offsets vector buffer.
5132   __ li(a0, Operand(
5133         ExternalReference::address_of_static_offsets_vector(isolate)));
5134   __ sw(a0, MemOperand(sp, 1 * kPointerSize));
5135
5136   // For arguments 4 and 3 get string length, calculate start of string data
5137   // and calculate the shift of the index (0 for ASCII and 1 for two byte).
5138   __ Addu(t2, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag));
5139   __ Xor(a3, a3, Operand(1));  // 1 for 2-byte str, 0 for 1-byte.
5140   // Load the length from the original subject string from the previous stack
5141   // frame. Therefore we have to use fp, which points exactly to two pointer
5142   // sizes below the previous sp. (Because creating a new stack frame pushes
5143   // the previous fp onto the stack and moves up sp by 2 * kPointerSize.)
5144   __ lw(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
5145   // If slice offset is not 0, load the length from the original sliced string.
5146   // Argument 4, a3: End of string data
5147   // Argument 3, a2: Start of string data
5148   // Prepare start and end index of the input.
5149   __ sllv(t1, t0, a3);
5150   __ addu(t0, t2, t1);
5151   __ sllv(t1, a1, a3);
5152   __ addu(a2, t0, t1);
5153
5154   __ lw(t2, FieldMemOperand(subject, String::kLengthOffset));
5155   __ sra(t2, t2, kSmiTagSize);
5156   __ sllv(t1, t2, a3);
5157   __ addu(a3, t0, t1);
5158   // Argument 2 (a1): Previous index.
5159   // Already there
5160
5161   // Argument 1 (a0): Subject string.
5162   __ mov(a0, subject);
5163
5164   // Locate the code entry and call it.
5165   __ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag));
5166   DirectCEntryStub stub;
5167   stub.GenerateCall(masm, t9);
5168
5169   __ LeaveExitFrame(false, no_reg);
5170
5171   // v0: result
5172   // subject: subject string (callee saved)
5173   // regexp_data: RegExp data (callee saved)
5174   // last_match_info_elements: Last match info elements (callee saved)
5175
5176   // Check the result.
5177
5178   Label success;
5179   __ Branch(&success, eq, v0, Operand(NativeRegExpMacroAssembler::SUCCESS));
5180   Label failure;
5181   __ Branch(&failure, eq, v0, Operand(NativeRegExpMacroAssembler::FAILURE));
5182   // If not exception it can only be retry. Handle that in the runtime system.
5183   __ Branch(&runtime, ne, v0, Operand(NativeRegExpMacroAssembler::EXCEPTION));
5184   // Result must now be exception. If there is no pending exception already a
5185   // stack overflow (on the backtrack stack) was detected in RegExp code but
5186   // haven't created the exception yet. Handle that in the runtime system.
5187   // TODO(592): Rerunning the RegExp to get the stack overflow exception.
5188   __ li(a1, Operand(isolate->factory()->the_hole_value()));
5189   __ li(a2, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
5190                                       isolate)));
5191   __ lw(v0, MemOperand(a2, 0));
5192   __ Branch(&runtime, eq, v0, Operand(a1));
5193
5194   __ sw(a1, MemOperand(a2, 0));  // Clear pending exception.
5195
5196   // Check if the exception is a termination. If so, throw as uncatchable.
5197   __ LoadRoot(a0, Heap::kTerminationExceptionRootIndex);
5198   Label termination_exception;
5199   __ Branch(&termination_exception, eq, v0, Operand(a0));
5200
5201   __ Throw(v0);
5202
5203   __ bind(&termination_exception);
5204   __ ThrowUncatchable(v0);
5205
5206   __ bind(&failure);
5207   // For failure and exception return null.
5208   __ li(v0, Operand(isolate->factory()->null_value()));
5209   __ DropAndRet(4);
5210
5211   // Process the result from the native regexp code.
5212   __ bind(&success);
5213   __ lw(a1,
5214          FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
5215   // Calculate number of capture registers (number_of_captures + 1) * 2.
5216   STATIC_ASSERT(kSmiTag == 0);
5217   STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
5218   __ Addu(a1, a1, Operand(2));  // a1 was a smi.
5219
5220   // a1: number of capture registers
5221   // subject: subject string
5222   // Store the capture count.
5223   __ sll(a2, a1, kSmiTagSize + kSmiShiftSize);  // To smi.
5224   __ sw(a2, FieldMemOperand(last_match_info_elements,
5225                              RegExpImpl::kLastCaptureCountOffset));
5226   // Store last subject and last input.
5227   __ sw(subject,
5228          FieldMemOperand(last_match_info_elements,
5229                          RegExpImpl::kLastSubjectOffset));
5230   __ mov(a2, subject);
5231   __ RecordWriteField(last_match_info_elements,
5232                       RegExpImpl::kLastSubjectOffset,
5233                       a2,
5234                       t3,
5235                       kRAHasNotBeenSaved,
5236                       kDontSaveFPRegs);
5237   __ sw(subject,
5238          FieldMemOperand(last_match_info_elements,
5239                          RegExpImpl::kLastInputOffset));
5240   __ RecordWriteField(last_match_info_elements,
5241                       RegExpImpl::kLastInputOffset,
5242                       subject,
5243                       t3,
5244                       kRAHasNotBeenSaved,
5245                       kDontSaveFPRegs);
5246
5247   // Get the static offsets vector filled by the native regexp code.
5248   ExternalReference address_of_static_offsets_vector =
5249       ExternalReference::address_of_static_offsets_vector(isolate);
5250   __ li(a2, Operand(address_of_static_offsets_vector));
5251
5252   // a1: number of capture registers
5253   // a2: offsets vector
5254   Label next_capture, done;
5255   // Capture register counter starts from number of capture registers and
5256   // counts down until wrapping after zero.
5257   __ Addu(a0,
5258          last_match_info_elements,
5259          Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag));
5260   __ bind(&next_capture);
5261   __ Subu(a1, a1, Operand(1));
5262   __ Branch(&done, lt, a1, Operand(zero_reg));
5263   // Read the value from the static offsets vector buffer.
5264   __ lw(a3, MemOperand(a2, 0));
5265   __ addiu(a2, a2, kPointerSize);
5266   // Store the smi value in the last match info.
5267   __ sll(a3, a3, kSmiTagSize);  // Convert to Smi.
5268   __ sw(a3, MemOperand(a0, 0));
5269   __ Branch(&next_capture, USE_DELAY_SLOT);
5270   __ addiu(a0, a0, kPointerSize);  // In branch delay slot.
5271
5272   __ bind(&done);
5273
5274   // Return last match info.
5275   __ lw(v0, MemOperand(sp, kLastMatchInfoOffset));
5276   __ DropAndRet(4);
5277
5278   // External string.  Short external strings have already been ruled out.
5279   // a0: scratch
5280   __ bind(&external_string);
5281   __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
5282   __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
5283   if (FLAG_debug_code) {
5284     // Assert that we do not have a cons or slice (indirect strings) here.
5285     // Sequential strings have already been ruled out.
5286     __ And(at, a0, Operand(kIsIndirectStringMask));
5287     __ Assert(eq,
5288               "external string expected, but not found",
5289               at,
5290               Operand(zero_reg));
5291   }
5292   __ lw(subject,
5293         FieldMemOperand(subject, ExternalString::kResourceDataOffset));
5294   // Move the pointer so that offset-wise, it looks like a sequential string.
5295   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize);
5296   __ Subu(subject,
5297           subject,
5298           SeqTwoByteString::kHeaderSize - kHeapObjectTag);
5299   __ jmp(&seq_string);
5300
5301   // Do the runtime call to execute the regexp.
5302   __ bind(&runtime);
5303   __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
5304 #endif  // V8_INTERPRETED_REGEXP
5305 }
5306
5307
5308 void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
5309   const int kMaxInlineLength = 100;
5310   Label slowcase;
5311   Label done;
5312   __ lw(a1, MemOperand(sp, kPointerSize * 2));
5313   STATIC_ASSERT(kSmiTag == 0);
5314   STATIC_ASSERT(kSmiTagSize == 1);
5315   __ JumpIfNotSmi(a1, &slowcase);
5316   __ Branch(&slowcase, hi, a1, Operand(Smi::FromInt(kMaxInlineLength)));
5317   // Smi-tagging is equivalent to multiplying by 2.
5318   // Allocate RegExpResult followed by FixedArray with size in ebx.
5319   // JSArray:   [Map][empty properties][Elements][Length-smi][index][input]
5320   // Elements:  [Map][Length][..elements..]
5321   // Size of JSArray with two in-object properties and the header of a
5322   // FixedArray.
5323   int objects_size =
5324       (JSRegExpResult::kSize + FixedArray::kHeaderSize) / kPointerSize;
5325   __ srl(t1, a1, kSmiTagSize + kSmiShiftSize);
5326   __ Addu(a2, t1, Operand(objects_size));
5327   __ AllocateInNewSpace(
5328       a2,  // In: Size, in words.
5329       v0,  // Out: Start of allocation (tagged).
5330       a3,  // Scratch register.
5331       t0,  // Scratch register.
5332       &slowcase,
5333       static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
5334   // v0: Start of allocated area, object-tagged.
5335   // a1: Number of elements in array, as smi.
5336   // t1: Number of elements, untagged.
5337
5338   // Set JSArray map to global.regexp_result_map().
5339   // Set empty properties FixedArray.
5340   // Set elements to point to FixedArray allocated right after the JSArray.
5341   // Interleave operations for better latency.
5342   __ lw(a2, ContextOperand(cp, Context::GLOBAL_INDEX));
5343   __ Addu(a3, v0, Operand(JSRegExpResult::kSize));
5344   __ li(t0, Operand(masm->isolate()->factory()->empty_fixed_array()));
5345   __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalContextOffset));
5346   __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
5347   __ lw(a2, ContextOperand(a2, Context::REGEXP_RESULT_MAP_INDEX));
5348   __ sw(t0, FieldMemOperand(v0, JSObject::kPropertiesOffset));
5349   __ sw(a2, FieldMemOperand(v0, HeapObject::kMapOffset));
5350
5351   // Set input, index and length fields from arguments.
5352   __ lw(a1, MemOperand(sp, kPointerSize * 0));
5353   __ lw(a2, MemOperand(sp, kPointerSize * 1));
5354   __ lw(t2, MemOperand(sp, kPointerSize * 2));
5355   __ sw(a1, FieldMemOperand(v0, JSRegExpResult::kInputOffset));
5356   __ sw(a2, FieldMemOperand(v0, JSRegExpResult::kIndexOffset));
5357   __ sw(t2, FieldMemOperand(v0, JSArray::kLengthOffset));
5358
5359   // Fill out the elements FixedArray.
5360   // v0: JSArray, tagged.
5361   // a3: FixedArray, tagged.
5362   // t1: Number of elements in array, untagged.
5363
5364   // Set map.
5365   __ li(a2, Operand(masm->isolate()->factory()->fixed_array_map()));
5366   __ sw(a2, FieldMemOperand(a3, HeapObject::kMapOffset));
5367   // Set FixedArray length.
5368   __ sll(t2, t1, kSmiTagSize);
5369   __ sw(t2, FieldMemOperand(a3, FixedArray::kLengthOffset));
5370   // Fill contents of fixed-array with the-hole.
5371   __ li(a2, Operand(masm->isolate()->factory()->the_hole_value()));
5372   __ Addu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
5373   // Fill fixed array elements with hole.
5374   // v0: JSArray, tagged.
5375   // a2: the hole.
5376   // a3: Start of elements in FixedArray.
5377   // t1: Number of elements to fill.
5378   Label loop;
5379   __ sll(t1, t1, kPointerSizeLog2);  // Convert num elements to num bytes.
5380   __ addu(t1, t1, a3);  // Point past last element to store.
5381   __ bind(&loop);
5382   __ Branch(&done, ge, a3, Operand(t1));  // Break when a3 past end of elem.
5383   __ sw(a2, MemOperand(a3));
5384   __ Branch(&loop, USE_DELAY_SLOT);
5385   __ addiu(a3, a3, kPointerSize);  // In branch delay slot.
5386
5387   __ bind(&done);
5388   __ DropAndRet(3);
5389
5390   __ bind(&slowcase);
5391   __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1);
5392 }
5393
5394
5395 static void GenerateRecordCallTarget(MacroAssembler* masm) {
5396   // Cache the called function in a global property cell.  Cache states
5397   // are uninitialized, monomorphic (indicated by a JSFunction), and
5398   // megamorphic.
5399   // a1 : the function to call
5400   // a2 : cache cell for call target
5401   Label done;
5402
5403   ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
5404             masm->isolate()->heap()->undefined_value());
5405   ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()),
5406             masm->isolate()->heap()->the_hole_value());
5407
5408   // Load the cache state into a3.
5409   __ lw(a3, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
5410
5411   // A monomorphic cache hit or an already megamorphic state: invoke the
5412   // function without changing the state.
5413   __ Branch(&done, eq, a3, Operand(a1));
5414   __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
5415   __ Branch(&done, eq, a3, Operand(at));
5416
5417   // A monomorphic miss (i.e, here the cache is not uninitialized) goes
5418   // megamorphic.
5419   __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
5420
5421   __ Branch(USE_DELAY_SLOT, &done, eq, a3, Operand(at));
5422   // An uninitialized cache is patched with the function.
5423   // Store a1 in the delay slot. This may or may not get overwritten depending
5424   // on the result of the comparison.
5425   __ sw(a1, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
5426   // No need for a write barrier here - cells are rescanned.
5427
5428   // MegamorphicSentinel is an immortal immovable object (undefined) so no
5429   // write-barrier is needed.
5430   __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
5431   __ sw(at, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
5432
5433   __ bind(&done);
5434 }
5435
5436
5437 void CallFunctionStub::Generate(MacroAssembler* masm) {
5438   // a1 : the function to call
5439   // a2 : cache cell for call target
5440   Label slow, non_function;
5441
5442   // The receiver might implicitly be the global object. This is
5443   // indicated by passing the hole as the receiver to the call
5444   // function stub.
5445   if (ReceiverMightBeImplicit()) {
5446     Label call;
5447     // Get the receiver from the stack.
5448     // function, receiver [, arguments]
5449     __ lw(t0, MemOperand(sp, argc_ * kPointerSize));
5450     // Call as function is indicated with the hole.
5451     __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
5452     __ Branch(&call, ne, t0, Operand(at));
5453     // Patch the receiver on the stack with the global receiver object.
5454     __ lw(a2, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
5455     __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset));
5456     __ sw(a2, MemOperand(sp, argc_ * kPointerSize));
5457     __ bind(&call);
5458   }
5459
5460   // Check that the function is really a JavaScript function.
5461   // a1: pushed function (to be verified)
5462   __ JumpIfSmi(a1, &non_function);
5463   // Get the map of the function object.
5464   __ GetObjectType(a1, a2, a2);
5465   __ Branch(&slow, ne, a2, Operand(JS_FUNCTION_TYPE));
5466
5467   // Fast-case: Invoke the function now.
5468   // a1: pushed function
5469   ParameterCount actual(argc_);
5470
5471   if (ReceiverMightBeImplicit()) {
5472     Label call_as_function;
5473     __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
5474     __ Branch(&call_as_function, eq, t0, Operand(at));
5475     __ InvokeFunction(a1,
5476                       actual,
5477                       JUMP_FUNCTION,
5478                       NullCallWrapper(),
5479                       CALL_AS_METHOD);
5480     __ bind(&call_as_function);
5481   }
5482   __ InvokeFunction(a1,
5483                     actual,
5484                     JUMP_FUNCTION,
5485                     NullCallWrapper(),
5486                     CALL_AS_FUNCTION);
5487
5488   // Slow-case: Non-function called.
5489   __ bind(&slow);
5490   // Check for function proxy.
5491   __ Branch(&non_function, ne, a2, Operand(JS_FUNCTION_PROXY_TYPE));
5492   __ push(a1);  // Put proxy as additional argument.
5493   __ li(a0, Operand(argc_ + 1, RelocInfo::NONE));
5494   __ li(a2, Operand(0, RelocInfo::NONE));
5495   __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY);
5496   __ SetCallKind(t1, CALL_AS_METHOD);
5497   {
5498     Handle<Code> adaptor =
5499       masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
5500     __ Jump(adaptor, RelocInfo::CODE_TARGET);
5501   }
5502
5503   // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
5504   // of the original receiver from the call site).
5505   __ bind(&non_function);
5506   __ sw(a1, MemOperand(sp, argc_ * kPointerSize));
5507   __ li(a0, Operand(argc_));  // Set up the number of arguments.
5508   __ mov(a2, zero_reg);
5509   __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION);
5510   __ SetCallKind(t1, CALL_AS_METHOD);
5511   __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
5512           RelocInfo::CODE_TARGET);
5513 }
5514
5515
5516 void CallConstructStub::Generate(MacroAssembler* masm) {
5517   // a0 : number of arguments
5518   // a1 : the function to call
5519   // a2 : cache cell for call target
5520   Label slow, non_function_call;
5521
5522   // Check that the function is not a smi.
5523   __ JumpIfSmi(a1, &non_function_call);
5524   // Check that the function is a JSFunction.
5525   __ GetObjectType(a1, a3, a3);
5526   __ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE));
5527
5528   if (RecordCallTarget()) {
5529     GenerateRecordCallTarget(masm);
5530   }
5531
5532   // Jump to the function-specific construct stub.
5533   __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
5534   __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kConstructStubOffset));
5535   __ Addu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag));
5536   __ Jump(at);
5537
5538   // a0: number of arguments
5539   // a1: called object
5540   // a3: object type
5541   Label do_call;
5542   __ bind(&slow);
5543   __ Branch(&non_function_call, ne, a3, Operand(JS_FUNCTION_PROXY_TYPE));
5544   __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
5545   __ jmp(&do_call);
5546
5547   __ bind(&non_function_call);
5548   __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
5549   __ bind(&do_call);
5550   // Set expected number of arguments to zero (not changing r0).
5551   __ li(a2, Operand(0, RelocInfo::NONE));
5552   __ SetCallKind(t1, CALL_AS_METHOD);
5553   __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
5554           RelocInfo::CODE_TARGET);
5555 }
5556
5557
5558 // Unfortunately you have to run without snapshots to see most of these
5559 // names in the profile since most compare stubs end up in the snapshot.
5560 void CompareStub::PrintName(StringStream* stream) {
5561   ASSERT((lhs_.is(a0) && rhs_.is(a1)) ||
5562          (lhs_.is(a1) && rhs_.is(a0)));
5563   const char* cc_name;
5564   switch (cc_) {
5565     case lt: cc_name = "LT"; break;
5566     case gt: cc_name = "GT"; break;
5567     case le: cc_name = "LE"; break;
5568     case ge: cc_name = "GE"; break;
5569     case eq: cc_name = "EQ"; break;
5570     case ne: cc_name = "NE"; break;
5571     default: cc_name = "UnknownCondition"; break;
5572   }
5573   bool is_equality = cc_ == eq || cc_ == ne;
5574   stream->Add("CompareStub_%s", cc_name);
5575   stream->Add(lhs_.is(a0) ? "_a0" : "_a1");
5576   stream->Add(rhs_.is(a0) ? "_a0" : "_a1");
5577   if (strict_ && is_equality) stream->Add("_STRICT");
5578   if (never_nan_nan_ && is_equality) stream->Add("_NO_NAN");
5579   if (!include_number_compare_) stream->Add("_NO_NUMBER");
5580   if (!include_smi_compare_) stream->Add("_NO_SMI");
5581 }
5582
5583
5584 int CompareStub::MinorKey() {
5585   // Encode the two parameters in a unique 16 bit value.
5586   ASSERT(static_cast<unsigned>(cc_) < (1 << 14));
5587   ASSERT((lhs_.is(a0) && rhs_.is(a1)) ||
5588          (lhs_.is(a1) && rhs_.is(a0)));
5589   return ConditionField::encode(static_cast<unsigned>(cc_))
5590          | RegisterField::encode(lhs_.is(a0))
5591          | StrictField::encode(strict_)
5592          | NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false)
5593          | IncludeSmiCompareField::encode(include_smi_compare_);
5594 }
5595
5596
5597 // StringCharCodeAtGenerator.
5598 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
5599   Label flat_string;
5600   Label ascii_string;
5601   Label got_char_code;
5602   Label sliced_string;
5603
5604   ASSERT(!t0.is(index_));
5605   ASSERT(!t0.is(result_));
5606   ASSERT(!t0.is(object_));
5607
5608   // If the receiver is a smi trigger the non-string case.
5609   __ JumpIfSmi(object_, receiver_not_string_);
5610
5611   // Fetch the instance type of the receiver into result register.
5612   __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
5613   __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
5614   // If the receiver is not a string trigger the non-string case.
5615   __ And(t0, result_, Operand(kIsNotStringMask));
5616   __ Branch(receiver_not_string_, ne, t0, Operand(zero_reg));
5617
5618   // If the index is non-smi trigger the non-smi case.
5619   __ JumpIfNotSmi(index_, &index_not_smi_);
5620
5621   __ bind(&got_smi_index_);
5622
5623   // Check for index out of range.
5624   __ lw(t0, FieldMemOperand(object_, String::kLengthOffset));
5625   __ Branch(index_out_of_range_, ls, t0, Operand(index_));
5626
5627   __ sra(index_, index_, kSmiTagSize);
5628
5629   StringCharLoadGenerator::Generate(masm,
5630                                     object_,
5631                                     index_,
5632                                     result_,
5633                                     &call_runtime_);
5634
5635   __ sll(result_, result_, kSmiTagSize);
5636   __ bind(&exit_);
5637 }
5638
5639
5640 void StringCharCodeAtGenerator::GenerateSlow(
5641     MacroAssembler* masm,
5642     const RuntimeCallHelper& call_helper) {
5643   __ Abort("Unexpected fallthrough to CharCodeAt slow case");
5644
5645   // Index is not a smi.
5646   __ bind(&index_not_smi_);
5647   // If index is a heap number, try converting it to an integer.
5648   __ CheckMap(index_,
5649               result_,
5650               Heap::kHeapNumberMapRootIndex,
5651               index_not_number_,
5652               DONT_DO_SMI_CHECK);
5653   call_helper.BeforeCall(masm);
5654   // Consumed by runtime conversion function:
5655   __ Push(object_, index_);
5656   if (index_flags_ == STRING_INDEX_IS_NUMBER) {
5657     __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
5658   } else {
5659     ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
5660     // NumberToSmi discards numbers that are not exact integers.
5661     __ CallRuntime(Runtime::kNumberToSmi, 1);
5662   }
5663
5664   // Save the conversion result before the pop instructions below
5665   // have a chance to overwrite it.
5666
5667   __ Move(index_, v0);
5668   __ pop(object_);
5669   // Reload the instance type.
5670   __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
5671   __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
5672   call_helper.AfterCall(masm);
5673   // If index is still not a smi, it must be out of range.
5674   __ JumpIfNotSmi(index_, index_out_of_range_);
5675   // Otherwise, return to the fast path.
5676   __ Branch(&got_smi_index_);
5677
5678   // Call runtime. We get here when the receiver is a string and the
5679   // index is a number, but the code of getting the actual character
5680   // is too complex (e.g., when the string needs to be flattened).
5681   __ bind(&call_runtime_);
5682   call_helper.BeforeCall(masm);
5683   __ sll(index_, index_, kSmiTagSize);
5684   __ Push(object_, index_);
5685   __ CallRuntime(Runtime::kStringCharCodeAt, 2);
5686
5687   __ Move(result_, v0);
5688
5689   call_helper.AfterCall(masm);
5690   __ jmp(&exit_);
5691
5692   __ Abort("Unexpected fallthrough from CharCodeAt slow case");
5693 }
5694
5695
5696 // -------------------------------------------------------------------------
5697 // StringCharFromCodeGenerator
5698
5699 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
5700   // Fast case of Heap::LookupSingleCharacterStringFromCode.
5701
5702   ASSERT(!t0.is(result_));
5703   ASSERT(!t0.is(code_));
5704
5705   STATIC_ASSERT(kSmiTag == 0);
5706   STATIC_ASSERT(kSmiShiftSize == 0);
5707   ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1));
5708   __ And(t0,
5709          code_,
5710          Operand(kSmiTagMask |
5711                  ((~String::kMaxAsciiCharCode) << kSmiTagSize)));
5712   __ Branch(&slow_case_, ne, t0, Operand(zero_reg));
5713
5714   __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
5715   // At this point code register contains smi tagged ASCII char code.
5716   STATIC_ASSERT(kSmiTag == 0);
5717   __ sll(t0, code_, kPointerSizeLog2 - kSmiTagSize);
5718   __ Addu(result_, result_, t0);
5719   __ lw(result_, FieldMemOperand(result_, FixedArray::kHeaderSize));
5720   __ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
5721   __ Branch(&slow_case_, eq, result_, Operand(t0));
5722   __ bind(&exit_);
5723 }
5724
5725
5726 void StringCharFromCodeGenerator::GenerateSlow(
5727     MacroAssembler* masm,
5728     const RuntimeCallHelper& call_helper) {
5729   __ Abort("Unexpected fallthrough to CharFromCode slow case");
5730
5731   __ bind(&slow_case_);
5732   call_helper.BeforeCall(masm);
5733   __ push(code_);
5734   __ CallRuntime(Runtime::kCharFromCode, 1);
5735   __ Move(result_, v0);
5736
5737   call_helper.AfterCall(masm);
5738   __ Branch(&exit_);
5739
5740   __ Abort("Unexpected fallthrough from CharFromCode slow case");
5741 }
5742
5743
5744 // -------------------------------------------------------------------------
5745 // StringCharAtGenerator
5746
5747 void StringCharAtGenerator::GenerateFast(MacroAssembler* masm) {
5748   char_code_at_generator_.GenerateFast(masm);
5749   char_from_code_generator_.GenerateFast(masm);
5750 }
5751
5752
5753 void StringCharAtGenerator::GenerateSlow(
5754     MacroAssembler* masm,
5755     const RuntimeCallHelper& call_helper) {
5756   char_code_at_generator_.GenerateSlow(masm, call_helper);
5757   char_from_code_generator_.GenerateSlow(masm, call_helper);
5758 }
5759
5760
5761 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
5762                                           Register dest,
5763                                           Register src,
5764                                           Register count,
5765                                           Register scratch,
5766                                           bool ascii) {
5767   Label loop;
5768   Label done;
5769   // This loop just copies one character at a time, as it is only used for
5770   // very short strings.
5771   if (!ascii) {
5772     __ addu(count, count, count);
5773   }
5774   __ Branch(&done, eq, count, Operand(zero_reg));
5775   __ addu(count, dest, count);  // Count now points to the last dest byte.
5776
5777   __ bind(&loop);
5778   __ lbu(scratch, MemOperand(src));
5779   __ addiu(src, src, 1);
5780   __ sb(scratch, MemOperand(dest));
5781   __ addiu(dest, dest, 1);
5782   __ Branch(&loop, lt, dest, Operand(count));
5783
5784   __ bind(&done);
5785 }
5786
5787
5788 enum CopyCharactersFlags {
5789   COPY_ASCII = 1,
5790   DEST_ALWAYS_ALIGNED = 2
5791 };
5792
5793
5794 void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm,
5795                                               Register dest,
5796                                               Register src,
5797                                               Register count,
5798                                               Register scratch1,
5799                                               Register scratch2,
5800                                               Register scratch3,
5801                                               Register scratch4,
5802                                               Register scratch5,
5803                                               int flags) {
5804   bool ascii = (flags & COPY_ASCII) != 0;
5805   bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0;
5806
5807   if (dest_always_aligned && FLAG_debug_code) {
5808     // Check that destination is actually word aligned if the flag says
5809     // that it is.
5810     __ And(scratch4, dest, Operand(kPointerAlignmentMask));
5811     __ Check(eq,
5812              "Destination of copy not aligned.",
5813              scratch4,
5814              Operand(zero_reg));
5815   }
5816
5817   const int kReadAlignment = 4;
5818   const int kReadAlignmentMask = kReadAlignment - 1;
5819   // Ensure that reading an entire aligned word containing the last character
5820   // of a string will not read outside the allocated area (because we pad up
5821   // to kObjectAlignment).
5822   STATIC_ASSERT(kObjectAlignment >= kReadAlignment);
5823   // Assumes word reads and writes are little endian.
5824   // Nothing to do for zero characters.
5825   Label done;
5826
5827   if (!ascii) {
5828     __ addu(count, count, count);
5829   }
5830   __ Branch(&done, eq, count, Operand(zero_reg));
5831
5832   Label byte_loop;
5833   // Must copy at least eight bytes, otherwise just do it one byte at a time.
5834   __ Subu(scratch1, count, Operand(8));
5835   __ Addu(count, dest, Operand(count));
5836   Register limit = count;  // Read until src equals this.
5837   __ Branch(&byte_loop, lt, scratch1, Operand(zero_reg));
5838
5839   if (!dest_always_aligned) {
5840     // Align dest by byte copying. Copies between zero and three bytes.
5841     __ And(scratch4, dest, Operand(kReadAlignmentMask));
5842     Label dest_aligned;
5843     __ Branch(&dest_aligned, eq, scratch4, Operand(zero_reg));
5844     Label aligned_loop;
5845     __ bind(&aligned_loop);
5846     __ lbu(scratch1, MemOperand(src));
5847     __ addiu(src, src, 1);
5848     __ sb(scratch1, MemOperand(dest));
5849     __ addiu(dest, dest, 1);
5850     __ addiu(scratch4, scratch4, 1);
5851     __ Branch(&aligned_loop, le, scratch4, Operand(kReadAlignmentMask));
5852     __ bind(&dest_aligned);
5853   }
5854
5855   Label simple_loop;
5856
5857   __ And(scratch4, src, Operand(kReadAlignmentMask));
5858   __ Branch(&simple_loop, eq, scratch4, Operand(zero_reg));
5859
5860   // Loop for src/dst that are not aligned the same way.
5861   // This loop uses lwl and lwr instructions. These instructions
5862   // depend on the endianness, and the implementation assumes little-endian.
5863   {
5864     Label loop;
5865     __ bind(&loop);
5866     __ lwr(scratch1, MemOperand(src));
5867     __ Addu(src, src, Operand(kReadAlignment));
5868     __ lwl(scratch1, MemOperand(src, -1));
5869     __ sw(scratch1, MemOperand(dest));
5870     __ Addu(dest, dest, Operand(kReadAlignment));
5871     __ Subu(scratch2, limit, dest);
5872     __ Branch(&loop, ge, scratch2, Operand(kReadAlignment));
5873   }
5874
5875   __ Branch(&byte_loop);
5876
5877   // Simple loop.
5878   // Copy words from src to dest, until less than four bytes left.
5879   // Both src and dest are word aligned.
5880   __ bind(&simple_loop);
5881   {
5882     Label loop;
5883     __ bind(&loop);
5884     __ lw(scratch1, MemOperand(src));
5885     __ Addu(src, src, Operand(kReadAlignment));
5886     __ sw(scratch1, MemOperand(dest));
5887     __ Addu(dest, dest, Operand(kReadAlignment));
5888     __ Subu(scratch2, limit, dest);
5889     __ Branch(&loop, ge, scratch2, Operand(kReadAlignment));
5890   }
5891
5892   // Copy bytes from src to dest until dest hits limit.
5893   __ bind(&byte_loop);
5894   // Test if dest has already reached the limit.
5895   __ Branch(&done, ge, dest, Operand(limit));
5896   __ lbu(scratch1, MemOperand(src));
5897   __ addiu(src, src, 1);
5898   __ sb(scratch1, MemOperand(dest));
5899   __ addiu(dest, dest, 1);
5900   __ Branch(&byte_loop);
5901
5902   __ bind(&done);
5903 }
5904
5905
5906 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
5907                                                         Register c1,
5908                                                         Register c2,
5909                                                         Register scratch1,
5910                                                         Register scratch2,
5911                                                         Register scratch3,
5912                                                         Register scratch4,
5913                                                         Register scratch5,
5914                                                         Label* not_found) {
5915   // Register scratch3 is the general scratch register in this function.
5916   Register scratch = scratch3;
5917
5918   // Make sure that both characters are not digits as such strings has a
5919   // different hash algorithm. Don't try to look for these in the symbol table.
5920   Label not_array_index;
5921   __ Subu(scratch, c1, Operand(static_cast<int>('0')));
5922   __ Branch(&not_array_index,
5923             Ugreater,
5924             scratch,
5925             Operand(static_cast<int>('9' - '0')));
5926   __ Subu(scratch, c2, Operand(static_cast<int>('0')));
5927
5928   // If check failed combine both characters into single halfword.
5929   // This is required by the contract of the method: code at the
5930   // not_found branch expects this combination in c1 register.
5931   Label tmp;
5932   __ sll(scratch1, c2, kBitsPerByte);
5933   __ Branch(&tmp, Ugreater, scratch, Operand(static_cast<int>('9' - '0')));
5934   __ Or(c1, c1, scratch1);
5935   __ bind(&tmp);
5936   __ Branch(
5937       not_found, Uless_equal, scratch, Operand(static_cast<int>('9' - '0')));
5938
5939   __ bind(&not_array_index);
5940   // Calculate the two character string hash.
5941   Register hash = scratch1;
5942   StringHelper::GenerateHashInit(masm, hash, c1);
5943   StringHelper::GenerateHashAddCharacter(masm, hash, c2);
5944   StringHelper::GenerateHashGetHash(masm, hash);
5945
5946   // Collect the two characters in a register.
5947   Register chars = c1;
5948   __ sll(scratch, c2, kBitsPerByte);
5949   __ Or(chars, chars, scratch);
5950
5951   // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
5952   // hash:  hash of two character string.
5953
5954   // Load symbol table.
5955   // Load address of first element of the symbol table.
5956   Register symbol_table = c2;
5957   __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex);
5958
5959   Register undefined = scratch4;
5960   __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
5961
5962   // Calculate capacity mask from the symbol table capacity.
5963   Register mask = scratch2;
5964   __ lw(mask, FieldMemOperand(symbol_table, SymbolTable::kCapacityOffset));
5965   __ sra(mask, mask, 1);
5966   __ Addu(mask, mask, -1);
5967
5968   // Calculate untagged address of the first element of the symbol table.
5969   Register first_symbol_table_element = symbol_table;
5970   __ Addu(first_symbol_table_element, symbol_table,
5971          Operand(SymbolTable::kElementsStartOffset - kHeapObjectTag));
5972
5973   // Registers.
5974   // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
5975   // hash:  hash of two character string
5976   // mask:  capacity mask
5977   // first_symbol_table_element: address of the first element of
5978   //                             the symbol table
5979   // undefined: the undefined object
5980   // scratch: -
5981
5982   // Perform a number of probes in the symbol table.
5983   const int kProbes = 4;
5984   Label found_in_symbol_table;
5985   Label next_probe[kProbes];
5986   Register candidate = scratch5;  // Scratch register contains candidate.
5987   for (int i = 0; i < kProbes; i++) {
5988     // Calculate entry in symbol table.
5989     if (i > 0) {
5990       __ Addu(candidate, hash, Operand(SymbolTable::GetProbeOffset(i)));
5991     } else {
5992       __ mov(candidate, hash);
5993     }
5994
5995     __ And(candidate, candidate, Operand(mask));
5996
5997     // Load the entry from the symble table.
5998     STATIC_ASSERT(SymbolTable::kEntrySize == 1);
5999     __ sll(scratch, candidate, kPointerSizeLog2);
6000     __ Addu(scratch, scratch, first_symbol_table_element);
6001     __ lw(candidate, MemOperand(scratch));
6002
6003     // If entry is undefined no string with this hash can be found.
6004     Label is_string;
6005     __ GetObjectType(candidate, scratch, scratch);
6006     __ Branch(&is_string, ne, scratch, Operand(ODDBALL_TYPE));
6007
6008     __ Branch(not_found, eq, undefined, Operand(candidate));
6009     // Must be the hole (deleted entry).
6010     if (FLAG_debug_code) {
6011       __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
6012       __ Assert(eq, "oddball in symbol table is not undefined or the hole",
6013           scratch, Operand(candidate));
6014     }
6015     __ jmp(&next_probe[i]);
6016
6017     __ bind(&is_string);
6018
6019     // Check that the candidate is a non-external ASCII string.  The instance
6020     // type is still in the scratch register from the CompareObjectType
6021     // operation.
6022     __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]);
6023
6024     // If length is not 2 the string is not a candidate.
6025     __ lw(scratch, FieldMemOperand(candidate, String::kLengthOffset));
6026     __ Branch(&next_probe[i], ne, scratch, Operand(Smi::FromInt(2)));
6027
6028     // Check if the two characters match.
6029     // Assumes that word load is little endian.
6030     __ lhu(scratch, FieldMemOperand(candidate, SeqAsciiString::kHeaderSize));
6031     __ Branch(&found_in_symbol_table, eq, chars, Operand(scratch));
6032     __ bind(&next_probe[i]);
6033   }
6034
6035   // No matching 2 character string found by probing.
6036   __ jmp(not_found);
6037
6038   // Scratch register contains result when we fall through to here.
6039   Register result = candidate;
6040   __ bind(&found_in_symbol_table);
6041   __ mov(v0, result);
6042 }
6043
6044
6045 void StringHelper::GenerateHashInit(MacroAssembler* masm,
6046                                     Register hash,
6047                                     Register character) {
6048   // hash = seed + character + ((seed + character) << 10);
6049   __ LoadRoot(hash, Heap::kHashSeedRootIndex);
6050   // Untag smi seed and add the character.
6051   __ SmiUntag(hash);
6052   __ addu(hash, hash, character);
6053   __ sll(at, hash, 10);
6054   __ addu(hash, hash, at);
6055   // hash ^= hash >> 6;
6056   __ srl(at, hash, 6);
6057   __ xor_(hash, hash, at);
6058 }
6059
6060
6061 void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
6062                                             Register hash,
6063                                             Register character) {
6064   // hash += character;
6065   __ addu(hash, hash, character);
6066   // hash += hash << 10;
6067   __ sll(at, hash, 10);
6068   __ addu(hash, hash, at);
6069   // hash ^= hash >> 6;
6070   __ srl(at, hash, 6);
6071   __ xor_(hash, hash, at);
6072 }
6073
6074
6075 void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
6076                                        Register hash) {
6077   // hash += hash << 3;
6078   __ sll(at, hash, 3);
6079   __ addu(hash, hash, at);
6080   // hash ^= hash >> 11;
6081   __ srl(at, hash, 11);
6082   __ xor_(hash, hash, at);
6083   // hash += hash << 15;
6084   __ sll(at, hash, 15);
6085   __ addu(hash, hash, at);
6086
6087   __ li(at, Operand(String::kHashBitMask));
6088   __ and_(hash, hash, at);
6089
6090   // if (hash == 0) hash = 27;
6091   __ ori(at, zero_reg, StringHasher::kZeroHash);
6092   __ Movz(hash, at, hash);
6093 }
6094
6095
6096 void SubStringStub::Generate(MacroAssembler* masm) {
6097   Label runtime;
6098   // Stack frame on entry.
6099   //  ra: return address
6100   //  sp[0]: to
6101   //  sp[4]: from
6102   //  sp[8]: string
6103
6104   // This stub is called from the native-call %_SubString(...), so
6105   // nothing can be assumed about the arguments. It is tested that:
6106   //  "string" is a sequential string,
6107   //  both "from" and "to" are smis, and
6108   //  0 <= from <= to <= string.length.
6109   // If any of these assumptions fail, we call the runtime system.
6110
6111   const int kToOffset = 0 * kPointerSize;
6112   const int kFromOffset = 1 * kPointerSize;
6113   const int kStringOffset = 2 * kPointerSize;
6114
6115   __ lw(a2, MemOperand(sp, kToOffset));
6116   __ lw(a3, MemOperand(sp, kFromOffset));
6117   STATIC_ASSERT(kFromOffset == kToOffset + 4);
6118   STATIC_ASSERT(kSmiTag == 0);
6119   STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
6120
6121   // Utilize delay slots. SmiUntag doesn't emit a jump, everything else is
6122   // safe in this case.
6123   __ UntagAndJumpIfNotSmi(a2, a2, &runtime);
6124   __ UntagAndJumpIfNotSmi(a3, a3, &runtime);
6125   // Both a2 and a3 are untagged integers.
6126
6127   __ Branch(&runtime, lt, a3, Operand(zero_reg));  // From < 0.
6128
6129   __ Branch(&runtime, gt, a3, Operand(a2));  // Fail if from > to.
6130   __ Subu(a2, a2, a3);
6131
6132   // Make sure first argument is a string.
6133   __ lw(v0, MemOperand(sp, kStringOffset));
6134   __ JumpIfSmi(v0, &runtime);
6135   __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
6136   __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset));
6137   __ And(t0, a1, Operand(kIsNotStringMask));
6138
6139   __ Branch(&runtime, ne, t0, Operand(zero_reg));
6140
6141   // Short-cut for the case of trivial substring.
6142   Label return_v0;
6143   // v0: original string
6144   // a2: result string length
6145   __ lw(t0, FieldMemOperand(v0, String::kLengthOffset));
6146   __ sra(t0, t0, 1);
6147   __ Branch(&return_v0, eq, a2, Operand(t0));
6148
6149
6150   Label result_longer_than_two;
6151   // Check for special case of two character ASCII string, in which case
6152   // we do a lookup in the symbol table first.
6153   __ li(t0, 2);
6154   __ Branch(&result_longer_than_two, gt, a2, Operand(t0));
6155   __ Branch(&runtime, lt, a2, Operand(t0));
6156
6157   __ JumpIfInstanceTypeIsNotSequentialAscii(a1, a1, &runtime);
6158
6159   // Get the two characters forming the sub string.
6160   __ Addu(v0, v0, Operand(a3));
6161   __ lbu(a3, FieldMemOperand(v0, SeqAsciiString::kHeaderSize));
6162   __ lbu(t0, FieldMemOperand(v0, SeqAsciiString::kHeaderSize + 1));
6163
6164   // Try to lookup two character string in symbol table.
6165   Label make_two_character_string;
6166   StringHelper::GenerateTwoCharacterSymbolTableProbe(
6167       masm, a3, t0, a1, t1, t2, t3, t4, &make_two_character_string);
6168   __ jmp(&return_v0);
6169
6170   // a2: result string length.
6171   // a3: two characters combined into halfword in little endian byte order.
6172   __ bind(&make_two_character_string);
6173   __ AllocateAsciiString(v0, a2, t0, t1, t4, &runtime);
6174   __ sh(a3, FieldMemOperand(v0, SeqAsciiString::kHeaderSize));
6175   __ jmp(&return_v0);
6176
6177   __ bind(&result_longer_than_two);
6178
6179   // Deal with different string types: update the index if necessary
6180   // and put the underlying string into t1.
6181   // v0: original string
6182   // a1: instance type
6183   // a2: length
6184   // a3: from index (untagged)
6185   Label underlying_unpacked, sliced_string, seq_or_external_string;
6186   // If the string is not indirect, it can only be sequential or external.
6187   STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
6188   STATIC_ASSERT(kIsIndirectStringMask != 0);
6189   __ And(t0, a1, Operand(kIsIndirectStringMask));
6190   __ Branch(USE_DELAY_SLOT, &seq_or_external_string, eq, t0, Operand(zero_reg));
6191   // t0 is used as a scratch register and can be overwritten in either case.
6192   __ And(t0, a1, Operand(kSlicedNotConsMask));
6193   __ Branch(&sliced_string, ne, t0, Operand(zero_reg));
6194   // Cons string.  Check whether it is flat, then fetch first part.
6195   __ lw(t1, FieldMemOperand(v0, ConsString::kSecondOffset));
6196   __ LoadRoot(t0, Heap::kEmptyStringRootIndex);
6197   __ Branch(&runtime, ne, t1, Operand(t0));
6198   __ lw(t1, FieldMemOperand(v0, ConsString::kFirstOffset));
6199   // Update instance type.
6200   __ lw(a1, FieldMemOperand(t1, HeapObject::kMapOffset));
6201   __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset));
6202   __ jmp(&underlying_unpacked);
6203
6204   __ bind(&sliced_string);
6205   // Sliced string.  Fetch parent and correct start index by offset.
6206   __ lw(t1, FieldMemOperand(v0, SlicedString::kParentOffset));
6207   __ lw(t0, FieldMemOperand(v0, SlicedString::kOffsetOffset));
6208   __ sra(t0, t0, 1);  // Add offset to index.
6209   __ Addu(a3, a3, t0);
6210   // Update instance type.
6211   __ lw(a1, FieldMemOperand(t1, HeapObject::kMapOffset));
6212   __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset));
6213   __ jmp(&underlying_unpacked);
6214
6215   __ bind(&seq_or_external_string);
6216   // Sequential or external string.  Just move string to the expected register.
6217   __ mov(t1, v0);
6218
6219   __ bind(&underlying_unpacked);
6220
6221   if (FLAG_string_slices) {
6222     Label copy_routine;
6223     // t1: underlying subject string
6224     // a1: instance type of underlying subject string
6225     // a2: length
6226     // a3: adjusted start index (untagged)
6227     // Short slice.  Copy instead of slicing.
6228     __ Branch(&copy_routine, lt, a2, Operand(SlicedString::kMinLength));
6229     // Allocate new sliced string.  At this point we do not reload the instance
6230     // type including the string encoding because we simply rely on the info
6231     // provided by the original string.  It does not matter if the original
6232     // string's encoding is wrong because we always have to recheck encoding of
6233     // the newly created string's parent anyways due to externalized strings.
6234     Label two_byte_slice, set_slice_header;
6235     STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
6236     STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
6237     __ And(t0, a1, Operand(kStringEncodingMask));
6238     __ Branch(&two_byte_slice, eq, t0, Operand(zero_reg));
6239     __ AllocateAsciiSlicedString(v0, a2, t2, t3, &runtime);
6240     __ jmp(&set_slice_header);
6241     __ bind(&two_byte_slice);
6242     __ AllocateTwoByteSlicedString(v0, a2, t2, t3, &runtime);
6243     __ bind(&set_slice_header);
6244     __ sll(a3, a3, 1);
6245     __ sw(t1, FieldMemOperand(v0, SlicedString::kParentOffset));
6246     __ sw(a3, FieldMemOperand(v0, SlicedString::kOffsetOffset));
6247     __ jmp(&return_v0);
6248
6249     __ bind(&copy_routine);
6250   }
6251
6252   // t1: underlying subject string
6253   // a1: instance type of underlying subject string
6254   // a2: length
6255   // a3: adjusted start index (untagged)
6256   Label two_byte_sequential, sequential_string, allocate_result;
6257   STATIC_ASSERT(kExternalStringTag != 0);
6258   STATIC_ASSERT(kSeqStringTag == 0);
6259   __ And(t0, a1, Operand(kExternalStringTag));
6260   __ Branch(&sequential_string, eq, t0, Operand(zero_reg));
6261
6262   // Handle external string.
6263   // Rule out short external strings.
6264   STATIC_CHECK(kShortExternalStringTag != 0);
6265   __ And(t0, a1, Operand(kShortExternalStringTag));
6266   __ Branch(&runtime, ne, t0, Operand(zero_reg));
6267   __ lw(t1, FieldMemOperand(t1, ExternalString::kResourceDataOffset));
6268   // t1 already points to the first character of underlying string.
6269   __ jmp(&allocate_result);
6270
6271   __ bind(&sequential_string);
6272   // Locate first character of underlying subject string.
6273   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize);
6274   __ Addu(t1, t1, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
6275
6276   __ bind(&allocate_result);
6277   // Sequential acii string.  Allocate the result.
6278   STATIC_ASSERT((kAsciiStringTag & kStringEncodingMask) != 0);
6279   __ And(t0, a1, Operand(kStringEncodingMask));
6280   __ Branch(&two_byte_sequential, eq, t0, Operand(zero_reg));
6281
6282   // Allocate and copy the resulting ASCII string.
6283   __ AllocateAsciiString(v0, a2, t0, t2, t3, &runtime);
6284
6285   // Locate first character of substring to copy.
6286   __ Addu(t1, t1, a3);
6287
6288   // Locate first character of result.
6289   __ Addu(a1, v0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
6290
6291   // v0: result string
6292   // a1: first character of result string
6293   // a2: result string length
6294   // t1: first character of substring to copy
6295   STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
6296   StringHelper::GenerateCopyCharactersLong(
6297       masm, a1, t1, a2, a3, t0, t2, t3, t4, COPY_ASCII | DEST_ALWAYS_ALIGNED);
6298   __ jmp(&return_v0);
6299
6300   // Allocate and copy the resulting two-byte string.
6301   __ bind(&two_byte_sequential);
6302   __ AllocateTwoByteString(v0, a2, t0, t2, t3, &runtime);
6303
6304   // Locate first character of substring to copy.
6305   STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
6306   __ sll(t0, a3, 1);
6307   __ Addu(t1, t1, t0);
6308   // Locate first character of result.
6309   __ Addu(a1, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
6310
6311   // v0: result string.
6312   // a1: first character of result.
6313   // a2: result length.
6314   // t1: first character of substring to copy.
6315   STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
6316   StringHelper::GenerateCopyCharactersLong(
6317       masm, a1, t1, a2, a3, t0, t2, t3, t4, DEST_ALWAYS_ALIGNED);
6318
6319   __ bind(&return_v0);
6320   Counters* counters = masm->isolate()->counters();
6321   __ IncrementCounter(counters->sub_string_native(), 1, a3, t0);
6322   __ DropAndRet(3);
6323
6324   // Just jump to runtime to create the sub string.
6325   __ bind(&runtime);
6326   __ TailCallRuntime(Runtime::kSubString, 3, 1);
6327 }
6328
6329
6330 void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
6331                                                       Register left,
6332                                                       Register right,
6333                                                       Register scratch1,
6334                                                       Register scratch2,
6335                                                       Register scratch3) {
6336   Register length = scratch1;
6337
6338   // Compare lengths.
6339   Label strings_not_equal, check_zero_length;
6340   __ lw(length, FieldMemOperand(left, String::kLengthOffset));
6341   __ lw(scratch2, FieldMemOperand(right, String::kLengthOffset));
6342   __ Branch(&check_zero_length, eq, length, Operand(scratch2));
6343   __ bind(&strings_not_equal);
6344   __ li(v0, Operand(Smi::FromInt(NOT_EQUAL)));
6345   __ Ret();
6346
6347   // Check if the length is zero.
6348   Label compare_chars;
6349   __ bind(&check_zero_length);
6350   STATIC_ASSERT(kSmiTag == 0);
6351   __ Branch(&compare_chars, ne, length, Operand(zero_reg));
6352   __ li(v0, Operand(Smi::FromInt(EQUAL)));
6353   __ Ret();
6354
6355   // Compare characters.
6356   __ bind(&compare_chars);
6357
6358   GenerateAsciiCharsCompareLoop(masm,
6359                                 left, right, length, scratch2, scratch3, v0,
6360                                 &strings_not_equal);
6361
6362   // Characters are equal.
6363   __ li(v0, Operand(Smi::FromInt(EQUAL)));
6364   __ Ret();
6365 }
6366
6367
6368 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
6369                                                         Register left,
6370                                                         Register right,
6371                                                         Register scratch1,
6372                                                         Register scratch2,
6373                                                         Register scratch3,
6374                                                         Register scratch4) {
6375   Label result_not_equal, compare_lengths;
6376   // Find minimum length and length difference.
6377   __ lw(scratch1, FieldMemOperand(left, String::kLengthOffset));
6378   __ lw(scratch2, FieldMemOperand(right, String::kLengthOffset));
6379   __ Subu(scratch3, scratch1, Operand(scratch2));
6380   Register length_delta = scratch3;
6381   __ slt(scratch4, scratch2, scratch1);
6382   __ Movn(scratch1, scratch2, scratch4);
6383   Register min_length = scratch1;
6384   STATIC_ASSERT(kSmiTag == 0);
6385   __ Branch(&compare_lengths, eq, min_length, Operand(zero_reg));
6386
6387   // Compare loop.
6388   GenerateAsciiCharsCompareLoop(masm,
6389                                 left, right, min_length, scratch2, scratch4, v0,
6390                                 &result_not_equal);
6391
6392   // Compare lengths - strings up to min-length are equal.
6393   __ bind(&compare_lengths);
6394   ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0));
6395   // Use length_delta as result if it's zero.
6396   __ mov(scratch2, length_delta);
6397   __ mov(scratch4, zero_reg);
6398   __ mov(v0, zero_reg);
6399
6400   __ bind(&result_not_equal);
6401   // Conditionally update the result based either on length_delta or
6402   // the last comparion performed in the loop above.
6403   Label ret;
6404   __ Branch(&ret, eq, scratch2, Operand(scratch4));
6405   __ li(v0, Operand(Smi::FromInt(GREATER)));
6406   __ Branch(&ret, gt, scratch2, Operand(scratch4));
6407   __ li(v0, Operand(Smi::FromInt(LESS)));
6408   __ bind(&ret);
6409   __ Ret();
6410 }
6411
6412
6413 void StringCompareStub::GenerateAsciiCharsCompareLoop(
6414     MacroAssembler* masm,
6415     Register left,
6416     Register right,
6417     Register length,
6418     Register scratch1,
6419     Register scratch2,
6420     Register scratch3,
6421     Label* chars_not_equal) {
6422   // Change index to run from -length to -1 by adding length to string
6423   // start. This means that loop ends when index reaches zero, which
6424   // doesn't need an additional compare.
6425   __ SmiUntag(length);
6426   __ Addu(scratch1, length,
6427           Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
6428   __ Addu(left, left, Operand(scratch1));
6429   __ Addu(right, right, Operand(scratch1));
6430   __ Subu(length, zero_reg, length);
6431   Register index = length;  // index = -length;
6432
6433
6434   // Compare loop.
6435   Label loop;
6436   __ bind(&loop);
6437   __ Addu(scratch3, left, index);
6438   __ lbu(scratch1, MemOperand(scratch3));
6439   __ Addu(scratch3, right, index);
6440   __ lbu(scratch2, MemOperand(scratch3));
6441   __ Branch(chars_not_equal, ne, scratch1, Operand(scratch2));
6442   __ Addu(index, index, 1);
6443   __ Branch(&loop, ne, index, Operand(zero_reg));
6444 }
6445
6446
6447 void StringCompareStub::Generate(MacroAssembler* masm) {
6448   Label runtime;
6449
6450   Counters* counters = masm->isolate()->counters();
6451
6452   // Stack frame on entry.
6453   //  sp[0]: right string
6454   //  sp[4]: left string
6455   __ lw(a1, MemOperand(sp, 1 * kPointerSize));  // Left.
6456   __ lw(a0, MemOperand(sp, 0 * kPointerSize));  // Right.
6457
6458   Label not_same;
6459   __ Branch(&not_same, ne, a0, Operand(a1));
6460   STATIC_ASSERT(EQUAL == 0);
6461   STATIC_ASSERT(kSmiTag == 0);
6462   __ li(v0, Operand(Smi::FromInt(EQUAL)));
6463   __ IncrementCounter(counters->string_compare_native(), 1, a1, a2);
6464   __ DropAndRet(2);
6465
6466   __ bind(&not_same);
6467
6468   // Check that both objects are sequential ASCII strings.
6469   __ JumpIfNotBothSequentialAsciiStrings(a1, a0, a2, a3, &runtime);
6470
6471   // Compare flat ASCII strings natively. Remove arguments from stack first.
6472   __ IncrementCounter(counters->string_compare_native(), 1, a2, a3);
6473   __ Addu(sp, sp, Operand(2 * kPointerSize));
6474   GenerateCompareFlatAsciiStrings(masm, a1, a0, a2, a3, t0, t1);
6475
6476   __ bind(&runtime);
6477   __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
6478 }
6479
6480
6481 void StringAddStub::Generate(MacroAssembler* masm) {
6482   Label call_runtime, call_builtin;
6483   Builtins::JavaScript builtin_id = Builtins::ADD;
6484
6485   Counters* counters = masm->isolate()->counters();
6486
6487   // Stack on entry:
6488   // sp[0]: second argument (right).
6489   // sp[4]: first argument (left).
6490
6491   // Load the two arguments.
6492   __ lw(a0, MemOperand(sp, 1 * kPointerSize));  // First argument.
6493   __ lw(a1, MemOperand(sp, 0 * kPointerSize));  // Second argument.
6494
6495   // Make sure that both arguments are strings if not known in advance.
6496   if (flags_ == NO_STRING_ADD_FLAGS) {
6497     __ JumpIfEitherSmi(a0, a1, &call_runtime);
6498     // Load instance types.
6499     __ lw(t0, FieldMemOperand(a0, HeapObject::kMapOffset));
6500     __ lw(t1, FieldMemOperand(a1, HeapObject::kMapOffset));
6501     __ lbu(t0, FieldMemOperand(t0, Map::kInstanceTypeOffset));
6502     __ lbu(t1, FieldMemOperand(t1, Map::kInstanceTypeOffset));
6503     STATIC_ASSERT(kStringTag == 0);
6504     // If either is not a string, go to runtime.
6505     __ Or(t4, t0, Operand(t1));
6506     __ And(t4, t4, Operand(kIsNotStringMask));
6507     __ Branch(&call_runtime, ne, t4, Operand(zero_reg));
6508   } else {
6509     // Here at least one of the arguments is definitely a string.
6510     // We convert the one that is not known to be a string.
6511     if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) {
6512       ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0);
6513       GenerateConvertArgument(
6514           masm, 1 * kPointerSize, a0, a2, a3, t0, t1, &call_builtin);
6515       builtin_id = Builtins::STRING_ADD_RIGHT;
6516     } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) {
6517       ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0);
6518       GenerateConvertArgument(
6519           masm, 0 * kPointerSize, a1, a2, a3, t0, t1, &call_builtin);
6520       builtin_id = Builtins::STRING_ADD_LEFT;
6521     }
6522   }
6523
6524   // Both arguments are strings.
6525   // a0: first string
6526   // a1: second string
6527   // t0: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
6528   // t1: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
6529   {
6530     Label strings_not_empty;
6531     // Check if either of the strings are empty. In that case return the other.
6532     // These tests use zero-length check on string-length whch is an Smi.
6533     // Assert that Smi::FromInt(0) is really 0.
6534     STATIC_ASSERT(kSmiTag == 0);
6535     ASSERT(Smi::FromInt(0) == 0);
6536     __ lw(a2, FieldMemOperand(a0, String::kLengthOffset));
6537     __ lw(a3, FieldMemOperand(a1, String::kLengthOffset));
6538     __ mov(v0, a0);       // Assume we'll return first string (from a0).
6539     __ Movz(v0, a1, a2);  // If first is empty, return second (from a1).
6540     __ slt(t4, zero_reg, a2);   // if (a2 > 0) t4 = 1.
6541     __ slt(t5, zero_reg, a3);   // if (a3 > 0) t5 = 1.
6542     __ and_(t4, t4, t5);        // Branch if both strings were non-empty.
6543     __ Branch(&strings_not_empty, ne, t4, Operand(zero_reg));
6544
6545     __ IncrementCounter(counters->string_add_native(), 1, a2, a3);
6546     __ DropAndRet(2);
6547
6548     __ bind(&strings_not_empty);
6549   }
6550
6551   // Untag both string-lengths.
6552   __ sra(a2, a2, kSmiTagSize);
6553   __ sra(a3, a3, kSmiTagSize);
6554
6555   // Both strings are non-empty.
6556   // a0: first string
6557   // a1: second string
6558   // a2: length of first string
6559   // a3: length of second string
6560   // t0: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
6561   // t1: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
6562   // Look at the length of the result of adding the two strings.
6563   Label string_add_flat_result, longer_than_two;
6564   // Adding two lengths can't overflow.
6565   STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2);
6566   __ Addu(t2, a2, Operand(a3));
6567   // Use the symbol table when adding two one character strings, as it
6568   // helps later optimizations to return a symbol here.
6569   __ Branch(&longer_than_two, ne, t2, Operand(2));
6570
6571   // Check that both strings are non-external ASCII strings.
6572   if (flags_ != NO_STRING_ADD_FLAGS) {
6573     __ lw(t0, FieldMemOperand(a0, HeapObject::kMapOffset));
6574     __ lw(t1, FieldMemOperand(a1, HeapObject::kMapOffset));
6575     __ lbu(t0, FieldMemOperand(t0, Map::kInstanceTypeOffset));
6576     __ lbu(t1, FieldMemOperand(t1, Map::kInstanceTypeOffset));
6577   }
6578   __ JumpIfBothInstanceTypesAreNotSequentialAscii(t0, t1, t2, t3,
6579                                                  &call_runtime);
6580
6581   // Get the two characters forming the sub string.
6582   __ lbu(a2, FieldMemOperand(a0, SeqAsciiString::kHeaderSize));
6583   __ lbu(a3, FieldMemOperand(a1, SeqAsciiString::kHeaderSize));
6584
6585   // Try to lookup two character string in symbol table. If it is not found
6586   // just allocate a new one.
6587   Label make_two_character_string;
6588   StringHelper::GenerateTwoCharacterSymbolTableProbe(
6589       masm, a2, a3, t2, t3, t0, t1, t5, &make_two_character_string);
6590   __ IncrementCounter(counters->string_add_native(), 1, a2, a3);
6591   __ DropAndRet(2);
6592
6593   __ bind(&make_two_character_string);
6594   // Resulting string has length 2 and first chars of two strings
6595   // are combined into single halfword in a2 register.
6596   // So we can fill resulting string without two loops by a single
6597   // halfword store instruction (which assumes that processor is
6598   // in a little endian mode).
6599   __ li(t2, Operand(2));
6600   __ AllocateAsciiString(v0, t2, t0, t1, t5, &call_runtime);
6601   __ sh(a2, FieldMemOperand(v0, SeqAsciiString::kHeaderSize));
6602   __ IncrementCounter(counters->string_add_native(), 1, a2, a3);
6603   __ DropAndRet(2);
6604
6605   __ bind(&longer_than_two);
6606   // Check if resulting string will be flat.
6607   __ Branch(&string_add_flat_result, lt, t2, Operand(ConsString::kMinLength));
6608   // Handle exceptionally long strings in the runtime system.
6609   STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0);
6610   ASSERT(IsPowerOf2(String::kMaxLength + 1));
6611   // kMaxLength + 1 is representable as shifted literal, kMaxLength is not.
6612   __ Branch(&call_runtime, hs, t2, Operand(String::kMaxLength + 1));
6613
6614   // If result is not supposed to be flat, allocate a cons string object.
6615   // If both strings are ASCII the result is an ASCII cons string.
6616   if (flags_ != NO_STRING_ADD_FLAGS) {
6617     __ lw(t0, FieldMemOperand(a0, HeapObject::kMapOffset));
6618     __ lw(t1, FieldMemOperand(a1, HeapObject::kMapOffset));
6619     __ lbu(t0, FieldMemOperand(t0, Map::kInstanceTypeOffset));
6620     __ lbu(t1, FieldMemOperand(t1, Map::kInstanceTypeOffset));
6621   }
6622   Label non_ascii, allocated, ascii_data;
6623   STATIC_ASSERT(kTwoByteStringTag == 0);
6624   // Branch to non_ascii if either string-encoding field is zero (non-ASCII).
6625   __ And(t4, t0, Operand(t1));
6626   __ And(t4, t4, Operand(kStringEncodingMask));
6627   __ Branch(&non_ascii, eq, t4, Operand(zero_reg));
6628
6629   // Allocate an ASCII cons string.
6630   __ bind(&ascii_data);
6631   __ AllocateAsciiConsString(v0, t2, t0, t1, &call_runtime);
6632   __ bind(&allocated);
6633   // Fill the fields of the cons string.
6634   __ sw(a0, FieldMemOperand(v0, ConsString::kFirstOffset));
6635   __ sw(a1, FieldMemOperand(v0, ConsString::kSecondOffset));
6636   __ IncrementCounter(counters->string_add_native(), 1, a2, a3);
6637   __ DropAndRet(2);
6638
6639   __ bind(&non_ascii);
6640   // At least one of the strings is two-byte. Check whether it happens
6641   // to contain only ASCII characters.
6642   // t0: first instance type.
6643   // t1: second instance type.
6644   // Branch to if _both_ instances have kAsciiDataHintMask set.
6645   __ And(at, t0, Operand(kAsciiDataHintMask));
6646   __ and_(at, at, t1);
6647   __ Branch(&ascii_data, ne, at, Operand(zero_reg));
6648
6649   __ xor_(t0, t0, t1);
6650   STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0);
6651   __ And(t0, t0, Operand(kAsciiStringTag | kAsciiDataHintTag));
6652   __ Branch(&ascii_data, eq, t0, Operand(kAsciiStringTag | kAsciiDataHintTag));
6653
6654   // Allocate a two byte cons string.
6655   __ AllocateTwoByteConsString(v0, t2, t0, t1, &call_runtime);
6656   __ Branch(&allocated);
6657
6658   // We cannot encounter sliced strings or cons strings here since:
6659   STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
6660   // Handle creating a flat result from either external or sequential strings.
6661   // Locate the first characters' locations.
6662   // a0: first string
6663   // a1: second string
6664   // a2: length of first string
6665   // a3: length of second string
6666   // t0: first string instance type (if flags_ == NO_STRING_ADD_FLAGS)
6667   // t1: second string instance type (if flags_ == NO_STRING_ADD_FLAGS)
6668   // t2: sum of lengths.
6669   Label first_prepared, second_prepared;
6670   __ bind(&string_add_flat_result);
6671   if (flags_ != NO_STRING_ADD_FLAGS) {
6672     __ lw(t0, FieldMemOperand(a0, HeapObject::kMapOffset));
6673     __ lw(t1, FieldMemOperand(a1, HeapObject::kMapOffset));
6674     __ lbu(t0, FieldMemOperand(t0, Map::kInstanceTypeOffset));
6675     __ lbu(t1, FieldMemOperand(t1, Map::kInstanceTypeOffset));
6676   }
6677   // Check whether both strings have same encoding
6678   __ Xor(t3, t0, Operand(t1));
6679   __ And(t3, t3, Operand(kStringEncodingMask));
6680   __ Branch(&call_runtime, ne, t3, Operand(zero_reg));
6681
6682   STATIC_ASSERT(kSeqStringTag == 0);
6683   __ And(t4, t0, Operand(kStringRepresentationMask));
6684
6685   STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
6686   Label skip_first_add;
6687   __ Branch(&skip_first_add, ne, t4, Operand(zero_reg));
6688   __ Branch(USE_DELAY_SLOT, &first_prepared);
6689   __ addiu(t3, a0, SeqAsciiString::kHeaderSize - kHeapObjectTag);
6690   __ bind(&skip_first_add);
6691   // External string: rule out short external string and load string resource.
6692   STATIC_ASSERT(kShortExternalStringTag != 0);
6693   __ And(t4, t0, Operand(kShortExternalStringMask));
6694   __ Branch(&call_runtime, ne, t4, Operand(zero_reg));
6695   __ lw(t3, FieldMemOperand(a0, ExternalString::kResourceDataOffset));
6696   __ bind(&first_prepared);
6697
6698   STATIC_ASSERT(kSeqStringTag == 0);
6699   __ And(t4, t1, Operand(kStringRepresentationMask));
6700   STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
6701   Label skip_second_add;
6702   __ Branch(&skip_second_add, ne, t4, Operand(zero_reg));
6703   __ Branch(USE_DELAY_SLOT, &second_prepared);
6704   __ addiu(a1, a1, SeqAsciiString::kHeaderSize - kHeapObjectTag);
6705   __ bind(&skip_second_add);
6706   // External string: rule out short external string and load string resource.
6707   STATIC_ASSERT(kShortExternalStringTag != 0);
6708   __ And(t4, t1, Operand(kShortExternalStringMask));
6709   __ Branch(&call_runtime, ne, t4, Operand(zero_reg));
6710   __ lw(a1, FieldMemOperand(a1, ExternalString::kResourceDataOffset));
6711   __ bind(&second_prepared);
6712
6713   Label non_ascii_string_add_flat_result;
6714   // t3: first character of first string
6715   // a1: first character of second string
6716   // a2: length of first string
6717   // a3: length of second string
6718   // t2: sum of lengths.
6719   // Both strings have the same encoding.
6720   STATIC_ASSERT(kTwoByteStringTag == 0);
6721   __ And(t4, t1, Operand(kStringEncodingMask));
6722   __ Branch(&non_ascii_string_add_flat_result, eq, t4, Operand(zero_reg));
6723
6724   __ AllocateAsciiString(v0, t2, t0, t1, t5, &call_runtime);
6725   __ Addu(t2, v0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
6726   // v0: result string.
6727   // t3: first character of first string.
6728   // a1: first character of second string
6729   // a2: length of first string.
6730   // a3: length of second string.
6731   // t2: first character of result.
6732
6733   StringHelper::GenerateCopyCharacters(masm, t2, t3, a2, t0, true);
6734   // t2: next character of result.
6735   StringHelper::GenerateCopyCharacters(masm, t2, a1, a3, t0, true);
6736   __ IncrementCounter(counters->string_add_native(), 1, a2, a3);
6737   __ DropAndRet(2);
6738
6739   __ bind(&non_ascii_string_add_flat_result);
6740   __ AllocateTwoByteString(v0, t2, t0, t1, t5, &call_runtime);
6741   __ Addu(t2, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
6742   // v0: result string.
6743   // t3: first character of first string.
6744   // a1: first character of second string.
6745   // a2: length of first string.
6746   // a3: length of second string.
6747   // t2: first character of result.
6748   StringHelper::GenerateCopyCharacters(masm, t2, t3, a2, t0, false);
6749   // t2: next character of result.
6750   StringHelper::GenerateCopyCharacters(masm, t2, a1, a3, t0, false);
6751
6752   __ IncrementCounter(counters->string_add_native(), 1, a2, a3);
6753   __ DropAndRet(2);
6754
6755   // Just jump to runtime to add the two strings.
6756   __ bind(&call_runtime);
6757   __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
6758
6759   if (call_builtin.is_linked()) {
6760     __ bind(&call_builtin);
6761     __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
6762   }
6763 }
6764
6765
6766 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
6767                                             int stack_offset,
6768                                             Register arg,
6769                                             Register scratch1,
6770                                             Register scratch2,
6771                                             Register scratch3,
6772                                             Register scratch4,
6773                                             Label* slow) {
6774   // First check if the argument is already a string.
6775   Label not_string, done;
6776   __ JumpIfSmi(arg, &not_string);
6777   __ GetObjectType(arg, scratch1, scratch1);
6778   __ Branch(&done, lt, scratch1, Operand(FIRST_NONSTRING_TYPE));
6779
6780   // Check the number to string cache.
6781   Label not_cached;
6782   __ bind(&not_string);
6783   // Puts the cached result into scratch1.
6784   NumberToStringStub::GenerateLookupNumberStringCache(masm,
6785                                                       arg,
6786                                                       scratch1,
6787                                                       scratch2,
6788                                                       scratch3,
6789                                                       scratch4,
6790                                                       false,
6791                                                       &not_cached);
6792   __ mov(arg, scratch1);
6793   __ sw(arg, MemOperand(sp, stack_offset));
6794   __ jmp(&done);
6795
6796   // Check if the argument is a safe string wrapper.
6797   __ bind(&not_cached);
6798   __ JumpIfSmi(arg, slow);
6799   __ GetObjectType(arg, scratch1, scratch2);  // map -> scratch1.
6800   __ Branch(slow, ne, scratch2, Operand(JS_VALUE_TYPE));
6801   __ lbu(scratch2, FieldMemOperand(scratch1, Map::kBitField2Offset));
6802   __ li(scratch4, 1 << Map::kStringWrapperSafeForDefaultValueOf);
6803   __ And(scratch2, scratch2, scratch4);
6804   __ Branch(slow, ne, scratch2, Operand(scratch4));
6805   __ lw(arg, FieldMemOperand(arg, JSValue::kValueOffset));
6806   __ sw(arg, MemOperand(sp, stack_offset));
6807
6808   __ bind(&done);
6809 }
6810
6811
6812 void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
6813   ASSERT(state_ == CompareIC::SMIS);
6814   Label miss;
6815   __ Or(a2, a1, a0);
6816   __ JumpIfNotSmi(a2, &miss);
6817
6818   if (GetCondition() == eq) {
6819     // For equality we do not care about the sign of the result.
6820     __ Subu(v0, a0, a1);
6821   } else {
6822     // Untag before subtracting to avoid handling overflow.
6823     __ SmiUntag(a1);
6824     __ SmiUntag(a0);
6825     __ Subu(v0, a1, a0);
6826   }
6827   __ Ret();
6828
6829   __ bind(&miss);
6830   GenerateMiss(masm);
6831 }
6832
6833
6834 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
6835   ASSERT(state_ == CompareIC::HEAP_NUMBERS);
6836
6837   Label generic_stub;
6838   Label unordered, maybe_undefined1, maybe_undefined2;
6839   Label miss;
6840   __ And(a2, a1, Operand(a0));
6841   __ JumpIfSmi(a2, &generic_stub);
6842
6843   __ GetObjectType(a0, a2, a2);
6844   __ Branch(&maybe_undefined1, ne, a2, Operand(HEAP_NUMBER_TYPE));
6845   __ GetObjectType(a1, a2, a2);
6846   __ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE));
6847
6848   // Inlining the double comparison and falling back to the general compare
6849   // stub if NaN is involved or FPU is unsupported.
6850   if (CpuFeatures::IsSupported(FPU)) {
6851     CpuFeatures::Scope scope(FPU);
6852
6853     // Load left and right operand.
6854     __ Subu(a2, a1, Operand(kHeapObjectTag));
6855     __ ldc1(f0, MemOperand(a2, HeapNumber::kValueOffset));
6856     __ Subu(a2, a0, Operand(kHeapObjectTag));
6857     __ ldc1(f2, MemOperand(a2, HeapNumber::kValueOffset));
6858
6859     // Return a result of -1, 0, or 1, or use CompareStub for NaNs.
6860     Label fpu_eq, fpu_lt;
6861     // Test if equal, and also handle the unordered/NaN case.
6862     __ BranchF(&fpu_eq, &unordered, eq, f0, f2);
6863
6864     // Test if less (unordered case is already handled).
6865     __ BranchF(&fpu_lt, NULL, lt, f0, f2);
6866
6867     // Otherwise it's greater, so just fall thru, and return.
6868     __ li(v0, Operand(GREATER));
6869     __ Ret();
6870
6871     __ bind(&fpu_eq);
6872     __ li(v0, Operand(EQUAL));
6873     __ Ret();
6874
6875     __ bind(&fpu_lt);
6876     __ li(v0, Operand(LESS));
6877     __ Ret();
6878   }
6879
6880   __ bind(&unordered);
6881
6882   CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS, a1, a0);
6883   __ bind(&generic_stub);
6884   __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
6885
6886   __ bind(&maybe_undefined1);
6887   if (Token::IsOrderedRelationalCompareOp(op_)) {
6888     __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
6889     __ Branch(&miss, ne, a0, Operand(at));
6890     __ GetObjectType(a1, a2, a2);
6891     __ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE));
6892     __ jmp(&unordered);
6893   }
6894
6895   __ bind(&maybe_undefined2);
6896   if (Token::IsOrderedRelationalCompareOp(op_)) {
6897     __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
6898     __ Branch(&unordered, eq, a1, Operand(at));
6899   }
6900
6901   __ bind(&miss);
6902   GenerateMiss(masm);
6903 }
6904
6905
6906 void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
6907   ASSERT(state_ == CompareIC::SYMBOLS);
6908   Label miss;
6909
6910   // Registers containing left and right operands respectively.
6911   Register left = a1;
6912   Register right = a0;
6913   Register tmp1 = a2;
6914   Register tmp2 = a3;
6915
6916   // Check that both operands are heap objects.
6917   __ JumpIfEitherSmi(left, right, &miss);
6918
6919   // Check that both operands are symbols.
6920   __ lw(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
6921   __ lw(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
6922   __ lbu(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
6923   __ lbu(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
6924   STATIC_ASSERT(kSymbolTag != 0);
6925   __ And(tmp1, tmp1, Operand(tmp2));
6926   __ And(tmp1, tmp1, kIsSymbolMask);
6927   __ Branch(&miss, eq, tmp1, Operand(zero_reg));
6928   // Make sure a0 is non-zero. At this point input operands are
6929   // guaranteed to be non-zero.
6930   ASSERT(right.is(a0));
6931   STATIC_ASSERT(EQUAL == 0);
6932   STATIC_ASSERT(kSmiTag == 0);
6933   __ mov(v0, right);
6934   // Symbols are compared by identity.
6935   __ Ret(ne, left, Operand(right));
6936   __ li(v0, Operand(Smi::FromInt(EQUAL)));
6937   __ Ret();
6938
6939   __ bind(&miss);
6940   GenerateMiss(masm);
6941 }
6942
6943
6944 void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
6945   ASSERT(state_ == CompareIC::STRINGS);
6946   Label miss;
6947
6948   bool equality = Token::IsEqualityOp(op_);
6949
6950   // Registers containing left and right operands respectively.
6951   Register left = a1;
6952   Register right = a0;
6953   Register tmp1 = a2;
6954   Register tmp2 = a3;
6955   Register tmp3 = t0;
6956   Register tmp4 = t1;
6957   Register tmp5 = t2;
6958
6959   // Check that both operands are heap objects.
6960   __ JumpIfEitherSmi(left, right, &miss);
6961
6962   // Check that both operands are strings. This leaves the instance
6963   // types loaded in tmp1 and tmp2.
6964   __ lw(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
6965   __ lw(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
6966   __ lbu(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
6967   __ lbu(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
6968   STATIC_ASSERT(kNotStringTag != 0);
6969   __ Or(tmp3, tmp1, tmp2);
6970   __ And(tmp5, tmp3, Operand(kIsNotStringMask));
6971   __ Branch(&miss, ne, tmp5, Operand(zero_reg));
6972
6973   // Fast check for identical strings.
6974   Label left_ne_right;
6975   STATIC_ASSERT(EQUAL == 0);
6976   STATIC_ASSERT(kSmiTag == 0);
6977   __ Branch(&left_ne_right, ne, left, Operand(right));
6978   __ Ret(USE_DELAY_SLOT);
6979   __ mov(v0, zero_reg);  // In the delay slot.
6980   __ bind(&left_ne_right);
6981
6982   // Handle not identical strings.
6983
6984   // Check that both strings are symbols. If they are, we're done
6985   // because we already know they are not identical.
6986   if (equality) {
6987     ASSERT(GetCondition() == eq);
6988     STATIC_ASSERT(kSymbolTag != 0);
6989     __ And(tmp3, tmp1, Operand(tmp2));
6990     __ And(tmp5, tmp3, Operand(kIsSymbolMask));
6991     Label is_symbol;
6992     __ Branch(&is_symbol, eq, tmp5, Operand(zero_reg));
6993     // Make sure a0 is non-zero. At this point input operands are
6994     // guaranteed to be non-zero.
6995     ASSERT(right.is(a0));
6996     __ Ret(USE_DELAY_SLOT);
6997     __ mov(v0, a0);  // In the delay slot.
6998     __ bind(&is_symbol);
6999   }
7000
7001   // Check that both strings are sequential ASCII.
7002   Label runtime;
7003   __ JumpIfBothInstanceTypesAreNotSequentialAscii(
7004       tmp1, tmp2, tmp3, tmp4, &runtime);
7005
7006   // Compare flat ASCII strings. Returns when done.
7007   if (equality) {
7008     StringCompareStub::GenerateFlatAsciiStringEquals(
7009         masm, left, right, tmp1, tmp2, tmp3);
7010   } else {
7011     StringCompareStub::GenerateCompareFlatAsciiStrings(
7012         masm, left, right, tmp1, tmp2, tmp3, tmp4);
7013   }
7014
7015   // Handle more complex cases in runtime.
7016   __ bind(&runtime);
7017   __ Push(left, right);
7018   if (equality) {
7019     __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
7020   } else {
7021     __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
7022   }
7023
7024   __ bind(&miss);
7025   GenerateMiss(masm);
7026 }
7027
7028
7029 void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
7030   ASSERT(state_ == CompareIC::OBJECTS);
7031   Label miss;
7032   __ And(a2, a1, Operand(a0));
7033   __ JumpIfSmi(a2, &miss);
7034
7035   // Compare lhs, a2 holds the map, a3 holds the type_reg
7036   __ GetObjectType(a0, a2, a3);
7037   __ Branch(&miss, ne, a3, Operand(JS_OBJECT_TYPE));
7038   __ lbu(a2, FieldMemOperand(a2, Map::kBitField2Offset));
7039   __ And(a2, a2, Operand(1 << Map::kUseUserObjectComparison));
7040   __ Branch(&miss, eq, a2, Operand(1 << Map::kUseUserObjectComparison));
7041
7042
7043   // Compare rhs, a2 holds the map, a3 holds the type_reg
7044   __ GetObjectType(a1, a2, a3);
7045   __ Branch(&miss, ne, a3, Operand(JS_OBJECT_TYPE));
7046   __ lbu(a2, FieldMemOperand(a2, Map::kBitField2Offset));
7047   __ And(a2, a2, Operand(1 << Map::kUseUserObjectComparison));
7048   __ Branch(&miss, eq, a2, Operand(1 << Map::kUseUserObjectComparison));
7049
7050   ASSERT(GetCondition() == eq);
7051   __ Ret(USE_DELAY_SLOT);
7052   __ subu(v0, a0, a1);
7053
7054   __ bind(&miss);
7055   GenerateMiss(masm);
7056 }
7057
7058
7059 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) {
7060   Label miss;
7061   __ And(a2, a1, a0);
7062   __ JumpIfSmi(a2, &miss);
7063   __ lw(a2, FieldMemOperand(a0, HeapObject::kMapOffset));
7064   __ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset));
7065
7066   // Check object in a0
7067   __ Branch(&miss, ne, a2, Operand(known_map_));
7068   __ lbu(a2, FieldMemOperand(a2, Map::kBitField2Offset));
7069   __ And(a2, a2, Operand(1 << Map::kUseUserObjectComparison));
7070   __ Branch(&miss, eq, a2, Operand(1 << Map::kUseUserObjectComparison));
7071
7072   // Check object in a1
7073   __ Branch(&miss, ne, a3, Operand(known_map_));
7074   __ lbu(a3, FieldMemOperand(a3, Map::kBitField2Offset));
7075   __ And(a3, a3, Operand(1 << Map::kUseUserObjectComparison));
7076   __ Branch(&miss, eq, a3, Operand(1 << Map::kUseUserObjectComparison));
7077
7078   __ Ret(USE_DELAY_SLOT);
7079   __ subu(v0, a0, a1);
7080
7081   __ bind(&miss);
7082   GenerateMiss(masm);
7083 }
7084
7085 void ICCompareStub::GenerateMiss(MacroAssembler* masm) {
7086   {
7087     // Call the runtime system in a fresh internal frame.
7088     ExternalReference miss =
7089         ExternalReference(IC_Utility(IC::kCompareIC_Miss), masm->isolate());
7090     FrameScope scope(masm, StackFrame::INTERNAL);
7091     __ Push(a1, a0);
7092     __ push(ra);
7093     __ Push(a1, a0);
7094     __ li(t0, Operand(Smi::FromInt(op_)));
7095     __ addiu(sp, sp, -kPointerSize);
7096     __ CallExternalReference(miss, 3, USE_DELAY_SLOT);
7097     __ sw(t0, MemOperand(sp));  // In the delay slot.
7098     // Compute the entry point of the rewritten stub.
7099     __ Addu(a2, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
7100     // Restore registers.
7101     __ Pop(a1, a0, ra);
7102   }
7103   __ Jump(a2);
7104 }
7105
7106
7107 void DirectCEntryStub::Generate(MacroAssembler* masm) {
7108   // No need to pop or drop anything, LeaveExitFrame will restore the old
7109   // stack, thus dropping the allocated space for the return value.
7110   // The saved ra is after the reserved stack space for the 4 args.
7111   __ lw(t9, MemOperand(sp, kCArgsSlotsSize));
7112
7113   if (FLAG_debug_code && FLAG_enable_slow_asserts) {
7114     // In case of an error the return address may point to a memory area
7115     // filled with kZapValue by the GC.
7116     // Dereference the address and check for this.
7117     __ lw(t0, MemOperand(t9));
7118     __ Assert(ne, "Received invalid return address.", t0,
7119         Operand(reinterpret_cast<uint32_t>(kZapValue)));
7120   }
7121   __ Jump(t9);
7122 }
7123
7124
7125 void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
7126                                     ExternalReference function) {
7127   __ li(t9, Operand(function));
7128   this->GenerateCall(masm, t9);
7129 }
7130
7131
7132 void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
7133                                     Register target) {
7134   __ Move(t9, target);
7135   __ AssertStackIsAligned();
7136   // Allocate space for arg slots.
7137   __ Subu(sp, sp, kCArgsSlotsSize);
7138
7139   // Block the trampoline pool through the whole function to make sure the
7140   // number of generated instructions is constant.
7141   Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm);
7142
7143   // We need to get the current 'pc' value, which is not available on MIPS.
7144   Label find_ra;
7145   masm->bal(&find_ra);  // ra = pc + 8.
7146   masm->nop();  // Branch delay slot nop.
7147   masm->bind(&find_ra);
7148
7149   const int kNumInstructionsToJump = 6;
7150   masm->addiu(ra, ra, kNumInstructionsToJump * kPointerSize);
7151   // Push return address (accessible to GC through exit frame pc).
7152   // This spot for ra was reserved in EnterExitFrame.
7153   masm->sw(ra, MemOperand(sp, kCArgsSlotsSize));
7154   masm->li(ra,
7155            Operand(reinterpret_cast<intptr_t>(GetCode().location()),
7156                    RelocInfo::CODE_TARGET),
7157            CONSTANT_SIZE);
7158   // Call the function.
7159   masm->Jump(t9);
7160   // Make sure the stored 'ra' points to this position.
7161   ASSERT_EQ(kNumInstructionsToJump, masm->InstructionsGeneratedSince(&find_ra));
7162 }
7163
7164
7165 void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
7166                                                         Label* miss,
7167                                                         Label* done,
7168                                                         Register receiver,
7169                                                         Register properties,
7170                                                         Handle<String> name,
7171                                                         Register scratch0) {
7172   // If names of slots in range from 1 to kProbes - 1 for the hash value are
7173   // not equal to the name and kProbes-th slot is not used (its name is the
7174   // undefined value), it guarantees the hash table doesn't contain the
7175   // property. It's true even if some slots represent deleted properties
7176   // (their names are the hole value).
7177   for (int i = 0; i < kInlinedProbes; i++) {
7178     // scratch0 points to properties hash.
7179     // Compute the masked index: (hash + i + i * i) & mask.
7180     Register index = scratch0;
7181     // Capacity is smi 2^n.
7182     __ lw(index, FieldMemOperand(properties, kCapacityOffset));
7183     __ Subu(index, index, Operand(1));
7184     __ And(index, index, Operand(
7185         Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i))));
7186
7187     // Scale the index by multiplying by the entry size.
7188     ASSERT(StringDictionary::kEntrySize == 3);
7189     __ sll(at, index, 1);
7190     __ Addu(index, index, at);
7191
7192     Register entity_name = scratch0;
7193     // Having undefined at this place means the name is not contained.
7194     ASSERT_EQ(kSmiTagSize, 1);
7195     Register tmp = properties;
7196     __ sll(scratch0, index, 1);
7197     __ Addu(tmp, properties, scratch0);
7198     __ lw(entity_name, FieldMemOperand(tmp, kElementsStartOffset));
7199
7200     ASSERT(!tmp.is(entity_name));
7201     __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex);
7202     __ Branch(done, eq, entity_name, Operand(tmp));
7203
7204     if (i != kInlinedProbes - 1) {
7205       // Load the hole ready for use below:
7206       __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex);
7207
7208       // Stop if found the property.
7209       __ Branch(miss, eq, entity_name, Operand(Handle<String>(name)));
7210
7211       Label the_hole;
7212       __ Branch(&the_hole, eq, entity_name, Operand(tmp));
7213
7214       // Check if the entry name is not a symbol.
7215       __ lw(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
7216       __ lbu(entity_name,
7217              FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
7218       __ And(scratch0, entity_name, Operand(kIsSymbolMask));
7219       __ Branch(miss, eq, scratch0, Operand(zero_reg));
7220
7221       __ bind(&the_hole);
7222
7223       // Restore the properties.
7224       __ lw(properties,
7225             FieldMemOperand(receiver, JSObject::kPropertiesOffset));
7226     }
7227   }
7228
7229   const int spill_mask =
7230       (ra.bit() | t2.bit() | t1.bit() | t0.bit() | a3.bit() |
7231        a2.bit() | a1.bit() | a0.bit() | v0.bit());
7232
7233   __ MultiPush(spill_mask);
7234   __ lw(a0, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
7235   __ li(a1, Operand(Handle<String>(name)));
7236   StringDictionaryLookupStub stub(NEGATIVE_LOOKUP);
7237   __ CallStub(&stub);
7238   __ mov(at, v0);
7239   __ MultiPop(spill_mask);
7240
7241   __ Branch(done, eq, at, Operand(zero_reg));
7242   __ Branch(miss, ne, at, Operand(zero_reg));
7243 }
7244
7245
7246 // Probe the string dictionary in the |elements| register. Jump to the
7247 // |done| label if a property with the given name is found. Jump to
7248 // the |miss| label otherwise.
7249 // If lookup was successful |scratch2| will be equal to elements + 4 * index.
7250 void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
7251                                                         Label* miss,
7252                                                         Label* done,
7253                                                         Register elements,
7254                                                         Register name,
7255                                                         Register scratch1,
7256                                                         Register scratch2) {
7257   ASSERT(!elements.is(scratch1));
7258   ASSERT(!elements.is(scratch2));
7259   ASSERT(!name.is(scratch1));
7260   ASSERT(!name.is(scratch2));
7261
7262   // Assert that name contains a string.
7263   if (FLAG_debug_code) __ AbortIfNotString(name);
7264
7265   // Compute the capacity mask.
7266   __ lw(scratch1, FieldMemOperand(elements, kCapacityOffset));
7267   __ sra(scratch1, scratch1, kSmiTagSize);  // convert smi to int
7268   __ Subu(scratch1, scratch1, Operand(1));
7269
7270   // Generate an unrolled loop that performs a few probes before
7271   // giving up. Measurements done on Gmail indicate that 2 probes
7272   // cover ~93% of loads from dictionaries.
7273   for (int i = 0; i < kInlinedProbes; i++) {
7274     // Compute the masked index: (hash + i + i * i) & mask.
7275     __ lw(scratch2, FieldMemOperand(name, String::kHashFieldOffset));
7276     if (i > 0) {
7277       // Add the probe offset (i + i * i) left shifted to avoid right shifting
7278       // the hash in a separate instruction. The value hash + i + i * i is right
7279       // shifted in the following and instruction.
7280       ASSERT(StringDictionary::GetProbeOffset(i) <
7281              1 << (32 - String::kHashFieldOffset));
7282       __ Addu(scratch2, scratch2, Operand(
7283            StringDictionary::GetProbeOffset(i) << String::kHashShift));
7284     }
7285     __ srl(scratch2, scratch2, String::kHashShift);
7286     __ And(scratch2, scratch1, scratch2);
7287
7288     // Scale the index by multiplying by the element size.
7289     ASSERT(StringDictionary::kEntrySize == 3);
7290     // scratch2 = scratch2 * 3.
7291
7292     __ sll(at, scratch2, 1);
7293     __ Addu(scratch2, scratch2, at);
7294
7295     // Check if the key is identical to the name.
7296     __ sll(at, scratch2, 2);
7297     __ Addu(scratch2, elements, at);
7298     __ lw(at, FieldMemOperand(scratch2, kElementsStartOffset));
7299     __ Branch(done, eq, name, Operand(at));
7300   }
7301
7302   const int spill_mask =
7303       (ra.bit() | t2.bit() | t1.bit() | t0.bit() |
7304        a3.bit() | a2.bit() | a1.bit() | a0.bit() | v0.bit()) &
7305       ~(scratch1.bit() | scratch2.bit());
7306
7307   __ MultiPush(spill_mask);
7308   if (name.is(a0)) {
7309     ASSERT(!elements.is(a1));
7310     __ Move(a1, name);
7311     __ Move(a0, elements);
7312   } else {
7313     __ Move(a0, elements);
7314     __ Move(a1, name);
7315   }
7316   StringDictionaryLookupStub stub(POSITIVE_LOOKUP);
7317   __ CallStub(&stub);
7318   __ mov(scratch2, a2);
7319   __ mov(at, v0);
7320   __ MultiPop(spill_mask);
7321
7322   __ Branch(done, ne, at, Operand(zero_reg));
7323   __ Branch(miss, eq, at, Operand(zero_reg));
7324 }
7325
7326
7327 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
7328   // This stub overrides SometimesSetsUpAFrame() to return false.  That means
7329   // we cannot call anything that could cause a GC from this stub.
7330   // Registers:
7331   //  result: StringDictionary to probe
7332   //  a1: key
7333   //  : StringDictionary to probe.
7334   //  index_: will hold an index of entry if lookup is successful.
7335   //          might alias with result_.
7336   // Returns:
7337   //  result_ is zero if lookup failed, non zero otherwise.
7338
7339   Register result = v0;
7340   Register dictionary = a0;
7341   Register key = a1;
7342   Register index = a2;
7343   Register mask = a3;
7344   Register hash = t0;
7345   Register undefined = t1;
7346   Register entry_key = t2;
7347
7348   Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
7349
7350   __ lw(mask, FieldMemOperand(dictionary, kCapacityOffset));
7351   __ sra(mask, mask, kSmiTagSize);
7352   __ Subu(mask, mask, Operand(1));
7353
7354   __ lw(hash, FieldMemOperand(key, String::kHashFieldOffset));
7355
7356   __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
7357
7358   for (int i = kInlinedProbes; i < kTotalProbes; i++) {
7359     // Compute the masked index: (hash + i + i * i) & mask.
7360     // Capacity is smi 2^n.
7361     if (i > 0) {
7362       // Add the probe offset (i + i * i) left shifted to avoid right shifting
7363       // the hash in a separate instruction. The value hash + i + i * i is right
7364       // shifted in the following and instruction.
7365       ASSERT(StringDictionary::GetProbeOffset(i) <
7366              1 << (32 - String::kHashFieldOffset));
7367       __ Addu(index, hash, Operand(
7368            StringDictionary::GetProbeOffset(i) << String::kHashShift));
7369     } else {
7370       __ mov(index, hash);
7371     }
7372     __ srl(index, index, String::kHashShift);
7373     __ And(index, mask, index);
7374
7375     // Scale the index by multiplying by the entry size.
7376     ASSERT(StringDictionary::kEntrySize == 3);
7377     // index *= 3.
7378     __ mov(at, index);
7379     __ sll(index, index, 1);
7380     __ Addu(index, index, at);
7381
7382
7383     ASSERT_EQ(kSmiTagSize, 1);
7384     __ sll(index, index, 2);
7385     __ Addu(index, index, dictionary);
7386     __ lw(entry_key, FieldMemOperand(index, kElementsStartOffset));
7387
7388     // Having undefined at this place means the name is not contained.
7389     __ Branch(&not_in_dictionary, eq, entry_key, Operand(undefined));
7390
7391     // Stop if found the property.
7392     __ Branch(&in_dictionary, eq, entry_key, Operand(key));
7393
7394     if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
7395       // Check if the entry name is not a symbol.
7396       __ lw(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset));
7397       __ lbu(entry_key,
7398              FieldMemOperand(entry_key, Map::kInstanceTypeOffset));
7399       __ And(result, entry_key, Operand(kIsSymbolMask));
7400       __ Branch(&maybe_in_dictionary, eq, result, Operand(zero_reg));
7401     }
7402   }
7403
7404   __ bind(&maybe_in_dictionary);
7405   // If we are doing negative lookup then probing failure should be
7406   // treated as a lookup success. For positive lookup probing failure
7407   // should be treated as lookup failure.
7408   if (mode_ == POSITIVE_LOOKUP) {
7409     __ Ret(USE_DELAY_SLOT);
7410     __ mov(result, zero_reg);
7411   }
7412
7413   __ bind(&in_dictionary);
7414   __ Ret(USE_DELAY_SLOT);
7415   __ li(result, 1);
7416
7417   __ bind(&not_in_dictionary);
7418   __ Ret(USE_DELAY_SLOT);
7419   __ mov(result, zero_reg);
7420 }
7421
7422
7423 struct AheadOfTimeWriteBarrierStubList {
7424   Register object, value, address;
7425   RememberedSetAction action;
7426 };
7427
7428 #define REG(Name) { kRegister_ ## Name ## _Code }
7429
7430 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
7431   // Used in RegExpExecStub.
7432   { REG(s2), REG(s0), REG(t3), EMIT_REMEMBERED_SET },
7433   { REG(s2), REG(a2), REG(t3), EMIT_REMEMBERED_SET },
7434   // Used in CompileArrayPushCall.
7435   // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore.
7436   // Also used in KeyedStoreIC::GenerateGeneric.
7437   { REG(a3), REG(t0), REG(t1), EMIT_REMEMBERED_SET },
7438   // Used in CompileStoreGlobal.
7439   { REG(t0), REG(a1), REG(a2), OMIT_REMEMBERED_SET },
7440   // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField.
7441   { REG(a1), REG(a2), REG(a3), EMIT_REMEMBERED_SET },
7442   { REG(a3), REG(a2), REG(a1), EMIT_REMEMBERED_SET },
7443   // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField.
7444   { REG(a2), REG(a1), REG(a3), EMIT_REMEMBERED_SET },
7445   { REG(a3), REG(a1), REG(a2), EMIT_REMEMBERED_SET },
7446   // KeyedStoreStubCompiler::GenerateStoreFastElement.
7447   { REG(a3), REG(a2), REG(t0), EMIT_REMEMBERED_SET },
7448   { REG(a2), REG(a3), REG(t0), EMIT_REMEMBERED_SET },
7449   // ElementsTransitionGenerator::GenerateSmiOnlyToObject
7450   // and ElementsTransitionGenerator::GenerateSmiOnlyToDouble
7451   // and ElementsTransitionGenerator::GenerateDoubleToObject
7452   { REG(a2), REG(a3), REG(t5), EMIT_REMEMBERED_SET },
7453   { REG(a2), REG(a3), REG(t5), OMIT_REMEMBERED_SET },
7454   // ElementsTransitionGenerator::GenerateDoubleToObject
7455   { REG(t2), REG(a2), REG(a0), EMIT_REMEMBERED_SET },
7456   { REG(a2), REG(t2), REG(t5), EMIT_REMEMBERED_SET },
7457   // StoreArrayLiteralElementStub::Generate
7458   { REG(t1), REG(a0), REG(t2), EMIT_REMEMBERED_SET },
7459   // Null termination.
7460   { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET}
7461 };
7462
7463 #undef REG
7464
7465
7466 bool RecordWriteStub::IsPregenerated() {
7467   for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
7468        !entry->object.is(no_reg);
7469        entry++) {
7470     if (object_.is(entry->object) &&
7471         value_.is(entry->value) &&
7472         address_.is(entry->address) &&
7473         remembered_set_action_ == entry->action &&
7474         save_fp_regs_mode_ == kDontSaveFPRegs) {
7475       return true;
7476     }
7477   }
7478   return false;
7479 }
7480
7481
7482 bool StoreBufferOverflowStub::IsPregenerated() {
7483   return save_doubles_ == kDontSaveFPRegs || ISOLATE->fp_stubs_generated();
7484 }
7485
7486
7487 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime() {
7488   StoreBufferOverflowStub stub1(kDontSaveFPRegs);
7489   stub1.GetCode()->set_is_pregenerated(true);
7490 }
7491
7492
7493 void RecordWriteStub::GenerateFixedRegStubsAheadOfTime() {
7494   for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
7495        !entry->object.is(no_reg);
7496        entry++) {
7497     RecordWriteStub stub(entry->object,
7498                          entry->value,
7499                          entry->address,
7500                          entry->action,
7501                          kDontSaveFPRegs);
7502     stub.GetCode()->set_is_pregenerated(true);
7503   }
7504 }
7505
7506
7507 // Takes the input in 3 registers: address_ value_ and object_.  A pointer to
7508 // the value has just been written into the object, now this stub makes sure
7509 // we keep the GC informed.  The word in the object where the value has been
7510 // written is in the address register.
7511 void RecordWriteStub::Generate(MacroAssembler* masm) {
7512   Label skip_to_incremental_noncompacting;
7513   Label skip_to_incremental_compacting;
7514
7515   // The first two branch+nop instructions are generated with labels so as to
7516   // get the offset fixed up correctly by the bind(Label*) call.  We patch it
7517   // back and forth between a "bne zero_reg, zero_reg, ..." (a nop in this
7518   // position) and the "beq zero_reg, zero_reg, ..." when we start and stop
7519   // incremental heap marking.
7520   // See RecordWriteStub::Patch for details.
7521   __ beq(zero_reg, zero_reg, &skip_to_incremental_noncompacting);
7522   __ nop();
7523   __ beq(zero_reg, zero_reg, &skip_to_incremental_compacting);
7524   __ nop();
7525
7526   if (remembered_set_action_ == EMIT_REMEMBERED_SET) {
7527     __ RememberedSetHelper(object_,
7528                            address_,
7529                            value_,
7530                            save_fp_regs_mode_,
7531                            MacroAssembler::kReturnAtEnd);
7532   }
7533   __ Ret();
7534
7535   __ bind(&skip_to_incremental_noncompacting);
7536   GenerateIncremental(masm, INCREMENTAL);
7537
7538   __ bind(&skip_to_incremental_compacting);
7539   GenerateIncremental(masm, INCREMENTAL_COMPACTION);
7540
7541   // Initial mode of the stub is expected to be STORE_BUFFER_ONLY.
7542   // Will be checked in IncrementalMarking::ActivateGeneratedStub.
7543
7544   PatchBranchIntoNop(masm, 0);
7545   PatchBranchIntoNop(masm, 2 * Assembler::kInstrSize);
7546 }
7547
7548
7549 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) {
7550   regs_.Save(masm);
7551
7552   if (remembered_set_action_ == EMIT_REMEMBERED_SET) {
7553     Label dont_need_remembered_set;
7554
7555     __ lw(regs_.scratch0(), MemOperand(regs_.address(), 0));
7556     __ JumpIfNotInNewSpace(regs_.scratch0(),  // Value.
7557                            regs_.scratch0(),
7558                            &dont_need_remembered_set);
7559
7560     __ CheckPageFlag(regs_.object(),
7561                      regs_.scratch0(),
7562                      1 << MemoryChunk::SCAN_ON_SCAVENGE,
7563                      ne,
7564                      &dont_need_remembered_set);
7565
7566     // First notify the incremental marker if necessary, then update the
7567     // remembered set.
7568     CheckNeedsToInformIncrementalMarker(
7569         masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode);
7570     InformIncrementalMarker(masm, mode);
7571     regs_.Restore(masm);
7572     __ RememberedSetHelper(object_,
7573                            address_,
7574                            value_,
7575                            save_fp_regs_mode_,
7576                            MacroAssembler::kReturnAtEnd);
7577
7578     __ bind(&dont_need_remembered_set);
7579   }
7580
7581   CheckNeedsToInformIncrementalMarker(
7582       masm, kReturnOnNoNeedToInformIncrementalMarker, mode);
7583   InformIncrementalMarker(masm, mode);
7584   regs_.Restore(masm);
7585   __ Ret();
7586 }
7587
7588
7589 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm, Mode mode) {
7590   regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_);
7591   int argument_count = 3;
7592   __ PrepareCallCFunction(argument_count, regs_.scratch0());
7593   Register address =
7594       a0.is(regs_.address()) ? regs_.scratch0() : regs_.address();
7595   ASSERT(!address.is(regs_.object()));
7596   ASSERT(!address.is(a0));
7597   __ Move(address, regs_.address());
7598   __ Move(a0, regs_.object());
7599   if (mode == INCREMENTAL_COMPACTION) {
7600     __ Move(a1, address);
7601   } else {
7602     ASSERT(mode == INCREMENTAL);
7603     __ lw(a1, MemOperand(address, 0));
7604   }
7605   __ li(a2, Operand(ExternalReference::isolate_address()));
7606
7607   AllowExternalCallThatCantCauseGC scope(masm);
7608   if (mode == INCREMENTAL_COMPACTION) {
7609     __ CallCFunction(
7610         ExternalReference::incremental_evacuation_record_write_function(
7611             masm->isolate()),
7612         argument_count);
7613   } else {
7614     ASSERT(mode == INCREMENTAL);
7615     __ CallCFunction(
7616         ExternalReference::incremental_marking_record_write_function(
7617             masm->isolate()),
7618         argument_count);
7619   }
7620   regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_);
7621 }
7622
7623
7624 void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
7625     MacroAssembler* masm,
7626     OnNoNeedToInformIncrementalMarker on_no_need,
7627     Mode mode) {
7628   Label on_black;
7629   Label need_incremental;
7630   Label need_incremental_pop_scratch;
7631
7632   // Let's look at the color of the object:  If it is not black we don't have
7633   // to inform the incremental marker.
7634   __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black);
7635
7636   regs_.Restore(masm);
7637   if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
7638     __ RememberedSetHelper(object_,
7639                            address_,
7640                            value_,
7641                            save_fp_regs_mode_,
7642                            MacroAssembler::kReturnAtEnd);
7643   } else {
7644     __ Ret();
7645   }
7646
7647   __ bind(&on_black);
7648
7649   // Get the value from the slot.
7650   __ lw(regs_.scratch0(), MemOperand(regs_.address(), 0));
7651
7652   if (mode == INCREMENTAL_COMPACTION) {
7653     Label ensure_not_white;
7654
7655     __ CheckPageFlag(regs_.scratch0(),  // Contains value.
7656                      regs_.scratch1(),  // Scratch.
7657                      MemoryChunk::kEvacuationCandidateMask,
7658                      eq,
7659                      &ensure_not_white);
7660
7661     __ CheckPageFlag(regs_.object(),
7662                      regs_.scratch1(),  // Scratch.
7663                      MemoryChunk::kSkipEvacuationSlotsRecordingMask,
7664                      eq,
7665                      &need_incremental);
7666
7667     __ bind(&ensure_not_white);
7668   }
7669
7670   // We need extra registers for this, so we push the object and the address
7671   // register temporarily.
7672   __ Push(regs_.object(), regs_.address());
7673   __ EnsureNotWhite(regs_.scratch0(),  // The value.
7674                     regs_.scratch1(),  // Scratch.
7675                     regs_.object(),  // Scratch.
7676                     regs_.address(),  // Scratch.
7677                     &need_incremental_pop_scratch);
7678   __ Pop(regs_.object(), regs_.address());
7679
7680   regs_.Restore(masm);
7681   if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
7682     __ RememberedSetHelper(object_,
7683                            address_,
7684                            value_,
7685                            save_fp_regs_mode_,
7686                            MacroAssembler::kReturnAtEnd);
7687   } else {
7688     __ Ret();
7689   }
7690
7691   __ bind(&need_incremental_pop_scratch);
7692   __ Pop(regs_.object(), regs_.address());
7693
7694   __ bind(&need_incremental);
7695
7696   // Fall through when we need to inform the incremental marker.
7697 }
7698
7699
7700 void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
7701   // ----------- S t a t e -------------
7702   //  -- a0    : element value to store
7703   //  -- a1    : array literal
7704   //  -- a2    : map of array literal
7705   //  -- a3    : element index as smi
7706   //  -- t0    : array literal index in function as smi
7707   // -----------------------------------
7708
7709   Label element_done;
7710   Label double_elements;
7711   Label smi_element;
7712   Label slow_elements;
7713   Label fast_elements;
7714
7715   __ CheckFastElements(a2, t1, &double_elements);
7716   // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
7717   __ JumpIfSmi(a0, &smi_element);
7718   __ CheckFastSmiOnlyElements(a2, t1, &fast_elements);
7719
7720   // Store into the array literal requires a elements transition. Call into
7721   // the runtime.
7722   __ bind(&slow_elements);
7723   // call.
7724   __ Push(a1, a3, a0);
7725   __ lw(t1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
7726   __ lw(t1, FieldMemOperand(t1, JSFunction::kLiteralsOffset));
7727   __ Push(t1, t0);
7728   __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
7729
7730   // Array literal has ElementsKind of FAST_ELEMENTS and value is an object.
7731   __ bind(&fast_elements);
7732   __ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset));
7733   __ sll(t2, a3, kPointerSizeLog2 - kSmiTagSize);
7734   __ Addu(t2, t1, t2);
7735   __ Addu(t2, t2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
7736   __ sw(a0, MemOperand(t2, 0));
7737   // Update the write barrier for the array store.
7738   __ RecordWrite(t1, t2, a0, kRAHasNotBeenSaved, kDontSaveFPRegs,
7739                  EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
7740   __ Ret(USE_DELAY_SLOT);
7741   __ mov(v0, a0);
7742
7743   // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
7744   // FAST_ELEMENTS, and value is Smi.
7745   __ bind(&smi_element);
7746   __ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset));
7747   __ sll(t2, a3, kPointerSizeLog2 - kSmiTagSize);
7748   __ Addu(t2, t1, t2);
7749   __ sw(a0, FieldMemOperand(t2, FixedArray::kHeaderSize));
7750   __ Ret(USE_DELAY_SLOT);
7751   __ mov(v0, a0);
7752
7753   // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
7754   __ bind(&double_elements);
7755   __ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset));
7756   __ StoreNumberToDoubleElements(a0, a3, a1, t1, t2, t3, t5, a2,
7757                                  &slow_elements);
7758   __ Ret(USE_DELAY_SLOT);
7759   __ mov(v0, a0);
7760 }
7761
7762
7763 #undef __
7764
7765 } }  // namespace v8::internal
7766
7767 #endif  // V8_TARGET_ARCH_MIPS