284503977128c86ff92776424c47f3267be931c7
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / src / x64 / code-stubs-x64.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_X64)
31
32 #include "bootstrapper.h"
33 #include "code-stubs.h"
34 #include "regexp-macro-assembler.h"
35
36 namespace v8 {
37 namespace internal {
38
39 #define __ ACCESS_MASM(masm)
40
41 void ToNumberStub::Generate(MacroAssembler* masm) {
42   // The ToNumber stub takes one argument in eax.
43   Label check_heap_number, call_builtin;
44   __ SmiTest(rax);
45   __ j(not_zero, &check_heap_number, Label::kNear);
46   __ Ret();
47
48   __ bind(&check_heap_number);
49   __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
50                  Heap::kHeapNumberMapRootIndex);
51   __ j(not_equal, &call_builtin, Label::kNear);
52   __ Ret();
53
54   __ bind(&call_builtin);
55   __ pop(rcx);  // Pop return address.
56   __ push(rax);
57   __ push(rcx);  // Push return address.
58   __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
59 }
60
61
62 void FastNewClosureStub::Generate(MacroAssembler* masm) {
63   // Create a new closure from the given function info in new
64   // space. Set the context to the current context in rsi.
65   Label gc;
66   __ AllocateInNewSpace(JSFunction::kSize, rax, rbx, rcx, &gc, TAG_OBJECT);
67
68   // Get the function info from the stack.
69   __ movq(rdx, Operand(rsp, 1 * kPointerSize));
70
71   int map_index = (language_mode_ == CLASSIC_MODE)
72       ? Context::FUNCTION_MAP_INDEX
73       : Context::STRICT_MODE_FUNCTION_MAP_INDEX;
74
75   // Compute the function map in the current global context and set that
76   // as the map of the allocated object.
77   __ movq(rcx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
78   __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset));
79   __ movq(rcx, Operand(rcx, Context::SlotOffset(map_index)));
80   __ movq(FieldOperand(rax, JSObject::kMapOffset), rcx);
81
82   // Initialize the rest of the function. We don't have to update the
83   // write barrier because the allocated object is in new space.
84   __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex);
85   __ LoadRoot(rcx, Heap::kTheHoleValueRootIndex);
86   __ LoadRoot(rdi, Heap::kUndefinedValueRootIndex);
87   __ movq(FieldOperand(rax, JSObject::kPropertiesOffset), rbx);
88   __ movq(FieldOperand(rax, JSObject::kElementsOffset), rbx);
89   __ movq(FieldOperand(rax, JSFunction::kPrototypeOrInitialMapOffset), rcx);
90   __ movq(FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset), rdx);
91   __ movq(FieldOperand(rax, JSFunction::kContextOffset), rsi);
92   __ movq(FieldOperand(rax, JSFunction::kLiteralsOffset), rbx);
93   __ movq(FieldOperand(rax, JSFunction::kNextFunctionLinkOffset), rdi);
94
95   // Initialize the code pointer in the function to be the one
96   // found in the shared function info object.
97   __ movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset));
98   __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
99   __ movq(FieldOperand(rax, JSFunction::kCodeEntryOffset), rdx);
100
101
102   // Return and remove the on-stack parameter.
103   __ ret(1 * kPointerSize);
104
105   // Create a new closure through the slower runtime call.
106   __ bind(&gc);
107   __ pop(rcx);  // Temporarily remove return address.
108   __ pop(rdx);
109   __ push(rsi);
110   __ push(rdx);
111   __ PushRoot(Heap::kFalseValueRootIndex);
112   __ push(rcx);  // Restore return address.
113   __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
114 }
115
116
117 void FastNewContextStub::Generate(MacroAssembler* masm) {
118   // Try to allocate the context in new space.
119   Label gc;
120   int length = slots_ + Context::MIN_CONTEXT_SLOTS;
121   __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize,
122                         rax, rbx, rcx, &gc, TAG_OBJECT);
123
124   // Get the function from the stack.
125   __ movq(rcx, Operand(rsp, 1 * kPointerSize));
126
127   // Set up the object header.
128   __ LoadRoot(kScratchRegister, Heap::kFunctionContextMapRootIndex);
129   __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister);
130   __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length));
131
132   // Set up the fixed slots.
133   __ Set(rbx, 0);  // Set to NULL.
134   __ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx);
135   __ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rsi);
136   __ movq(Operand(rax, Context::SlotOffset(Context::EXTENSION_INDEX)), rbx);
137
138   // Copy the global object from the previous context.
139   __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
140   __ movq(Operand(rax, Context::SlotOffset(Context::GLOBAL_INDEX)), rbx);
141
142   // Initialize the rest of the slots to undefined.
143   __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
144   for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
145     __ movq(Operand(rax, Context::SlotOffset(i)), rbx);
146   }
147
148   // Return and remove the on-stack parameter.
149   __ movq(rsi, rax);
150   __ ret(1 * kPointerSize);
151
152   // Need to collect. Call into runtime system.
153   __ bind(&gc);
154   __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
155 }
156
157
158 void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
159   // Stack layout on entry:
160   //
161   // [rsp + (1 * kPointerSize)]: function
162   // [rsp + (2 * kPointerSize)]: serialized scope info
163
164   // Try to allocate the context in new space.
165   Label gc;
166   int length = slots_ + Context::MIN_CONTEXT_SLOTS;
167   __ AllocateInNewSpace(FixedArray::SizeFor(length),
168                         rax, rbx, rcx, &gc, TAG_OBJECT);
169
170   // Get the function from the stack.
171   __ movq(rcx, Operand(rsp, 1 * kPointerSize));
172
173   // Get the serialized scope info from the stack.
174   __ movq(rbx, Operand(rsp, 2 * kPointerSize));
175
176   // Set up the object header.
177   __ LoadRoot(kScratchRegister, Heap::kBlockContextMapRootIndex);
178   __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister);
179   __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length));
180
181   // If this block context is nested in the global context we get a smi
182   // sentinel instead of a function. The block context should get the
183   // canonical empty function of the global context as its closure which
184   // we still have to look up.
185   Label after_sentinel;
186   __ JumpIfNotSmi(rcx, &after_sentinel, Label::kNear);
187   if (FLAG_debug_code) {
188     const char* message = "Expected 0 as a Smi sentinel";
189     __ cmpq(rcx, Immediate(0));
190     __ Assert(equal, message);
191   }
192   __ movq(rcx, GlobalObjectOperand());
193   __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset));
194   __ movq(rcx, ContextOperand(rcx, Context::CLOSURE_INDEX));
195   __ bind(&after_sentinel);
196
197   // Set up the fixed slots.
198   __ movq(ContextOperand(rax, Context::CLOSURE_INDEX), rcx);
199   __ movq(ContextOperand(rax, Context::PREVIOUS_INDEX), rsi);
200   __ movq(ContextOperand(rax, Context::EXTENSION_INDEX), rbx);
201
202   // Copy the global object from the previous context.
203   __ movq(rbx, ContextOperand(rsi, Context::GLOBAL_INDEX));
204   __ movq(ContextOperand(rax, Context::GLOBAL_INDEX), rbx);
205
206   // Initialize the rest of the slots to the hole value.
207   __ LoadRoot(rbx, Heap::kTheHoleValueRootIndex);
208   for (int i = 0; i < slots_; i++) {
209     __ movq(ContextOperand(rax, i + Context::MIN_CONTEXT_SLOTS), rbx);
210   }
211
212   // Return and remove the on-stack parameter.
213   __ movq(rsi, rax);
214   __ ret(2 * kPointerSize);
215
216   // Need to collect. Call into runtime system.
217   __ bind(&gc);
218   __ TailCallRuntime(Runtime::kPushBlockContext, 2, 1);
219 }
220
221
222 static void GenerateFastCloneShallowArrayCommon(
223     MacroAssembler* masm,
224     int length,
225     FastCloneShallowArrayStub::Mode mode,
226     Label* fail) {
227   // Registers on entry:
228   //
229   // rcx: boilerplate literal array.
230   ASSERT(mode != FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS);
231
232   // All sizes here are multiples of kPointerSize.
233   int elements_size = 0;
234   if (length > 0) {
235     elements_size = mode == FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
236         ? FixedDoubleArray::SizeFor(length)
237         : FixedArray::SizeFor(length);
238   }
239   int size = JSArray::kSize + elements_size;
240
241   // Allocate both the JS array and the elements array in one big
242   // allocation. This avoids multiple limit checks.
243   __ AllocateInNewSpace(size, rax, rbx, rdx, fail, TAG_OBJECT);
244
245   // Copy the JS array part.
246   for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
247     if ((i != JSArray::kElementsOffset) || (length == 0)) {
248       __ movq(rbx, FieldOperand(rcx, i));
249       __ movq(FieldOperand(rax, i), rbx);
250     }
251   }
252
253   if (length > 0) {
254     // Get hold of the elements array of the boilerplate and setup the
255     // elements pointer in the resulting object.
256     __ movq(rcx, FieldOperand(rcx, JSArray::kElementsOffset));
257     __ lea(rdx, Operand(rax, JSArray::kSize));
258     __ movq(FieldOperand(rax, JSArray::kElementsOffset), rdx);
259
260     // Copy the elements array.
261     if (mode == FastCloneShallowArrayStub::CLONE_ELEMENTS) {
262       for (int i = 0; i < elements_size; i += kPointerSize) {
263         __ movq(rbx, FieldOperand(rcx, i));
264         __ movq(FieldOperand(rdx, i), rbx);
265       }
266     } else {
267       ASSERT(mode == FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS);
268       int i;
269       for (i = 0; i < FixedDoubleArray::kHeaderSize; i += kPointerSize) {
270         __ movq(rbx, FieldOperand(rcx, i));
271         __ movq(FieldOperand(rdx, i), rbx);
272       }
273       while (i < elements_size) {
274         __ movsd(xmm0, FieldOperand(rcx, i));
275         __ movsd(FieldOperand(rdx, i), xmm0);
276         i += kDoubleSize;
277       }
278       ASSERT(i == elements_size);
279     }
280   }
281 }
282
283 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
284   // Stack layout on entry:
285   //
286   // [rsp + kPointerSize]: constant elements.
287   // [rsp + (2 * kPointerSize)]: literal index.
288   // [rsp + (3 * kPointerSize)]: literals array.
289
290   // Load boilerplate object into rcx and check if we need to create a
291   // boilerplate.
292   __ movq(rcx, Operand(rsp, 3 * kPointerSize));
293   __ movq(rax, Operand(rsp, 2 * kPointerSize));
294   SmiIndex index = masm->SmiToIndex(rax, rax, kPointerSizeLog2);
295   __ movq(rcx,
296           FieldOperand(rcx, index.reg, index.scale, FixedArray::kHeaderSize));
297   __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
298   Label slow_case;
299   __ j(equal, &slow_case);
300
301   FastCloneShallowArrayStub::Mode mode = mode_;
302   // rcx is boilerplate object.
303   Factory* factory = masm->isolate()->factory();
304   if (mode == CLONE_ANY_ELEMENTS) {
305     Label double_elements, check_fast_elements;
306     __ movq(rbx, FieldOperand(rcx, JSArray::kElementsOffset));
307     __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
308            factory->fixed_cow_array_map());
309     __ j(not_equal, &check_fast_elements);
310     GenerateFastCloneShallowArrayCommon(masm, 0,
311                                         COPY_ON_WRITE_ELEMENTS, &slow_case);
312     __ ret(3 * kPointerSize);
313
314     __ bind(&check_fast_elements);
315     __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
316            factory->fixed_array_map());
317     __ j(not_equal, &double_elements);
318     GenerateFastCloneShallowArrayCommon(masm, length_,
319                                         CLONE_ELEMENTS, &slow_case);
320     __ ret(3 * kPointerSize);
321
322     __ bind(&double_elements);
323     mode = CLONE_DOUBLE_ELEMENTS;
324     // Fall through to generate the code to handle double elements.
325   }
326
327   if (FLAG_debug_code) {
328     const char* message;
329     Heap::RootListIndex expected_map_index;
330     if (mode == CLONE_ELEMENTS) {
331       message = "Expected (writable) fixed array";
332       expected_map_index = Heap::kFixedArrayMapRootIndex;
333     } else if (mode == CLONE_DOUBLE_ELEMENTS) {
334       message = "Expected (writable) fixed double array";
335       expected_map_index = Heap::kFixedDoubleArrayMapRootIndex;
336     } else {
337       ASSERT(mode == COPY_ON_WRITE_ELEMENTS);
338       message = "Expected copy-on-write fixed array";
339       expected_map_index = Heap::kFixedCOWArrayMapRootIndex;
340     }
341     __ push(rcx);
342     __ movq(rcx, FieldOperand(rcx, JSArray::kElementsOffset));
343     __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
344                    expected_map_index);
345     __ Assert(equal, message);
346     __ pop(rcx);
347   }
348
349   GenerateFastCloneShallowArrayCommon(masm, length_, mode, &slow_case);
350   __ ret(3 * kPointerSize);
351
352   __ bind(&slow_case);
353   __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
354 }
355
356
357 void FastCloneShallowObjectStub::Generate(MacroAssembler* masm) {
358   // Stack layout on entry:
359   //
360   // [rsp + kPointerSize]: object literal flags.
361   // [rsp + (2 * kPointerSize)]: constant properties.
362   // [rsp + (3 * kPointerSize)]: literal index.
363   // [rsp + (4 * kPointerSize)]: literals array.
364
365   // Load boilerplate object into ecx and check if we need to create a
366   // boilerplate.
367   Label slow_case;
368   __ movq(rcx, Operand(rsp, 4 * kPointerSize));
369   __ movq(rax, Operand(rsp, 3 * kPointerSize));
370   SmiIndex index = masm->SmiToIndex(rax, rax, kPointerSizeLog2);
371   __ movq(rcx,
372           FieldOperand(rcx, index.reg, index.scale, FixedArray::kHeaderSize));
373   __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
374   __ j(equal, &slow_case);
375
376   // Check that the boilerplate contains only fast properties and we can
377   // statically determine the instance size.
378   int size = JSObject::kHeaderSize + length_ * kPointerSize;
379   __ movq(rax, FieldOperand(rcx, HeapObject::kMapOffset));
380   __ movzxbq(rax, FieldOperand(rax, Map::kInstanceSizeOffset));
381   __ cmpq(rax, Immediate(size >> kPointerSizeLog2));
382   __ j(not_equal, &slow_case);
383
384   // Allocate the JS object and copy header together with all in-object
385   // properties from the boilerplate.
386   __ AllocateInNewSpace(size, rax, rbx, rdx, &slow_case, TAG_OBJECT);
387   for (int i = 0; i < size; i += kPointerSize) {
388     __ movq(rbx, FieldOperand(rcx, i));
389     __ movq(FieldOperand(rax, i), rbx);
390   }
391
392   // Return and remove the on-stack parameters.
393   __ ret(4 * kPointerSize);
394
395   __ bind(&slow_case);
396   __ TailCallRuntime(Runtime::kCreateObjectLiteralShallow, 4, 1);
397 }
398
399
400 // The stub expects its argument on the stack and returns its result in tos_:
401 // zero for false, and a non-zero value for true.
402 void ToBooleanStub::Generate(MacroAssembler* masm) {
403   // This stub overrides SometimesSetsUpAFrame() to return false.  That means
404   // we cannot call anything that could cause a GC from this stub.
405   Label patch;
406   const Register argument = rax;
407   const Register map = rdx;
408
409   if (!types_.IsEmpty()) {
410     __ movq(argument, Operand(rsp, 1 * kPointerSize));
411   }
412
413   // undefined -> false
414   CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false);
415
416   // Boolean -> its value
417   CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false);
418   CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true);
419
420   // 'null' -> false.
421   CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false);
422
423   if (types_.Contains(SMI)) {
424     // Smis: 0 -> false, all other -> true
425     Label not_smi;
426     __ JumpIfNotSmi(argument, &not_smi, Label::kNear);
427     // argument contains the correct return value already
428     if (!tos_.is(argument)) {
429       __ movq(tos_, argument);
430     }
431     __ ret(1 * kPointerSize);
432     __ bind(&not_smi);
433   } else if (types_.NeedsMap()) {
434     // If we need a map later and have a Smi -> patch.
435     __ JumpIfSmi(argument, &patch, Label::kNear);
436   }
437
438   if (types_.NeedsMap()) {
439     __ movq(map, FieldOperand(argument, HeapObject::kMapOffset));
440
441     if (types_.CanBeUndetectable()) {
442       __ testb(FieldOperand(map, Map::kBitFieldOffset),
443                Immediate(1 << Map::kIsUndetectable));
444       // Undetectable -> false.
445       Label not_undetectable;
446       __ j(zero, &not_undetectable, Label::kNear);
447       __ Set(tos_, 0);
448       __ ret(1 * kPointerSize);
449       __ bind(&not_undetectable);
450     }
451   }
452
453   if (types_.Contains(SPEC_OBJECT)) {
454     // spec object -> true.
455     Label not_js_object;
456     __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
457     __ j(below, &not_js_object, Label::kNear);
458     // argument contains the correct return value already.
459     if (!tos_.is(argument)) {
460       __ Set(tos_, 1);
461     }
462     __ ret(1 * kPointerSize);
463     __ bind(&not_js_object);
464   }
465
466   if (types_.Contains(STRING)) {
467     // String value -> false iff empty.
468     Label not_string;
469     __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
470     __ j(above_equal, &not_string, Label::kNear);
471     __ movq(tos_, FieldOperand(argument, String::kLengthOffset));
472     __ ret(1 * kPointerSize);  // the string length is OK as the return value
473     __ bind(&not_string);
474   }
475
476   if (types_.Contains(HEAP_NUMBER)) {
477     // heap number -> false iff +0, -0, or NaN.
478     Label not_heap_number, false_result;
479     __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
480     __ j(not_equal, &not_heap_number, Label::kNear);
481     __ xorps(xmm0, xmm0);
482     __ ucomisd(xmm0, FieldOperand(argument, HeapNumber::kValueOffset));
483     __ j(zero, &false_result, Label::kNear);
484     // argument contains the correct return value already.
485     if (!tos_.is(argument)) {
486       __ Set(tos_, 1);
487     }
488     __ ret(1 * kPointerSize);
489     __ bind(&false_result);
490     __ Set(tos_, 0);
491     __ ret(1 * kPointerSize);
492     __ bind(&not_heap_number);
493   }
494
495   __ bind(&patch);
496   GenerateTypeTransition(masm);
497 }
498
499
500 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
501   __ PushCallerSaved(save_doubles_);
502   const int argument_count = 1;
503   __ PrepareCallCFunction(argument_count);
504 #ifdef _WIN64
505   __ LoadAddress(rcx, ExternalReference::isolate_address());
506 #else
507   __ LoadAddress(rdi, ExternalReference::isolate_address());
508 #endif
509
510   AllowExternalCallThatCantCauseGC scope(masm);
511   __ CallCFunction(
512       ExternalReference::store_buffer_overflow_function(masm->isolate()),
513       argument_count);
514   __ PopCallerSaved(save_doubles_);
515   __ ret(0);
516 }
517
518
519 void ToBooleanStub::CheckOddball(MacroAssembler* masm,
520                                  Type type,
521                                  Heap::RootListIndex value,
522                                  bool result) {
523   const Register argument = rax;
524   if (types_.Contains(type)) {
525     // If we see an expected oddball, return its ToBoolean value tos_.
526     Label different_value;
527     __ CompareRoot(argument, value);
528     __ j(not_equal, &different_value, Label::kNear);
529     if (!result) {
530       // If we have to return zero, there is no way around clearing tos_.
531       __ Set(tos_, 0);
532     } else if (!tos_.is(argument)) {
533       // If we have to return non-zero, we can re-use the argument if it is the
534       // same register as the result, because we never see Smi-zero here.
535       __ Set(tos_, 1);
536     }
537     __ ret(1 * kPointerSize);
538     __ bind(&different_value);
539   }
540 }
541
542
543 void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
544   __ pop(rcx);  // Get return address, operand is now on top of stack.
545   __ Push(Smi::FromInt(tos_.code()));
546   __ Push(Smi::FromInt(types_.ToByte()));
547   __ push(rcx);  // Push return address.
548   // Patch the caller to an appropriate specialized stub and return the
549   // operation result to the caller of the stub.
550   __ TailCallExternalReference(
551       ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
552       3,
553       1);
554 }
555
556
557 class FloatingPointHelper : public AllStatic {
558  public:
559   // Load the operands from rdx and rax into xmm0 and xmm1, as doubles.
560   // If the operands are not both numbers, jump to not_numbers.
561   // Leaves rdx and rax unchanged.  SmiOperands assumes both are smis.
562   // NumberOperands assumes both are smis or heap numbers.
563   static void LoadSSE2SmiOperands(MacroAssembler* masm);
564   static void LoadSSE2NumberOperands(MacroAssembler* masm);
565   static void LoadSSE2UnknownOperands(MacroAssembler* masm,
566                                       Label* not_numbers);
567
568   // Takes the operands in rdx and rax and loads them as integers in rax
569   // and rcx.
570   static void LoadAsIntegers(MacroAssembler* masm,
571                              Label* operand_conversion_failure,
572                              Register heap_number_map);
573   // As above, but we know the operands to be numbers. In that case,
574   // conversion can't fail.
575   static void LoadNumbersAsIntegers(MacroAssembler* masm);
576
577   // Tries to convert two values to smis losslessly.
578   // This fails if either argument is not a Smi nor a HeapNumber,
579   // or if it's a HeapNumber with a value that can't be converted
580   // losslessly to a Smi. In that case, control transitions to the
581   // on_not_smis label.
582   // On success, either control goes to the on_success label (if one is
583   // provided), or it falls through at the end of the code (if on_success
584   // is NULL).
585   // On success, both first and second holds Smi tagged values.
586   // One of first or second must be non-Smi when entering.
587   static void NumbersToSmis(MacroAssembler* masm,
588                             Register first,
589                             Register second,
590                             Register scratch1,
591                             Register scratch2,
592                             Register scratch3,
593                             Label* on_success,
594                             Label* on_not_smis);
595 };
596
597
598 // Get the integer part of a heap number.
599 // Overwrites the contents of rdi, rbx and rcx. Result cannot be rdi or rbx.
600 void IntegerConvert(MacroAssembler* masm,
601                     Register result,
602                     Register source) {
603   // Result may be rcx. If result and source are the same register, source will
604   // be overwritten.
605   ASSERT(!result.is(rdi) && !result.is(rbx));
606   // TODO(lrn): When type info reaches here, if value is a 32-bit integer, use
607   // cvttsd2si (32-bit version) directly.
608   Register double_exponent = rbx;
609   Register double_value = rdi;
610   Label done, exponent_63_plus;
611   // Get double and extract exponent.
612   __ movq(double_value, FieldOperand(source, HeapNumber::kValueOffset));
613   // Clear result preemptively, in case we need to return zero.
614   __ xorl(result, result);
615   __ movq(xmm0, double_value);  // Save copy in xmm0 in case we need it there.
616   // Double to remove sign bit, shift exponent down to least significant bits.
617   // and subtract bias to get the unshifted, unbiased exponent.
618   __ lea(double_exponent, Operand(double_value, double_value, times_1, 0));
619   __ shr(double_exponent, Immediate(64 - HeapNumber::kExponentBits));
620   __ subl(double_exponent, Immediate(HeapNumber::kExponentBias));
621   // Check whether the exponent is too big for a 63 bit unsigned integer.
622   __ cmpl(double_exponent, Immediate(63));
623   __ j(above_equal, &exponent_63_plus, Label::kNear);
624   // Handle exponent range 0..62.
625   __ cvttsd2siq(result, xmm0);
626   __ jmp(&done, Label::kNear);
627
628   __ bind(&exponent_63_plus);
629   // Exponent negative or 63+.
630   __ cmpl(double_exponent, Immediate(83));
631   // If exponent negative or above 83, number contains no significant bits in
632   // the range 0..2^31, so result is zero, and rcx already holds zero.
633   __ j(above, &done, Label::kNear);
634
635   // Exponent in rage 63..83.
636   // Mantissa * 2^exponent contains bits in the range 2^0..2^31, namely
637   // the least significant exponent-52 bits.
638
639   // Negate low bits of mantissa if value is negative.
640   __ addq(double_value, double_value);  // Move sign bit to carry.
641   __ sbbl(result, result);  // And convert carry to -1 in result register.
642   // if scratch2 is negative, do (scratch2-1)^-1, otherwise (scratch2-0)^0.
643   __ addl(double_value, result);
644   // Do xor in opposite directions depending on where we want the result
645   // (depending on whether result is rcx or not).
646
647   if (result.is(rcx)) {
648     __ xorl(double_value, result);
649     // Left shift mantissa by (exponent - mantissabits - 1) to save the
650     // bits that have positional values below 2^32 (the extra -1 comes from the
651     // doubling done above to move the sign bit into the carry flag).
652     __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1));
653     __ shll_cl(double_value);
654     __ movl(result, double_value);
655   } else {
656     // As the then-branch, but move double-value to result before shifting.
657     __ xorl(result, double_value);
658     __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1));
659     __ shll_cl(result);
660   }
661
662   __ bind(&done);
663 }
664
665
666 void UnaryOpStub::Generate(MacroAssembler* masm) {
667   switch (operand_type_) {
668     case UnaryOpIC::UNINITIALIZED:
669       GenerateTypeTransition(masm);
670       break;
671     case UnaryOpIC::SMI:
672       GenerateSmiStub(masm);
673       break;
674     case UnaryOpIC::HEAP_NUMBER:
675       GenerateHeapNumberStub(masm);
676       break;
677     case UnaryOpIC::GENERIC:
678       GenerateGenericStub(masm);
679       break;
680   }
681 }
682
683
684 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
685   __ pop(rcx);  // Save return address.
686
687   __ push(rax);  // the operand
688   __ Push(Smi::FromInt(op_));
689   __ Push(Smi::FromInt(mode_));
690   __ Push(Smi::FromInt(operand_type_));
691
692   __ push(rcx);  // Push return address.
693
694   // Patch the caller to an appropriate specialized stub and return the
695   // operation result to the caller of the stub.
696   __ TailCallExternalReference(
697       ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1);
698 }
699
700
701 // TODO(svenpanne): Use virtual functions instead of switch.
702 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
703   switch (op_) {
704     case Token::SUB:
705       GenerateSmiStubSub(masm);
706       break;
707     case Token::BIT_NOT:
708       GenerateSmiStubBitNot(masm);
709       break;
710     default:
711       UNREACHABLE();
712   }
713 }
714
715
716 void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
717   Label slow;
718   GenerateSmiCodeSub(masm, &slow, &slow, Label::kNear, Label::kNear);
719   __ bind(&slow);
720   GenerateTypeTransition(masm);
721 }
722
723
724 void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
725   Label non_smi;
726   GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
727   __ bind(&non_smi);
728   GenerateTypeTransition(masm);
729 }
730
731
732 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
733                                      Label* non_smi,
734                                      Label* slow,
735                                      Label::Distance non_smi_near,
736                                      Label::Distance slow_near) {
737   Label done;
738   __ JumpIfNotSmi(rax, non_smi, non_smi_near);
739   __ SmiNeg(rax, rax, &done, Label::kNear);
740   __ jmp(slow, slow_near);
741   __ bind(&done);
742   __ ret(0);
743 }
744
745
746 void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
747                                         Label* non_smi,
748                                         Label::Distance non_smi_near) {
749   __ JumpIfNotSmi(rax, non_smi, non_smi_near);
750   __ SmiNot(rax, rax);
751   __ ret(0);
752 }
753
754
755 // TODO(svenpanne): Use virtual functions instead of switch.
756 void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
757   switch (op_) {
758     case Token::SUB:
759       GenerateHeapNumberStubSub(masm);
760       break;
761     case Token::BIT_NOT:
762       GenerateHeapNumberStubBitNot(masm);
763       break;
764     default:
765       UNREACHABLE();
766   }
767 }
768
769
770 void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
771   Label non_smi, slow, call_builtin;
772   GenerateSmiCodeSub(masm, &non_smi, &call_builtin, Label::kNear);
773   __ bind(&non_smi);
774   GenerateHeapNumberCodeSub(masm, &slow);
775   __ bind(&slow);
776   GenerateTypeTransition(masm);
777   __ bind(&call_builtin);
778   GenerateGenericCodeFallback(masm);
779 }
780
781
782 void UnaryOpStub::GenerateHeapNumberStubBitNot(
783     MacroAssembler* masm) {
784   Label non_smi, slow;
785   GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
786   __ bind(&non_smi);
787   GenerateHeapNumberCodeBitNot(masm, &slow);
788   __ bind(&slow);
789   GenerateTypeTransition(masm);
790 }
791
792
793 void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
794                                             Label* slow) {
795   // Check if the operand is a heap number.
796   __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
797                  Heap::kHeapNumberMapRootIndex);
798   __ j(not_equal, slow);
799
800   // Operand is a float, negate its value by flipping the sign bit.
801   if (mode_ == UNARY_OVERWRITE) {
802     __ Set(kScratchRegister, 0x01);
803     __ shl(kScratchRegister, Immediate(63));
804     __ xor_(FieldOperand(rax, HeapNumber::kValueOffset), kScratchRegister);
805   } else {
806     // Allocate a heap number before calculating the answer,
807     // so we don't have an untagged double around during GC.
808     Label slow_allocate_heapnumber, heapnumber_allocated;
809     __ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber);
810     __ jmp(&heapnumber_allocated);
811
812     __ bind(&slow_allocate_heapnumber);
813     {
814       FrameScope scope(masm, StackFrame::INTERNAL);
815       __ push(rax);
816       __ CallRuntime(Runtime::kNumberAlloc, 0);
817       __ movq(rcx, rax);
818       __ pop(rax);
819     }
820     __ bind(&heapnumber_allocated);
821     // rcx: allocated 'empty' number
822
823     // Copy the double value to the new heap number, flipping the sign.
824     __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset));
825     __ Set(kScratchRegister, 0x01);
826     __ shl(kScratchRegister, Immediate(63));
827     __ xor_(rdx, kScratchRegister);  // Flip sign.
828     __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx);
829     __ movq(rax, rcx);
830   }
831   __ ret(0);
832 }
833
834
835 void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm,
836                                                Label* slow) {
837   // Check if the operand is a heap number.
838   __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
839                  Heap::kHeapNumberMapRootIndex);
840   __ j(not_equal, slow);
841
842   // Convert the heap number in rax to an untagged integer in rcx.
843   IntegerConvert(masm, rax, rax);
844
845   // Do the bitwise operation and smi tag the result.
846   __ notl(rax);
847   __ Integer32ToSmi(rax, rax);
848   __ ret(0);
849 }
850
851
852 // TODO(svenpanne): Use virtual functions instead of switch.
853 void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
854   switch (op_) {
855     case Token::SUB:
856       GenerateGenericStubSub(masm);
857       break;
858     case Token::BIT_NOT:
859       GenerateGenericStubBitNot(masm);
860       break;
861     default:
862       UNREACHABLE();
863   }
864 }
865
866
867 void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
868   Label non_smi, slow;
869   GenerateSmiCodeSub(masm, &non_smi, &slow, Label::kNear);
870   __ bind(&non_smi);
871   GenerateHeapNumberCodeSub(masm, &slow);
872   __ bind(&slow);
873   GenerateGenericCodeFallback(masm);
874 }
875
876
877 void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
878   Label non_smi, slow;
879   GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
880   __ bind(&non_smi);
881   GenerateHeapNumberCodeBitNot(masm, &slow);
882   __ bind(&slow);
883   GenerateGenericCodeFallback(masm);
884 }
885
886
887 void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) {
888   // Handle the slow case by jumping to the JavaScript builtin.
889   __ pop(rcx);  // pop return address
890   __ push(rax);
891   __ push(rcx);  // push return address
892   switch (op_) {
893     case Token::SUB:
894       __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
895       break;
896     case Token::BIT_NOT:
897       __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION);
898       break;
899     default:
900       UNREACHABLE();
901   }
902 }
903
904
905 void UnaryOpStub::PrintName(StringStream* stream) {
906   const char* op_name = Token::Name(op_);
907   const char* overwrite_name = NULL;  // Make g++ happy.
908   switch (mode_) {
909     case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break;
910     case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break;
911   }
912   stream->Add("UnaryOpStub_%s_%s_%s",
913               op_name,
914               overwrite_name,
915               UnaryOpIC::GetName(operand_type_));
916 }
917
918
919 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
920   __ pop(rcx);  // Save return address.
921   __ push(rdx);
922   __ push(rax);
923   // Left and right arguments are now on top.
924   // Push this stub's key. Although the operation and the type info are
925   // encoded into the key, the encoding is opaque, so push them too.
926   __ Push(Smi::FromInt(MinorKey()));
927   __ Push(Smi::FromInt(op_));
928   __ Push(Smi::FromInt(operands_type_));
929
930   __ push(rcx);  // Push return address.
931
932   // Patch the caller to an appropriate specialized stub and return the
933   // operation result to the caller of the stub.
934   __ TailCallExternalReference(
935       ExternalReference(IC_Utility(IC::kBinaryOp_Patch),
936                         masm->isolate()),
937       5,
938       1);
939 }
940
941
942 void BinaryOpStub::Generate(MacroAssembler* masm) {
943   // Explicitly allow generation of nested stubs. It is safe here because
944   // generation code does not use any raw pointers.
945   AllowStubCallsScope allow_stub_calls(masm, true);
946
947   switch (operands_type_) {
948     case BinaryOpIC::UNINITIALIZED:
949       GenerateTypeTransition(masm);
950       break;
951     case BinaryOpIC::SMI:
952       GenerateSmiStub(masm);
953       break;
954     case BinaryOpIC::INT32:
955       UNREACHABLE();
956       // The int32 case is identical to the Smi case.  We avoid creating this
957       // ic state on x64.
958       break;
959     case BinaryOpIC::HEAP_NUMBER:
960       GenerateHeapNumberStub(masm);
961       break;
962     case BinaryOpIC::ODDBALL:
963       GenerateOddballStub(masm);
964       break;
965     case BinaryOpIC::BOTH_STRING:
966       GenerateBothStringStub(masm);
967       break;
968     case BinaryOpIC::STRING:
969       GenerateStringStub(masm);
970       break;
971     case BinaryOpIC::GENERIC:
972       GenerateGeneric(masm);
973       break;
974     default:
975       UNREACHABLE();
976   }
977 }
978
979
980 void BinaryOpStub::PrintName(StringStream* stream) {
981   const char* op_name = Token::Name(op_);
982   const char* overwrite_name;
983   switch (mode_) {
984     case NO_OVERWRITE: overwrite_name = "Alloc"; break;
985     case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
986     case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
987     default: overwrite_name = "UnknownOverwrite"; break;
988   }
989   stream->Add("BinaryOpStub_%s_%s_%s",
990               op_name,
991               overwrite_name,
992               BinaryOpIC::GetName(operands_type_));
993 }
994
995
996 void BinaryOpStub::GenerateSmiCode(
997     MacroAssembler* masm,
998     Label* slow,
999     SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
1000
1001   // Arguments to BinaryOpStub are in rdx and rax.
1002   Register left = rdx;
1003   Register right = rax;
1004
1005   // We only generate heapnumber answers for overflowing calculations
1006   // for the four basic arithmetic operations and logical right shift by 0.
1007   bool generate_inline_heapnumber_results =
1008       (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) &&
1009       (op_ == Token::ADD || op_ == Token::SUB ||
1010        op_ == Token::MUL || op_ == Token::DIV || op_ == Token::SHR);
1011
1012   // Smi check of both operands.  If op is BIT_OR, the check is delayed
1013   // until after the OR operation.
1014   Label not_smis;
1015   Label use_fp_on_smis;
1016   Label fail;
1017
1018   if (op_ != Token::BIT_OR) {
1019     Comment smi_check_comment(masm, "-- Smi check arguments");
1020     __ JumpIfNotBothSmi(left, right, &not_smis);
1021   }
1022
1023   Label smi_values;
1024   __ bind(&smi_values);
1025   // Perform the operation.
1026   Comment perform_smi(masm, "-- Perform smi operation");
1027   switch (op_) {
1028     case Token::ADD:
1029       ASSERT(right.is(rax));
1030       __ SmiAdd(right, right, left, &use_fp_on_smis);  // ADD is commutative.
1031       break;
1032
1033     case Token::SUB:
1034       __ SmiSub(left, left, right, &use_fp_on_smis);
1035       __ movq(rax, left);
1036       break;
1037
1038     case Token::MUL:
1039       ASSERT(right.is(rax));
1040       __ SmiMul(right, right, left, &use_fp_on_smis);  // MUL is commutative.
1041       break;
1042
1043     case Token::DIV:
1044       // SmiDiv will not accept left in rdx or right in rax.
1045       left = rcx;
1046       right = rbx;
1047       __ movq(rbx, rax);
1048       __ movq(rcx, rdx);
1049       __ SmiDiv(rax, left, right, &use_fp_on_smis);
1050       break;
1051
1052     case Token::MOD:
1053       // SmiMod will not accept left in rdx or right in rax.
1054       left = rcx;
1055       right = rbx;
1056       __ movq(rbx, rax);
1057       __ movq(rcx, rdx);
1058       __ SmiMod(rax, left, right, &use_fp_on_smis);
1059       break;
1060
1061     case Token::BIT_OR: {
1062       ASSERT(right.is(rax));
1063       __ SmiOrIfSmis(right, right, left, &not_smis);  // BIT_OR is commutative.
1064       break;
1065       }
1066     case Token::BIT_XOR:
1067       ASSERT(right.is(rax));
1068       __ SmiXor(right, right, left);  // BIT_XOR is commutative.
1069       break;
1070
1071     case Token::BIT_AND:
1072       ASSERT(right.is(rax));
1073       __ SmiAnd(right, right, left);  // BIT_AND is commutative.
1074       break;
1075
1076     case Token::SHL:
1077       __ SmiShiftLeft(left, left, right);
1078       __ movq(rax, left);
1079       break;
1080
1081     case Token::SAR:
1082       __ SmiShiftArithmeticRight(left, left, right);
1083       __ movq(rax, left);
1084       break;
1085
1086     case Token::SHR:
1087       __ SmiShiftLogicalRight(left, left, right, &use_fp_on_smis);
1088       __ movq(rax, left);
1089       break;
1090
1091     default:
1092       UNREACHABLE();
1093   }
1094
1095   // 5. Emit return of result in rax.  Some operations have registers pushed.
1096   __ ret(0);
1097
1098   if (use_fp_on_smis.is_linked()) {
1099     // 6. For some operations emit inline code to perform floating point
1100     //    operations on known smis (e.g., if the result of the operation
1101     //    overflowed the smi range).
1102     __ bind(&use_fp_on_smis);
1103     if (op_ == Token::DIV || op_ == Token::MOD) {
1104       // Restore left and right to rdx and rax.
1105       __ movq(rdx, rcx);
1106       __ movq(rax, rbx);
1107     }
1108
1109     if (generate_inline_heapnumber_results) {
1110       __ AllocateHeapNumber(rcx, rbx, slow);
1111       Comment perform_float(masm, "-- Perform float operation on smis");
1112       if (op_ == Token::SHR) {
1113         __ SmiToInteger32(left, left);
1114         __ cvtqsi2sd(xmm0, left);
1115       } else {
1116         FloatingPointHelper::LoadSSE2SmiOperands(masm);
1117         switch (op_) {
1118         case Token::ADD: __ addsd(xmm0, xmm1); break;
1119         case Token::SUB: __ subsd(xmm0, xmm1); break;
1120         case Token::MUL: __ mulsd(xmm0, xmm1); break;
1121         case Token::DIV: __ divsd(xmm0, xmm1); break;
1122         default: UNREACHABLE();
1123         }
1124       }
1125       __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
1126       __ movq(rax, rcx);
1127       __ ret(0);
1128     } else {
1129       __ jmp(&fail);
1130     }
1131   }
1132
1133   // 7. Non-smi operands reach the end of the code generated by
1134   //    GenerateSmiCode, and fall through to subsequent code,
1135   //    with the operands in rdx and rax.
1136   //    But first we check if non-smi values are HeapNumbers holding
1137   //    values that could be smi.
1138   __ bind(&not_smis);
1139   Comment done_comment(masm, "-- Enter non-smi code");
1140   FloatingPointHelper::NumbersToSmis(masm, left, right, rbx, rdi, rcx,
1141                                      &smi_values, &fail);
1142   __ jmp(&smi_values);
1143   __ bind(&fail);
1144 }
1145
1146
1147 void BinaryOpStub::GenerateFloatingPointCode(MacroAssembler* masm,
1148                                              Label* allocation_failure,
1149                                              Label* non_numeric_failure) {
1150   switch (op_) {
1151     case Token::ADD:
1152     case Token::SUB:
1153     case Token::MUL:
1154     case Token::DIV: {
1155       FloatingPointHelper::LoadSSE2UnknownOperands(masm, non_numeric_failure);
1156
1157       switch (op_) {
1158         case Token::ADD: __ addsd(xmm0, xmm1); break;
1159         case Token::SUB: __ subsd(xmm0, xmm1); break;
1160         case Token::MUL: __ mulsd(xmm0, xmm1); break;
1161         case Token::DIV: __ divsd(xmm0, xmm1); break;
1162         default: UNREACHABLE();
1163       }
1164       GenerateHeapResultAllocation(masm, allocation_failure);
1165       __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0);
1166       __ ret(0);
1167       break;
1168     }
1169     case Token::MOD: {
1170       // For MOD we jump to the allocation_failure label, to call runtime.
1171       __ jmp(allocation_failure);
1172       break;
1173     }
1174     case Token::BIT_OR:
1175     case Token::BIT_AND:
1176     case Token::BIT_XOR:
1177     case Token::SAR:
1178     case Token::SHL:
1179     case Token::SHR: {
1180       Label non_smi_shr_result;
1181       Register heap_number_map = r9;
1182       __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
1183       FloatingPointHelper::LoadAsIntegers(masm, non_numeric_failure,
1184                                           heap_number_map);
1185       switch (op_) {
1186         case Token::BIT_OR:  __ orl(rax, rcx); break;
1187         case Token::BIT_AND: __ andl(rax, rcx); break;
1188         case Token::BIT_XOR: __ xorl(rax, rcx); break;
1189         case Token::SAR: __ sarl_cl(rax); break;
1190         case Token::SHL: __ shll_cl(rax); break;
1191         case Token::SHR: {
1192           __ shrl_cl(rax);
1193           // Check if result is negative. This can only happen for a shift
1194           // by zero.
1195           __ testl(rax, rax);
1196           __ j(negative, &non_smi_shr_result);
1197           break;
1198         }
1199         default: UNREACHABLE();
1200       }
1201       STATIC_ASSERT(kSmiValueSize == 32);
1202       // Tag smi result and return.
1203       __ Integer32ToSmi(rax, rax);
1204       __ Ret();
1205
1206       // Logical shift right can produce an unsigned int32 that is not
1207       // an int32, and so is not in the smi range.  Allocate a heap number
1208       // in that case.
1209       if (op_ == Token::SHR) {
1210         __ bind(&non_smi_shr_result);
1211         Label allocation_failed;
1212         __ movl(rbx, rax);  // rbx holds result value (uint32 value as int64).
1213         // Allocate heap number in new space.
1214         // Not using AllocateHeapNumber macro in order to reuse
1215         // already loaded heap_number_map.
1216         __ AllocateInNewSpace(HeapNumber::kSize,
1217                               rax,
1218                               rdx,
1219                               no_reg,
1220                               &allocation_failed,
1221                               TAG_OBJECT);
1222         // Set the map.
1223         if (FLAG_debug_code) {
1224           __ AbortIfNotRootValue(heap_number_map,
1225                                  Heap::kHeapNumberMapRootIndex,
1226                                  "HeapNumberMap register clobbered.");
1227         }
1228         __ movq(FieldOperand(rax, HeapObject::kMapOffset),
1229                 heap_number_map);
1230         __ cvtqsi2sd(xmm0, rbx);
1231         __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0);
1232         __ Ret();
1233
1234         __ bind(&allocation_failed);
1235         // We need tagged values in rdx and rax for the following code,
1236         // not int32 in rax and rcx.
1237         __ Integer32ToSmi(rax, rcx);
1238         __ Integer32ToSmi(rdx, rbx);
1239         __ jmp(allocation_failure);
1240       }
1241       break;
1242     }
1243     default: UNREACHABLE(); break;
1244   }
1245   // No fall-through from this generated code.
1246   if (FLAG_debug_code) {
1247     __ Abort("Unexpected fall-through in "
1248              "BinaryStub::GenerateFloatingPointCode.");
1249   }
1250 }
1251
1252
1253 void BinaryOpStub::GenerateStringAddCode(MacroAssembler* masm) {
1254   ASSERT(op_ == Token::ADD);
1255   Label left_not_string, call_runtime;
1256
1257   // Registers containing left and right operands respectively.
1258   Register left = rdx;
1259   Register right = rax;
1260
1261   // Test if left operand is a string.
1262   __ JumpIfSmi(left, &left_not_string, Label::kNear);
1263   __ CmpObjectType(left, FIRST_NONSTRING_TYPE, rcx);
1264   __ j(above_equal, &left_not_string, Label::kNear);
1265   StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB);
1266   GenerateRegisterArgsPush(masm);
1267   __ TailCallStub(&string_add_left_stub);
1268
1269   // Left operand is not a string, test right.
1270   __ bind(&left_not_string);
1271   __ JumpIfSmi(right, &call_runtime, Label::kNear);
1272   __ CmpObjectType(right, FIRST_NONSTRING_TYPE, rcx);
1273   __ j(above_equal, &call_runtime, Label::kNear);
1274
1275   StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB);
1276   GenerateRegisterArgsPush(masm);
1277   __ TailCallStub(&string_add_right_stub);
1278
1279   // Neither argument is a string.
1280   __ bind(&call_runtime);
1281 }
1282
1283
1284 void BinaryOpStub::GenerateCallRuntimeCode(MacroAssembler* masm) {
1285   GenerateRegisterArgsPush(masm);
1286   switch (op_) {
1287     case Token::ADD:
1288       __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION);
1289       break;
1290     case Token::SUB:
1291       __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION);
1292       break;
1293     case Token::MUL:
1294       __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION);
1295       break;
1296     case Token::DIV:
1297       __ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION);
1298       break;
1299     case Token::MOD:
1300       __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION);
1301       break;
1302     case Token::BIT_OR:
1303       __ InvokeBuiltin(Builtins::BIT_OR, JUMP_FUNCTION);
1304       break;
1305     case Token::BIT_AND:
1306       __ InvokeBuiltin(Builtins::BIT_AND, JUMP_FUNCTION);
1307       break;
1308     case Token::BIT_XOR:
1309       __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_FUNCTION);
1310       break;
1311     case Token::SAR:
1312       __ InvokeBuiltin(Builtins::SAR, JUMP_FUNCTION);
1313       break;
1314     case Token::SHL:
1315       __ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION);
1316       break;
1317     case Token::SHR:
1318       __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION);
1319       break;
1320     default:
1321       UNREACHABLE();
1322   }
1323 }
1324
1325
1326 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
1327   Label call_runtime;
1328   if (result_type_ == BinaryOpIC::UNINITIALIZED ||
1329       result_type_ == BinaryOpIC::SMI) {
1330     // Only allow smi results.
1331     GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS);
1332   } else {
1333     // Allow heap number result and don't make a transition if a heap number
1334     // cannot be allocated.
1335     GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
1336   }
1337
1338   // Code falls through if the result is not returned as either a smi or heap
1339   // number.
1340   GenerateTypeTransition(masm);
1341
1342   if (call_runtime.is_linked()) {
1343     __ bind(&call_runtime);
1344     GenerateCallRuntimeCode(masm);
1345   }
1346 }
1347
1348
1349 void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
1350   ASSERT(operands_type_ == BinaryOpIC::STRING);
1351   ASSERT(op_ == Token::ADD);
1352   GenerateStringAddCode(masm);
1353   // Try to add arguments as strings, otherwise, transition to the generic
1354   // BinaryOpIC type.
1355   GenerateTypeTransition(masm);
1356 }
1357
1358
1359 void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
1360   Label call_runtime;
1361   ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING);
1362   ASSERT(op_ == Token::ADD);
1363   // If both arguments are strings, call the string add stub.
1364   // Otherwise, do a transition.
1365
1366   // Registers containing left and right operands respectively.
1367   Register left = rdx;
1368   Register right = rax;
1369
1370   // Test if left operand is a string.
1371   __ JumpIfSmi(left, &call_runtime);
1372   __ CmpObjectType(left, FIRST_NONSTRING_TYPE, rcx);
1373   __ j(above_equal, &call_runtime);
1374
1375   // Test if right operand is a string.
1376   __ JumpIfSmi(right, &call_runtime);
1377   __ CmpObjectType(right, FIRST_NONSTRING_TYPE, rcx);
1378   __ j(above_equal, &call_runtime);
1379
1380   StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB);
1381   GenerateRegisterArgsPush(masm);
1382   __ TailCallStub(&string_add_stub);
1383
1384   __ bind(&call_runtime);
1385   GenerateTypeTransition(masm);
1386 }
1387
1388
1389 void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
1390   Label call_runtime;
1391
1392   if (op_ == Token::ADD) {
1393     // Handle string addition here, because it is the only operation
1394     // that does not do a ToNumber conversion on the operands.
1395     GenerateStringAddCode(masm);
1396   }
1397
1398   // Convert oddball arguments to numbers.
1399   Label check, done;
1400   __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
1401   __ j(not_equal, &check, Label::kNear);
1402   if (Token::IsBitOp(op_)) {
1403     __ xor_(rdx, rdx);
1404   } else {
1405     __ LoadRoot(rdx, Heap::kNanValueRootIndex);
1406   }
1407   __ jmp(&done, Label::kNear);
1408   __ bind(&check);
1409   __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
1410   __ j(not_equal, &done, Label::kNear);
1411   if (Token::IsBitOp(op_)) {
1412     __ xor_(rax, rax);
1413   } else {
1414     __ LoadRoot(rax, Heap::kNanValueRootIndex);
1415   }
1416   __ bind(&done);
1417
1418   GenerateHeapNumberStub(masm);
1419 }
1420
1421
1422 void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
1423   Label gc_required, not_number;
1424   GenerateFloatingPointCode(masm, &gc_required, &not_number);
1425
1426   __ bind(&not_number);
1427   GenerateTypeTransition(masm);
1428
1429   __ bind(&gc_required);
1430   GenerateCallRuntimeCode(masm);
1431 }
1432
1433
1434 void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
1435   Label call_runtime, call_string_add_or_runtime;
1436
1437   GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
1438
1439   GenerateFloatingPointCode(masm, &call_runtime, &call_string_add_or_runtime);
1440
1441   __ bind(&call_string_add_or_runtime);
1442   if (op_ == Token::ADD) {
1443     GenerateStringAddCode(masm);
1444   }
1445
1446   __ bind(&call_runtime);
1447   GenerateCallRuntimeCode(masm);
1448 }
1449
1450
1451 void BinaryOpStub::GenerateHeapResultAllocation(MacroAssembler* masm,
1452                                                 Label* alloc_failure) {
1453   Label skip_allocation;
1454   OverwriteMode mode = mode_;
1455   switch (mode) {
1456     case OVERWRITE_LEFT: {
1457       // If the argument in rdx is already an object, we skip the
1458       // allocation of a heap number.
1459       __ JumpIfNotSmi(rdx, &skip_allocation);
1460       // Allocate a heap number for the result. Keep eax and edx intact
1461       // for the possible runtime call.
1462       __ AllocateHeapNumber(rbx, rcx, alloc_failure);
1463       // Now rdx can be overwritten losing one of the arguments as we are
1464       // now done and will not need it any more.
1465       __ movq(rdx, rbx);
1466       __ bind(&skip_allocation);
1467       // Use object in rdx as a result holder
1468       __ movq(rax, rdx);
1469       break;
1470     }
1471     case OVERWRITE_RIGHT:
1472       // If the argument in rax is already an object, we skip the
1473       // allocation of a heap number.
1474       __ JumpIfNotSmi(rax, &skip_allocation);
1475       // Fall through!
1476     case NO_OVERWRITE:
1477       // Allocate a heap number for the result. Keep rax and rdx intact
1478       // for the possible runtime call.
1479       __ AllocateHeapNumber(rbx, rcx, alloc_failure);
1480       // Now rax can be overwritten losing one of the arguments as we are
1481       // now done and will not need it any more.
1482       __ movq(rax, rbx);
1483       __ bind(&skip_allocation);
1484       break;
1485     default: UNREACHABLE();
1486   }
1487 }
1488
1489
1490 void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
1491   __ pop(rcx);
1492   __ push(rdx);
1493   __ push(rax);
1494   __ push(rcx);
1495 }
1496
1497
1498 void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
1499   // TAGGED case:
1500   //   Input:
1501   //     rsp[8]: argument (should be number).
1502   //     rsp[0]: return address.
1503   //   Output:
1504   //     rax: tagged double result.
1505   // UNTAGGED case:
1506   //   Input::
1507   //     rsp[0]: return address.
1508   //     xmm1: untagged double input argument
1509   //   Output:
1510   //     xmm1: untagged double result.
1511
1512   Label runtime_call;
1513   Label runtime_call_clear_stack;
1514   Label skip_cache;
1515   const bool tagged = (argument_type_ == TAGGED);
1516   if (tagged) {
1517     Label input_not_smi, loaded;
1518     // Test that rax is a number.
1519     __ movq(rax, Operand(rsp, kPointerSize));
1520     __ JumpIfNotSmi(rax, &input_not_smi, Label::kNear);
1521     // Input is a smi. Untag and load it onto the FPU stack.
1522     // Then load the bits of the double into rbx.
1523     __ SmiToInteger32(rax, rax);
1524     __ subq(rsp, Immediate(kDoubleSize));
1525     __ cvtlsi2sd(xmm1, rax);
1526     __ movsd(Operand(rsp, 0), xmm1);
1527     __ movq(rbx, xmm1);
1528     __ movq(rdx, xmm1);
1529     __ fld_d(Operand(rsp, 0));
1530     __ addq(rsp, Immediate(kDoubleSize));
1531     __ jmp(&loaded, Label::kNear);
1532
1533     __ bind(&input_not_smi);
1534     // Check if input is a HeapNumber.
1535     __ LoadRoot(rbx, Heap::kHeapNumberMapRootIndex);
1536     __ cmpq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
1537     __ j(not_equal, &runtime_call);
1538     // Input is a HeapNumber. Push it on the FPU stack and load its
1539     // bits into rbx.
1540     __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset));
1541     __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset));
1542     __ movq(rdx, rbx);
1543
1544     __ bind(&loaded);
1545   } else {  // UNTAGGED.
1546     __ movq(rbx, xmm1);
1547     __ movq(rdx, xmm1);
1548   }
1549
1550   // ST[0] == double value, if TAGGED.
1551   // rbx = bits of double value.
1552   // rdx = also bits of double value.
1553   // Compute hash (h is 32 bits, bits are 64 and the shifts are arithmetic):
1554   //   h = h0 = bits ^ (bits >> 32);
1555   //   h ^= h >> 16;
1556   //   h ^= h >> 8;
1557   //   h = h & (cacheSize - 1);
1558   // or h = (h0 ^ (h0 >> 8) ^ (h0 >> 16) ^ (h0 >> 24)) & (cacheSize - 1)
1559   __ sar(rdx, Immediate(32));
1560   __ xorl(rdx, rbx);
1561   __ movl(rcx, rdx);
1562   __ movl(rax, rdx);
1563   __ movl(rdi, rdx);
1564   __ sarl(rdx, Immediate(8));
1565   __ sarl(rcx, Immediate(16));
1566   __ sarl(rax, Immediate(24));
1567   __ xorl(rcx, rdx);
1568   __ xorl(rax, rdi);
1569   __ xorl(rcx, rax);
1570   ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize));
1571   __ andl(rcx, Immediate(TranscendentalCache::SubCache::kCacheSize - 1));
1572
1573   // ST[0] == double value.
1574   // rbx = bits of double value.
1575   // rcx = TranscendentalCache::hash(double value).
1576   ExternalReference cache_array =
1577       ExternalReference::transcendental_cache_array_address(masm->isolate());
1578   __ movq(rax, cache_array);
1579   int cache_array_index =
1580       type_ * sizeof(Isolate::Current()->transcendental_cache()->caches_[0]);
1581   __ movq(rax, Operand(rax, cache_array_index));
1582   // rax points to the cache for the type type_.
1583   // If NULL, the cache hasn't been initialized yet, so go through runtime.
1584   __ testq(rax, rax);
1585   __ j(zero, &runtime_call_clear_stack);  // Only clears stack if TAGGED.
1586 #ifdef DEBUG
1587   // Check that the layout of cache elements match expectations.
1588   {  // NOLINT - doesn't like a single brace on a line.
1589     TranscendentalCache::SubCache::Element test_elem[2];
1590     char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
1591     char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
1592     char* elem_in0  = reinterpret_cast<char*>(&(test_elem[0].in[0]));
1593     char* elem_in1  = reinterpret_cast<char*>(&(test_elem[0].in[1]));
1594     char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
1595     // Two uint_32's and a pointer per element.
1596     CHECK_EQ(16, static_cast<int>(elem2_start - elem_start));
1597     CHECK_EQ(0, static_cast<int>(elem_in0 - elem_start));
1598     CHECK_EQ(kIntSize, static_cast<int>(elem_in1 - elem_start));
1599     CHECK_EQ(2 * kIntSize, static_cast<int>(elem_out - elem_start));
1600   }
1601 #endif
1602   // Find the address of the rcx'th entry in the cache, i.e., &rax[rcx*16].
1603   __ addl(rcx, rcx);
1604   __ lea(rcx, Operand(rax, rcx, times_8, 0));
1605   // Check if cache matches: Double value is stored in uint32_t[2] array.
1606   Label cache_miss;
1607   __ cmpq(rbx, Operand(rcx, 0));
1608   __ j(not_equal, &cache_miss, Label::kNear);
1609   // Cache hit!
1610   Counters* counters = masm->isolate()->counters();
1611   __ IncrementCounter(counters->transcendental_cache_hit(), 1);
1612   __ movq(rax, Operand(rcx, 2 * kIntSize));
1613   if (tagged) {
1614     __ fstp(0);  // Clear FPU stack.
1615     __ ret(kPointerSize);
1616   } else {  // UNTAGGED.
1617     __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
1618     __ Ret();
1619   }
1620
1621   __ bind(&cache_miss);
1622   __ IncrementCounter(counters->transcendental_cache_miss(), 1);
1623   // Update cache with new value.
1624   if (tagged) {
1625   __ AllocateHeapNumber(rax, rdi, &runtime_call_clear_stack);
1626   } else {  // UNTAGGED.
1627     __ AllocateHeapNumber(rax, rdi, &skip_cache);
1628     __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm1);
1629     __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset));
1630   }
1631   GenerateOperation(masm, type_);
1632   __ movq(Operand(rcx, 0), rbx);
1633   __ movq(Operand(rcx, 2 * kIntSize), rax);
1634   __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
1635   if (tagged) {
1636     __ ret(kPointerSize);
1637   } else {  // UNTAGGED.
1638     __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
1639     __ Ret();
1640
1641     // Skip cache and return answer directly, only in untagged case.
1642     __ bind(&skip_cache);
1643     __ subq(rsp, Immediate(kDoubleSize));
1644     __ movsd(Operand(rsp, 0), xmm1);
1645     __ fld_d(Operand(rsp, 0));
1646     GenerateOperation(masm, type_);
1647     __ fstp_d(Operand(rsp, 0));
1648     __ movsd(xmm1, Operand(rsp, 0));
1649     __ addq(rsp, Immediate(kDoubleSize));
1650     // We return the value in xmm1 without adding it to the cache, but
1651     // we cause a scavenging GC so that future allocations will succeed.
1652     {
1653       FrameScope scope(masm, StackFrame::INTERNAL);
1654       // Allocate an unused object bigger than a HeapNumber.
1655       __ Push(Smi::FromInt(2 * kDoubleSize));
1656       __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace);
1657     }
1658     __ Ret();
1659   }
1660
1661   // Call runtime, doing whatever allocation and cleanup is necessary.
1662   if (tagged) {
1663     __ bind(&runtime_call_clear_stack);
1664     __ fstp(0);
1665     __ bind(&runtime_call);
1666     __ TailCallExternalReference(
1667         ExternalReference(RuntimeFunction(), masm->isolate()), 1, 1);
1668   } else {  // UNTAGGED.
1669     __ bind(&runtime_call_clear_stack);
1670     __ bind(&runtime_call);
1671     __ AllocateHeapNumber(rax, rdi, &skip_cache);
1672     __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm1);
1673     {
1674       FrameScope scope(masm, StackFrame::INTERNAL);
1675       __ push(rax);
1676       __ CallRuntime(RuntimeFunction(), 1);
1677     }
1678     __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
1679     __ Ret();
1680   }
1681 }
1682
1683
1684 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
1685   switch (type_) {
1686     // Add more cases when necessary.
1687     case TranscendentalCache::SIN: return Runtime::kMath_sin;
1688     case TranscendentalCache::COS: return Runtime::kMath_cos;
1689     case TranscendentalCache::TAN: return Runtime::kMath_tan;
1690     case TranscendentalCache::LOG: return Runtime::kMath_log;
1691     default:
1692       UNIMPLEMENTED();
1693       return Runtime::kAbort;
1694   }
1695 }
1696
1697
1698 void TranscendentalCacheStub::GenerateOperation(
1699     MacroAssembler* masm, TranscendentalCache::Type type) {
1700   // Registers:
1701   // rax: Newly allocated HeapNumber, which must be preserved.
1702   // rbx: Bits of input double. Must be preserved.
1703   // rcx: Pointer to cache entry. Must be preserved.
1704   // st(0): Input double
1705   Label done;
1706   if (type == TranscendentalCache::SIN ||
1707       type == TranscendentalCache::COS ||
1708       type == TranscendentalCache::TAN) {
1709     // Both fsin and fcos require arguments in the range +/-2^63 and
1710     // return NaN for infinities and NaN. They can share all code except
1711     // the actual fsin/fcos operation.
1712     Label in_range;
1713     // If argument is outside the range -2^63..2^63, fsin/cos doesn't
1714     // work. We must reduce it to the appropriate range.
1715     __ movq(rdi, rbx);
1716     // Move exponent and sign bits to low bits.
1717     __ shr(rdi, Immediate(HeapNumber::kMantissaBits));
1718     // Remove sign bit.
1719     __ andl(rdi, Immediate((1 << HeapNumber::kExponentBits) - 1));
1720     int supported_exponent_limit = (63 + HeapNumber::kExponentBias);
1721     __ cmpl(rdi, Immediate(supported_exponent_limit));
1722     __ j(below, &in_range);
1723     // Check for infinity and NaN. Both return NaN for sin.
1724     __ cmpl(rdi, Immediate(0x7ff));
1725     Label non_nan_result;
1726     __ j(not_equal, &non_nan_result, Label::kNear);
1727     // Input is +/-Infinity or NaN. Result is NaN.
1728     __ fstp(0);
1729     // NaN is represented by 0x7ff8000000000000.
1730     __ subq(rsp, Immediate(kPointerSize));
1731     __ movl(Operand(rsp, 4), Immediate(0x7ff80000));
1732     __ movl(Operand(rsp, 0), Immediate(0x00000000));
1733     __ fld_d(Operand(rsp, 0));
1734     __ addq(rsp, Immediate(kPointerSize));
1735     __ jmp(&done);
1736
1737     __ bind(&non_nan_result);
1738
1739     // Use fpmod to restrict argument to the range +/-2*PI.
1740     __ movq(rdi, rax);  // Save rax before using fnstsw_ax.
1741     __ fldpi();
1742     __ fadd(0);
1743     __ fld(1);
1744     // FPU Stack: input, 2*pi, input.
1745     {
1746       Label no_exceptions;
1747       __ fwait();
1748       __ fnstsw_ax();
1749       // Clear if Illegal Operand or Zero Division exceptions are set.
1750       __ testl(rax, Immediate(5));  // #IO and #ZD flags of FPU status word.
1751       __ j(zero, &no_exceptions);
1752       __ fnclex();
1753       __ bind(&no_exceptions);
1754     }
1755
1756     // Compute st(0) % st(1)
1757     {
1758       Label partial_remainder_loop;
1759       __ bind(&partial_remainder_loop);
1760       __ fprem1();
1761       __ fwait();
1762       __ fnstsw_ax();
1763       __ testl(rax, Immediate(0x400));  // Check C2 bit of FPU status word.
1764       // If C2 is set, computation only has partial result. Loop to
1765       // continue computation.
1766       __ j(not_zero, &partial_remainder_loop);
1767   }
1768     // FPU Stack: input, 2*pi, input % 2*pi
1769     __ fstp(2);
1770     // FPU Stack: input % 2*pi, 2*pi,
1771     __ fstp(0);
1772     // FPU Stack: input % 2*pi
1773     __ movq(rax, rdi);  // Restore rax, pointer to the new HeapNumber.
1774     __ bind(&in_range);
1775     switch (type) {
1776       case TranscendentalCache::SIN:
1777         __ fsin();
1778         break;
1779       case TranscendentalCache::COS:
1780         __ fcos();
1781         break;
1782       case TranscendentalCache::TAN:
1783         // FPTAN calculates tangent onto st(0) and pushes 1.0 onto the
1784         // FP register stack.
1785         __ fptan();
1786         __ fstp(0);  // Pop FP register stack.
1787         break;
1788       default:
1789         UNREACHABLE();
1790     }
1791     __ bind(&done);
1792   } else {
1793     ASSERT(type == TranscendentalCache::LOG);
1794     __ fldln2();
1795     __ fxch();
1796     __ fyl2x();
1797   }
1798 }
1799
1800
1801 // Input: rdx, rax are the left and right objects of a bit op.
1802 // Output: rax, rcx are left and right integers for a bit op.
1803 void FloatingPointHelper::LoadNumbersAsIntegers(MacroAssembler* masm) {
1804   // Check float operands.
1805   Label done;
1806   Label rax_is_smi;
1807   Label rax_is_object;
1808   Label rdx_is_object;
1809
1810   __ JumpIfNotSmi(rdx, &rdx_is_object);
1811   __ SmiToInteger32(rdx, rdx);
1812   __ JumpIfSmi(rax, &rax_is_smi);
1813
1814   __ bind(&rax_is_object);
1815   IntegerConvert(masm, rcx, rax);  // Uses rdi, rcx and rbx.
1816   __ jmp(&done);
1817
1818   __ bind(&rdx_is_object);
1819   IntegerConvert(masm, rdx, rdx);  // Uses rdi, rcx and rbx.
1820   __ JumpIfNotSmi(rax, &rax_is_object);
1821   __ bind(&rax_is_smi);
1822   __ SmiToInteger32(rcx, rax);
1823
1824   __ bind(&done);
1825   __ movl(rax, rdx);
1826 }
1827
1828
1829 // Input: rdx, rax are the left and right objects of a bit op.
1830 // Output: rax, rcx are left and right integers for a bit op.
1831 // Jump to conversion_failure: rdx and rax are unchanged.
1832 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
1833                                          Label* conversion_failure,
1834                                          Register heap_number_map) {
1835   // Check float operands.
1836   Label arg1_is_object, check_undefined_arg1;
1837   Label arg2_is_object, check_undefined_arg2;
1838   Label load_arg2, done;
1839
1840   __ JumpIfNotSmi(rdx, &arg1_is_object);
1841   __ SmiToInteger32(r8, rdx);
1842   __ jmp(&load_arg2);
1843
1844   // If the argument is undefined it converts to zero (ECMA-262, section 9.5).
1845   __ bind(&check_undefined_arg1);
1846   __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
1847   __ j(not_equal, conversion_failure);
1848   __ Set(r8, 0);
1849   __ jmp(&load_arg2);
1850
1851   __ bind(&arg1_is_object);
1852   __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), heap_number_map);
1853   __ j(not_equal, &check_undefined_arg1);
1854   // Get the untagged integer version of the rdx heap number in rcx.
1855   IntegerConvert(masm, r8, rdx);
1856
1857   // Here r8 has the untagged integer, rax has a Smi or a heap number.
1858   __ bind(&load_arg2);
1859   // Test if arg2 is a Smi.
1860   __ JumpIfNotSmi(rax, &arg2_is_object);
1861   __ SmiToInteger32(rcx, rax);
1862   __ jmp(&done);
1863
1864   // If the argument is undefined it converts to zero (ECMA-262, section 9.5).
1865   __ bind(&check_undefined_arg2);
1866   __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
1867   __ j(not_equal, conversion_failure);
1868   __ Set(rcx, 0);
1869   __ jmp(&done);
1870
1871   __ bind(&arg2_is_object);
1872   __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map);
1873   __ j(not_equal, &check_undefined_arg2);
1874   // Get the untagged integer version of the rax heap number in rcx.
1875   IntegerConvert(masm, rcx, rax);
1876   __ bind(&done);
1877   __ movl(rax, r8);
1878 }
1879
1880
1881 void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) {
1882   __ SmiToInteger32(kScratchRegister, rdx);
1883   __ cvtlsi2sd(xmm0, kScratchRegister);
1884   __ SmiToInteger32(kScratchRegister, rax);
1885   __ cvtlsi2sd(xmm1, kScratchRegister);
1886 }
1887
1888
1889 void FloatingPointHelper::LoadSSE2NumberOperands(MacroAssembler* masm) {
1890   Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, done;
1891   // Load operand in rdx into xmm0.
1892   __ JumpIfSmi(rdx, &load_smi_rdx);
1893   __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
1894   // Load operand in rax into xmm1.
1895   __ JumpIfSmi(rax, &load_smi_rax);
1896   __ bind(&load_nonsmi_rax);
1897   __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
1898   __ jmp(&done);
1899
1900   __ bind(&load_smi_rdx);
1901   __ SmiToInteger32(kScratchRegister, rdx);
1902   __ cvtlsi2sd(xmm0, kScratchRegister);
1903   __ JumpIfNotSmi(rax, &load_nonsmi_rax);
1904
1905   __ bind(&load_smi_rax);
1906   __ SmiToInteger32(kScratchRegister, rax);
1907   __ cvtlsi2sd(xmm1, kScratchRegister);
1908
1909   __ bind(&done);
1910 }
1911
1912
1913 void FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm,
1914                                                   Label* not_numbers) {
1915   Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, load_float_rax, done;
1916   // Load operand in rdx into xmm0, or branch to not_numbers.
1917   __ LoadRoot(rcx, Heap::kHeapNumberMapRootIndex);
1918   __ JumpIfSmi(rdx, &load_smi_rdx);
1919   __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), rcx);
1920   __ j(not_equal, not_numbers);  // Argument in rdx is not a number.
1921   __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
1922   // Load operand in rax into xmm1, or branch to not_numbers.
1923   __ JumpIfSmi(rax, &load_smi_rax);
1924
1925   __ bind(&load_nonsmi_rax);
1926   __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), rcx);
1927   __ j(not_equal, not_numbers);
1928   __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
1929   __ jmp(&done);
1930
1931   __ bind(&load_smi_rdx);
1932   __ SmiToInteger32(kScratchRegister, rdx);
1933   __ cvtlsi2sd(xmm0, kScratchRegister);
1934   __ JumpIfNotSmi(rax, &load_nonsmi_rax);
1935
1936   __ bind(&load_smi_rax);
1937   __ SmiToInteger32(kScratchRegister, rax);
1938   __ cvtlsi2sd(xmm1, kScratchRegister);
1939   __ bind(&done);
1940 }
1941
1942
1943 void FloatingPointHelper::NumbersToSmis(MacroAssembler* masm,
1944                                         Register first,
1945                                         Register second,
1946                                         Register scratch1,
1947                                         Register scratch2,
1948                                         Register scratch3,
1949                                         Label* on_success,
1950                                         Label* on_not_smis)   {
1951   Register heap_number_map = scratch3;
1952   Register smi_result = scratch1;
1953   Label done;
1954
1955   __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
1956
1957   Label first_smi;
1958   __ JumpIfSmi(first, &first_smi, Label::kNear);
1959   __ cmpq(FieldOperand(first, HeapObject::kMapOffset), heap_number_map);
1960   __ j(not_equal, on_not_smis);
1961   // Convert HeapNumber to smi if possible.
1962   __ movsd(xmm0, FieldOperand(first, HeapNumber::kValueOffset));
1963   __ movq(scratch2, xmm0);
1964   __ cvttsd2siq(smi_result, xmm0);
1965   // Check if conversion was successful by converting back and
1966   // comparing to the original double's bits.
1967   __ cvtlsi2sd(xmm1, smi_result);
1968   __ movq(kScratchRegister, xmm1);
1969   __ cmpq(scratch2, kScratchRegister);
1970   __ j(not_equal, on_not_smis);
1971   __ Integer32ToSmi(first, smi_result);
1972
1973   __ JumpIfSmi(second, (on_success != NULL) ? on_success : &done);
1974   __ bind(&first_smi);
1975   if (FLAG_debug_code) {
1976     // Second should be non-smi if we get here.
1977     __ AbortIfSmi(second);
1978   }
1979   __ cmpq(FieldOperand(second, HeapObject::kMapOffset), heap_number_map);
1980   __ j(not_equal, on_not_smis);
1981   // Convert second to smi, if possible.
1982   __ movsd(xmm0, FieldOperand(second, HeapNumber::kValueOffset));
1983   __ movq(scratch2, xmm0);
1984   __ cvttsd2siq(smi_result, xmm0);
1985   __ cvtlsi2sd(xmm1, smi_result);
1986   __ movq(kScratchRegister, xmm1);
1987   __ cmpq(scratch2, kScratchRegister);
1988   __ j(not_equal, on_not_smis);
1989   __ Integer32ToSmi(second, smi_result);
1990   if (on_success != NULL) {
1991     __ jmp(on_success);
1992   } else {
1993     __ bind(&done);
1994   }
1995 }
1996
1997
1998 void MathPowStub::Generate(MacroAssembler* masm) {
1999   // Choose register conforming to calling convention (when bailing out).
2000 #ifdef _WIN64
2001   const Register exponent = rdx;
2002 #else
2003   const Register exponent = rdi;
2004 #endif
2005   const Register base = rax;
2006   const Register scratch = rcx;
2007   const XMMRegister double_result = xmm3;
2008   const XMMRegister double_base = xmm2;
2009   const XMMRegister double_exponent = xmm1;
2010   const XMMRegister double_scratch = xmm4;
2011
2012   Label call_runtime, done, exponent_not_smi, int_exponent;
2013
2014   // Save 1 in double_result - we need this several times later on.
2015   __ movq(scratch, Immediate(1));
2016   __ cvtlsi2sd(double_result, scratch);
2017
2018   if (exponent_type_ == ON_STACK) {
2019     Label base_is_smi, unpack_exponent;
2020     // The exponent and base are supplied as arguments on the stack.
2021     // This can only happen if the stub is called from non-optimized code.
2022     // Load input parameters from stack.
2023     __ movq(base, Operand(rsp, 2 * kPointerSize));
2024     __ movq(exponent, Operand(rsp, 1 * kPointerSize));
2025     __ JumpIfSmi(base, &base_is_smi, Label::kNear);
2026     __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset),
2027                    Heap::kHeapNumberMapRootIndex);
2028     __ j(not_equal, &call_runtime);
2029
2030     __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset));
2031     __ jmp(&unpack_exponent, Label::kNear);
2032
2033     __ bind(&base_is_smi);
2034     __ SmiToInteger32(base, base);
2035     __ cvtlsi2sd(double_base, base);
2036     __ bind(&unpack_exponent);
2037
2038     __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
2039     __ SmiToInteger32(exponent, exponent);
2040     __ jmp(&int_exponent);
2041
2042     __ bind(&exponent_not_smi);
2043     __ CompareRoot(FieldOperand(exponent, HeapObject::kMapOffset),
2044                    Heap::kHeapNumberMapRootIndex);
2045     __ j(not_equal, &call_runtime);
2046     __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset));
2047   } else if (exponent_type_ == TAGGED) {
2048     __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
2049     __ SmiToInteger32(exponent, exponent);
2050     __ jmp(&int_exponent);
2051
2052     __ bind(&exponent_not_smi);
2053     __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset));
2054   }
2055
2056   if (exponent_type_ != INTEGER) {
2057     Label fast_power;
2058     // Detect integer exponents stored as double.
2059     __ cvttsd2si(exponent, double_exponent);
2060     // Skip to runtime if possibly NaN (indicated by the indefinite integer).
2061     __ cmpl(exponent, Immediate(0x80000000u));
2062     __ j(equal, &call_runtime);
2063     __ cvtlsi2sd(double_scratch, exponent);
2064     // Already ruled out NaNs for exponent.
2065     __ ucomisd(double_exponent, double_scratch);
2066     __ j(equal, &int_exponent);
2067
2068     if (exponent_type_ == ON_STACK) {
2069       // Detect square root case.  Crankshaft detects constant +/-0.5 at
2070       // compile time and uses DoMathPowHalf instead.  We then skip this check
2071       // for non-constant cases of +/-0.5 as these hardly occur.
2072       Label continue_sqrt, continue_rsqrt, not_plus_half;
2073       // Test for 0.5.
2074       // Load double_scratch with 0.5.
2075       __ movq(scratch, V8_UINT64_C(0x3FE0000000000000), RelocInfo::NONE);
2076       __ movq(double_scratch, scratch);
2077       // Already ruled out NaNs for exponent.
2078       __ ucomisd(double_scratch, double_exponent);
2079       __ j(not_equal, &not_plus_half, Label::kNear);
2080
2081       // Calculates square root of base.  Check for the special case of
2082       // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13).
2083       // According to IEEE-754, double-precision -Infinity has the highest
2084       // 12 bits set and the lowest 52 bits cleared.
2085       __ movq(scratch, V8_UINT64_C(0xFFF0000000000000), RelocInfo::NONE);
2086       __ movq(double_scratch, scratch);
2087       __ ucomisd(double_scratch, double_base);
2088       // Comparing -Infinity with NaN results in "unordered", which sets the
2089       // zero flag as if both were equal.  However, it also sets the carry flag.
2090       __ j(not_equal, &continue_sqrt, Label::kNear);
2091       __ j(carry, &continue_sqrt, Label::kNear);
2092
2093       // Set result to Infinity in the special case.
2094       __ xorps(double_result, double_result);
2095       __ subsd(double_result, double_scratch);
2096       __ jmp(&done);
2097
2098       __ bind(&continue_sqrt);
2099       // sqrtsd returns -0 when input is -0.  ECMA spec requires +0.
2100       __ xorps(double_scratch, double_scratch);
2101       __ addsd(double_scratch, double_base);  // Convert -0 to 0.
2102       __ sqrtsd(double_result, double_scratch);
2103       __ jmp(&done);
2104
2105       // Test for -0.5.
2106       __ bind(&not_plus_half);
2107       // Load double_scratch with -0.5 by substracting 1.
2108       __ subsd(double_scratch, double_result);
2109       // Already ruled out NaNs for exponent.
2110       __ ucomisd(double_scratch, double_exponent);
2111       __ j(not_equal, &fast_power, Label::kNear);
2112
2113       // Calculates reciprocal of square root of base.  Check for the special
2114       // case of Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13).
2115       // According to IEEE-754, double-precision -Infinity has the highest
2116       // 12 bits set and the lowest 52 bits cleared.
2117       __ movq(scratch, V8_UINT64_C(0xFFF0000000000000), RelocInfo::NONE);
2118       __ movq(double_scratch, scratch);
2119       __ ucomisd(double_scratch, double_base);
2120       // Comparing -Infinity with NaN results in "unordered", which sets the
2121       // zero flag as if both were equal.  However, it also sets the carry flag.
2122       __ j(not_equal, &continue_rsqrt, Label::kNear);
2123       __ j(carry, &continue_rsqrt, Label::kNear);
2124
2125       // Set result to 0 in the special case.
2126       __ xorps(double_result, double_result);
2127       __ jmp(&done);
2128
2129       __ bind(&continue_rsqrt);
2130       // sqrtsd returns -0 when input is -0.  ECMA spec requires +0.
2131       __ xorps(double_exponent, double_exponent);
2132       __ addsd(double_exponent, double_base);  // Convert -0 to +0.
2133       __ sqrtsd(double_exponent, double_exponent);
2134       __ divsd(double_result, double_exponent);
2135       __ jmp(&done);
2136     }
2137
2138     // Using FPU instructions to calculate power.
2139     Label fast_power_failed;
2140     __ bind(&fast_power);
2141     __ fnclex();  // Clear flags to catch exceptions later.
2142     // Transfer (B)ase and (E)xponent onto the FPU register stack.
2143     __ subq(rsp, Immediate(kDoubleSize));
2144     __ movsd(Operand(rsp, 0), double_exponent);
2145     __ fld_d(Operand(rsp, 0));  // E
2146     __ movsd(Operand(rsp, 0), double_base);
2147     __ fld_d(Operand(rsp, 0));  // B, E
2148
2149     // Exponent is in st(1) and base is in st(0)
2150     // B ^ E = (2^(E * log2(B)) - 1) + 1 = (2^X - 1) + 1 for X = E * log2(B)
2151     // FYL2X calculates st(1) * log2(st(0))
2152     __ fyl2x();    // X
2153     __ fld(0);     // X, X
2154     __ frndint();  // rnd(X), X
2155     __ fsub(1);    // rnd(X), X-rnd(X)
2156     __ fxch(1);    // X - rnd(X), rnd(X)
2157     // F2XM1 calculates 2^st(0) - 1 for -1 < st(0) < 1
2158     __ f2xm1();    // 2^(X-rnd(X)) - 1, rnd(X)
2159     __ fld1();     // 1, 2^(X-rnd(X)) - 1, rnd(X)
2160     __ faddp(1);   // 1, 2^(X-rnd(X)), rnd(X)
2161     // FSCALE calculates st(0) * 2^st(1)
2162     __ fscale();   // 2^X, rnd(X)
2163     __ fstp(1);
2164     // Bail out to runtime in case of exceptions in the status word.
2165     __ fnstsw_ax();
2166     __ testb(rax, Immediate(0x5F));  // Check for all but precision exception.
2167     __ j(not_zero, &fast_power_failed, Label::kNear);
2168     __ fstp_d(Operand(rsp, 0));
2169     __ movsd(double_result, Operand(rsp, 0));
2170     __ addq(rsp, Immediate(kDoubleSize));
2171     __ jmp(&done);
2172
2173     __ bind(&fast_power_failed);
2174     __ fninit();
2175     __ addq(rsp, Immediate(kDoubleSize));
2176     __ jmp(&call_runtime);
2177   }
2178
2179   // Calculate power with integer exponent.
2180   __ bind(&int_exponent);
2181   const XMMRegister double_scratch2 = double_exponent;
2182   // Back up exponent as we need to check if exponent is negative later.
2183   __ movq(scratch, exponent);  // Back up exponent.
2184   __ movsd(double_scratch, double_base);  // Back up base.
2185   __ movsd(double_scratch2, double_result);  // Load double_exponent with 1.
2186
2187   // Get absolute value of exponent.
2188   Label no_neg, while_true, no_multiply;
2189   __ testl(scratch, scratch);
2190   __ j(positive, &no_neg, Label::kNear);
2191   __ negl(scratch);
2192   __ bind(&no_neg);
2193
2194   __ bind(&while_true);
2195   __ shrl(scratch, Immediate(1));
2196   __ j(not_carry, &no_multiply, Label::kNear);
2197   __ mulsd(double_result, double_scratch);
2198   __ bind(&no_multiply);
2199
2200   __ mulsd(double_scratch, double_scratch);
2201   __ j(not_zero, &while_true);
2202
2203   // If the exponent is negative, return 1/result.
2204   __ testl(exponent, exponent);
2205   __ j(greater, &done);
2206   __ divsd(double_scratch2, double_result);
2207   __ movsd(double_result, double_scratch2);
2208   // Test whether result is zero.  Bail out to check for subnormal result.
2209   // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
2210   __ xorps(double_scratch2, double_scratch2);
2211   __ ucomisd(double_scratch2, double_result);
2212   // double_exponent aliased as double_scratch2 has already been overwritten
2213   // and may not have contained the exponent value in the first place when the
2214   // input was a smi.  We reset it with exponent value before bailing out.
2215   __ j(not_equal, &done);
2216   __ cvtlsi2sd(double_exponent, exponent);
2217
2218   // Returning or bailing out.
2219   Counters* counters = masm->isolate()->counters();
2220   if (exponent_type_ == ON_STACK) {
2221     // The arguments are still on the stack.
2222     __ bind(&call_runtime);
2223     __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1);
2224
2225     // The stub is called from non-optimized code, which expects the result
2226     // as heap number in eax.
2227     __ bind(&done);
2228     __ AllocateHeapNumber(rax, rcx, &call_runtime);
2229     __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), double_result);
2230     __ IncrementCounter(counters->math_pow(), 1);
2231     __ ret(2 * kPointerSize);
2232   } else {
2233     __ bind(&call_runtime);
2234     // Move base to the correct argument register.  Exponent is already in xmm1.
2235     __ movsd(xmm0, double_base);
2236     ASSERT(double_exponent.is(xmm1));
2237     {
2238       AllowExternalCallThatCantCauseGC scope(masm);
2239       __ PrepareCallCFunction(2);
2240       __ CallCFunction(
2241           ExternalReference::power_double_double_function(masm->isolate()), 2);
2242     }
2243     // Return value is in xmm0.
2244     __ movsd(double_result, xmm0);
2245     // Restore context register.
2246     __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2247
2248     __ bind(&done);
2249     __ IncrementCounter(counters->math_pow(), 1);
2250     __ ret(0);
2251   }
2252 }
2253
2254
2255 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
2256   // The key is in rdx and the parameter count is in rax.
2257
2258   // The displacement is used for skipping the frame pointer on the
2259   // stack. It is the offset of the last parameter (if any) relative
2260   // to the frame pointer.
2261   static const int kDisplacement = 1 * kPointerSize;
2262
2263   // Check that the key is a smi.
2264   Label slow;
2265   __ JumpIfNotSmi(rdx, &slow);
2266
2267   // Check if the calling frame is an arguments adaptor frame.  We look at the
2268   // context offset, and if the frame is not a regular one, then we find a
2269   // Smi instead of the context.  We can't use SmiCompare here, because that
2270   // only works for comparing two smis.
2271   Label adaptor;
2272   __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2273   __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
2274          Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2275   __ j(equal, &adaptor);
2276
2277   // Check index against formal parameters count limit passed in
2278   // through register rax. Use unsigned comparison to get negative
2279   // check for free.
2280   __ cmpq(rdx, rax);
2281   __ j(above_equal, &slow);
2282
2283   // Read the argument from the stack and return it.
2284   SmiIndex index = masm->SmiToIndex(rax, rax, kPointerSizeLog2);
2285   __ lea(rbx, Operand(rbp, index.reg, index.scale, 0));
2286   index = masm->SmiToNegativeIndex(rdx, rdx, kPointerSizeLog2);
2287   __ movq(rax, Operand(rbx, index.reg, index.scale, kDisplacement));
2288   __ Ret();
2289
2290   // Arguments adaptor case: Check index against actual arguments
2291   // limit found in the arguments adaptor frame. Use unsigned
2292   // comparison to get negative check for free.
2293   __ bind(&adaptor);
2294   __ movq(rcx, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2295   __ cmpq(rdx, rcx);
2296   __ j(above_equal, &slow);
2297
2298   // Read the argument from the stack and return it.
2299   index = masm->SmiToIndex(rax, rcx, kPointerSizeLog2);
2300   __ lea(rbx, Operand(rbx, index.reg, index.scale, 0));
2301   index = masm->SmiToNegativeIndex(rdx, rdx, kPointerSizeLog2);
2302   __ movq(rax, Operand(rbx, index.reg, index.scale, kDisplacement));
2303   __ Ret();
2304
2305   // Slow-case: Handle non-smi or out-of-bounds access to arguments
2306   // by calling the runtime system.
2307   __ bind(&slow);
2308   __ pop(rbx);  // Return address.
2309   __ push(rdx);
2310   __ push(rbx);
2311   __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
2312 }
2313
2314
2315 void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
2316   // Stack layout:
2317   //  rsp[0] : return address
2318   //  rsp[8] : number of parameters (tagged)
2319   //  rsp[16] : receiver displacement
2320   //  rsp[24] : function
2321   // Registers used over the whole function:
2322   //  rbx: the mapped parameter count (untagged)
2323   //  rax: the allocated object (tagged).
2324
2325   Factory* factory = masm->isolate()->factory();
2326
2327   __ SmiToInteger64(rbx, Operand(rsp, 1 * kPointerSize));
2328   // rbx = parameter count (untagged)
2329
2330   // Check if the calling frame is an arguments adaptor frame.
2331   Label runtime;
2332   Label adaptor_frame, try_allocate;
2333   __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2334   __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
2335   __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2336   __ j(equal, &adaptor_frame);
2337
2338   // No adaptor, parameter count = argument count.
2339   __ movq(rcx, rbx);
2340   __ jmp(&try_allocate, Label::kNear);
2341
2342   // We have an adaptor frame. Patch the parameters pointer.
2343   __ bind(&adaptor_frame);
2344   __ SmiToInteger64(rcx,
2345                     Operand(rdx,
2346                             ArgumentsAdaptorFrameConstants::kLengthOffset));
2347   __ lea(rdx, Operand(rdx, rcx, times_pointer_size,
2348                       StandardFrameConstants::kCallerSPOffset));
2349   __ movq(Operand(rsp, 2 * kPointerSize), rdx);
2350
2351   // rbx = parameter count (untagged)
2352   // rcx = argument count (untagged)
2353   // Compute the mapped parameter count = min(rbx, rcx) in rbx.
2354   __ cmpq(rbx, rcx);
2355   __ j(less_equal, &try_allocate, Label::kNear);
2356   __ movq(rbx, rcx);
2357
2358   __ bind(&try_allocate);
2359
2360   // Compute the sizes of backing store, parameter map, and arguments object.
2361   // 1. Parameter map, has 2 extra words containing context and backing store.
2362   const int kParameterMapHeaderSize =
2363       FixedArray::kHeaderSize + 2 * kPointerSize;
2364   Label no_parameter_map;
2365   __ xor_(r8, r8);
2366   __ testq(rbx, rbx);
2367   __ j(zero, &no_parameter_map, Label::kNear);
2368   __ lea(r8, Operand(rbx, times_pointer_size, kParameterMapHeaderSize));
2369   __ bind(&no_parameter_map);
2370
2371   // 2. Backing store.
2372   __ lea(r8, Operand(r8, rcx, times_pointer_size, FixedArray::kHeaderSize));
2373
2374   // 3. Arguments object.
2375   __ addq(r8, Immediate(Heap::kArgumentsObjectSize));
2376
2377   // Do the allocation of all three objects in one go.
2378   __ AllocateInNewSpace(r8, rax, rdx, rdi, &runtime, TAG_OBJECT);
2379
2380   // rax = address of new object(s) (tagged)
2381   // rcx = argument count (untagged)
2382   // Get the arguments boilerplate from the current (global) context into rdi.
2383   Label has_mapped_parameters, copy;
2384   __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
2385   __ movq(rdi, FieldOperand(rdi, GlobalObject::kGlobalContextOffset));
2386   __ testq(rbx, rbx);
2387   __ j(not_zero, &has_mapped_parameters, Label::kNear);
2388
2389   const int kIndex = Context::ARGUMENTS_BOILERPLATE_INDEX;
2390   __ movq(rdi, Operand(rdi, Context::SlotOffset(kIndex)));
2391   __ jmp(&copy, Label::kNear);
2392
2393   const int kAliasedIndex = Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX;
2394   __ bind(&has_mapped_parameters);
2395   __ movq(rdi, Operand(rdi, Context::SlotOffset(kAliasedIndex)));
2396   __ bind(&copy);
2397
2398   // rax = address of new object (tagged)
2399   // rbx = mapped parameter count (untagged)
2400   // rcx = argument count (untagged)
2401   // rdi = address of boilerplate object (tagged)
2402   // Copy the JS object part.
2403   for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
2404     __ movq(rdx, FieldOperand(rdi, i));
2405     __ movq(FieldOperand(rax, i), rdx);
2406   }
2407
2408   // Set up the callee in-object property.
2409   STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
2410   __ movq(rdx, Operand(rsp, 3 * kPointerSize));
2411   __ movq(FieldOperand(rax, JSObject::kHeaderSize +
2412                        Heap::kArgumentsCalleeIndex * kPointerSize),
2413           rdx);
2414
2415   // Use the length (smi tagged) and set that as an in-object property too.
2416   // Note: rcx is tagged from here on.
2417   STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
2418   __ Integer32ToSmi(rcx, rcx);
2419   __ movq(FieldOperand(rax, JSObject::kHeaderSize +
2420                        Heap::kArgumentsLengthIndex * kPointerSize),
2421           rcx);
2422
2423   // Set up the elements pointer in the allocated arguments object.
2424   // If we allocated a parameter map, edi will point there, otherwise to the
2425   // backing store.
2426   __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSize));
2427   __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi);
2428
2429   // rax = address of new object (tagged)
2430   // rbx = mapped parameter count (untagged)
2431   // rcx = argument count (tagged)
2432   // rdi = address of parameter map or backing store (tagged)
2433
2434   // Initialize parameter map. If there are no mapped arguments, we're done.
2435   Label skip_parameter_map;
2436   __ testq(rbx, rbx);
2437   __ j(zero, &skip_parameter_map);
2438
2439   __ LoadRoot(kScratchRegister, Heap::kNonStrictArgumentsElementsMapRootIndex);
2440   // rbx contains the untagged argument count. Add 2 and tag to write.
2441   __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister);
2442   __ Integer64PlusConstantToSmi(r9, rbx, 2);
2443   __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), r9);
2444   __ movq(FieldOperand(rdi, FixedArray::kHeaderSize + 0 * kPointerSize), rsi);
2445   __ lea(r9, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize));
2446   __ movq(FieldOperand(rdi, FixedArray::kHeaderSize + 1 * kPointerSize), r9);
2447
2448   // Copy the parameter slots and the holes in the arguments.
2449   // We need to fill in mapped_parameter_count slots. They index the context,
2450   // where parameters are stored in reverse order, at
2451   //   MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
2452   // The mapped parameter thus need to get indices
2453   //   MIN_CONTEXT_SLOTS+parameter_count-1 ..
2454   //       MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
2455   // We loop from right to left.
2456   Label parameters_loop, parameters_test;
2457
2458   // Load tagged parameter count into r9.
2459   __ Integer32ToSmi(r9, rbx);
2460   __ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS));
2461   __ addq(r8, Operand(rsp, 1 * kPointerSize));
2462   __ subq(r8, r9);
2463   __ Move(r11, factory->the_hole_value());
2464   __ movq(rdx, rdi);
2465   __ lea(rdi, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize));
2466   // r9 = loop variable (tagged)
2467   // r8 = mapping index (tagged)
2468   // r11 = the hole value
2469   // rdx = address of parameter map (tagged)
2470   // rdi = address of backing store (tagged)
2471   __ jmp(&parameters_test, Label::kNear);
2472
2473   __ bind(&parameters_loop);
2474   __ SmiSubConstant(r9, r9, Smi::FromInt(1));
2475   __ SmiToInteger64(kScratchRegister, r9);
2476   __ movq(FieldOperand(rdx, kScratchRegister,
2477                        times_pointer_size,
2478                        kParameterMapHeaderSize),
2479           r8);
2480   __ movq(FieldOperand(rdi, kScratchRegister,
2481                        times_pointer_size,
2482                        FixedArray::kHeaderSize),
2483           r11);
2484   __ SmiAddConstant(r8, r8, Smi::FromInt(1));
2485   __ bind(&parameters_test);
2486   __ SmiTest(r9);
2487   __ j(not_zero, &parameters_loop, Label::kNear);
2488
2489   __ bind(&skip_parameter_map);
2490
2491   // rcx = argument count (tagged)
2492   // rdi = address of backing store (tagged)
2493   // Copy arguments header and remaining slots (if there are any).
2494   __ Move(FieldOperand(rdi, FixedArray::kMapOffset),
2495           factory->fixed_array_map());
2496   __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx);
2497
2498   Label arguments_loop, arguments_test;
2499   __ movq(r8, rbx);
2500   __ movq(rdx, Operand(rsp, 2 * kPointerSize));
2501   // Untag rcx for the loop below.
2502   __ SmiToInteger64(rcx, rcx);
2503   __ lea(kScratchRegister, Operand(r8, times_pointer_size, 0));
2504   __ subq(rdx, kScratchRegister);
2505   __ jmp(&arguments_test, Label::kNear);
2506
2507   __ bind(&arguments_loop);
2508   __ subq(rdx, Immediate(kPointerSize));
2509   __ movq(r9, Operand(rdx, 0));
2510   __ movq(FieldOperand(rdi, r8,
2511                        times_pointer_size,
2512                        FixedArray::kHeaderSize),
2513           r9);
2514   __ addq(r8, Immediate(1));
2515
2516   __ bind(&arguments_test);
2517   __ cmpq(r8, rcx);
2518   __ j(less, &arguments_loop, Label::kNear);
2519
2520   // Return and remove the on-stack parameters.
2521   __ ret(3 * kPointerSize);
2522
2523   // Do the runtime call to allocate the arguments object.
2524   // rcx = argument count (untagged)
2525   __ bind(&runtime);
2526   __ Integer32ToSmi(rcx, rcx);
2527   __ movq(Operand(rsp, 1 * kPointerSize), rcx);  // Patch argument count.
2528   __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1);
2529 }
2530
2531
2532 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
2533   // esp[0] : return address
2534   // esp[8] : number of parameters
2535   // esp[16] : receiver displacement
2536   // esp[24] : function
2537
2538   // Check if the calling frame is an arguments adaptor frame.
2539   Label runtime;
2540   __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2541   __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
2542   __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2543   __ j(not_equal, &runtime);
2544
2545   // Patch the arguments.length and the parameters pointer.
2546   __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2547   __ movq(Operand(rsp, 1 * kPointerSize), rcx);
2548   __ SmiToInteger64(rcx, rcx);
2549   __ lea(rdx, Operand(rdx, rcx, times_pointer_size,
2550               StandardFrameConstants::kCallerSPOffset));
2551   __ movq(Operand(rsp, 2 * kPointerSize), rdx);
2552
2553   __ bind(&runtime);
2554   __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
2555 }
2556
2557
2558 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
2559   // rsp[0] : return address
2560   // rsp[8] : number of parameters
2561   // rsp[16] : receiver displacement
2562   // rsp[24] : function
2563
2564   // Check if the calling frame is an arguments adaptor frame.
2565   Label adaptor_frame, try_allocate, runtime;
2566   __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2567   __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
2568   __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2569   __ j(equal, &adaptor_frame);
2570
2571   // Get the length from the frame.
2572   __ movq(rcx, Operand(rsp, 1 * kPointerSize));
2573   __ SmiToInteger64(rcx, rcx);
2574   __ jmp(&try_allocate);
2575
2576   // Patch the arguments.length and the parameters pointer.
2577   __ bind(&adaptor_frame);
2578   __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2579   __ movq(Operand(rsp, 1 * kPointerSize), rcx);
2580   __ SmiToInteger64(rcx, rcx);
2581   __ lea(rdx, Operand(rdx, rcx, times_pointer_size,
2582                       StandardFrameConstants::kCallerSPOffset));
2583   __ movq(Operand(rsp, 2 * kPointerSize), rdx);
2584
2585   // Try the new space allocation. Start out with computing the size of
2586   // the arguments object and the elements array.
2587   Label add_arguments_object;
2588   __ bind(&try_allocate);
2589   __ testq(rcx, rcx);
2590   __ j(zero, &add_arguments_object, Label::kNear);
2591   __ lea(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize));
2592   __ bind(&add_arguments_object);
2593   __ addq(rcx, Immediate(Heap::kArgumentsObjectSizeStrict));
2594
2595   // Do the allocation of both objects in one go.
2596   __ AllocateInNewSpace(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT);
2597
2598   // Get the arguments boilerplate from the current (global) context.
2599   __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
2600   __ movq(rdi, FieldOperand(rdi, GlobalObject::kGlobalContextOffset));
2601   const int offset =
2602       Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX);
2603   __ movq(rdi, Operand(rdi, offset));
2604
2605   // Copy the JS object part.
2606   for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
2607     __ movq(rbx, FieldOperand(rdi, i));
2608     __ movq(FieldOperand(rax, i), rbx);
2609   }
2610
2611   // Get the length (smi tagged) and set that as an in-object property too.
2612   STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
2613   __ movq(rcx, Operand(rsp, 1 * kPointerSize));
2614   __ movq(FieldOperand(rax, JSObject::kHeaderSize +
2615                        Heap::kArgumentsLengthIndex * kPointerSize),
2616           rcx);
2617
2618   // If there are no actual arguments, we're done.
2619   Label done;
2620   __ testq(rcx, rcx);
2621   __ j(zero, &done);
2622
2623   // Get the parameters pointer from the stack.
2624   __ movq(rdx, Operand(rsp, 2 * kPointerSize));
2625
2626   // Set up the elements pointer in the allocated arguments object and
2627   // initialize the header in the elements fixed array.
2628   __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSizeStrict));
2629   __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi);
2630   __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex);
2631   __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister);
2632
2633
2634   __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx);
2635   // Untag the length for the loop below.
2636   __ SmiToInteger64(rcx, rcx);
2637
2638   // Copy the fixed array slots.
2639   Label loop;
2640   __ bind(&loop);
2641   __ movq(rbx, Operand(rdx, -1 * kPointerSize));  // Skip receiver.
2642   __ movq(FieldOperand(rdi, FixedArray::kHeaderSize), rbx);
2643   __ addq(rdi, Immediate(kPointerSize));
2644   __ subq(rdx, Immediate(kPointerSize));
2645   __ decq(rcx);
2646   __ j(not_zero, &loop);
2647
2648   // Return and remove the on-stack parameters.
2649   __ bind(&done);
2650   __ ret(3 * kPointerSize);
2651
2652   // Do the runtime call to allocate the arguments object.
2653   __ bind(&runtime);
2654   __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1);
2655 }
2656
2657
2658 void RegExpExecStub::Generate(MacroAssembler* masm) {
2659   // Just jump directly to runtime if native RegExp is not selected at compile
2660   // time or if regexp entry in generated code is turned off runtime switch or
2661   // at compilation.
2662 #ifdef V8_INTERPRETED_REGEXP
2663   __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
2664 #else  // V8_INTERPRETED_REGEXP
2665
2666   // Stack frame on entry.
2667   //  rsp[0]: return address
2668   //  rsp[8]: last_match_info (expected JSArray)
2669   //  rsp[16]: previous index
2670   //  rsp[24]: subject string
2671   //  rsp[32]: JSRegExp object
2672
2673   static const int kLastMatchInfoOffset = 1 * kPointerSize;
2674   static const int kPreviousIndexOffset = 2 * kPointerSize;
2675   static const int kSubjectOffset = 3 * kPointerSize;
2676   static const int kJSRegExpOffset = 4 * kPointerSize;
2677
2678   Label runtime;
2679   // Ensure that a RegExp stack is allocated.
2680   Isolate* isolate = masm->isolate();
2681   ExternalReference address_of_regexp_stack_memory_address =
2682       ExternalReference::address_of_regexp_stack_memory_address(isolate);
2683   ExternalReference address_of_regexp_stack_memory_size =
2684       ExternalReference::address_of_regexp_stack_memory_size(isolate);
2685   __ Load(kScratchRegister, address_of_regexp_stack_memory_size);
2686   __ testq(kScratchRegister, kScratchRegister);
2687   __ j(zero, &runtime);
2688
2689   // Check that the first argument is a JSRegExp object.
2690   __ movq(rax, Operand(rsp, kJSRegExpOffset));
2691   __ JumpIfSmi(rax, &runtime);
2692   __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister);
2693   __ j(not_equal, &runtime);
2694   // Check that the RegExp has been compiled (data contains a fixed array).
2695   __ movq(rax, FieldOperand(rax, JSRegExp::kDataOffset));
2696   if (FLAG_debug_code) {
2697     Condition is_smi = masm->CheckSmi(rax);
2698     __ Check(NegateCondition(is_smi),
2699         "Unexpected type for RegExp data, FixedArray expected");
2700     __ CmpObjectType(rax, FIXED_ARRAY_TYPE, kScratchRegister);
2701     __ Check(equal, "Unexpected type for RegExp data, FixedArray expected");
2702   }
2703
2704   // rax: RegExp data (FixedArray)
2705   // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
2706   __ SmiToInteger32(rbx, FieldOperand(rax, JSRegExp::kDataTagOffset));
2707   __ cmpl(rbx, Immediate(JSRegExp::IRREGEXP));
2708   __ j(not_equal, &runtime);
2709
2710   // rax: RegExp data (FixedArray)
2711   // Check that the number of captures fit in the static offsets vector buffer.
2712   __ SmiToInteger32(rdx,
2713                     FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset));
2714   // Calculate number of capture registers (number_of_captures + 1) * 2.
2715   __ leal(rdx, Operand(rdx, rdx, times_1, 2));
2716   // Check that the static offsets vector buffer is large enough.
2717   __ cmpl(rdx, Immediate(OffsetsVector::kStaticOffsetsVectorSize));
2718   __ j(above, &runtime);
2719
2720   // rax: RegExp data (FixedArray)
2721   // rdx: Number of capture registers
2722   // Check that the second argument is a string.
2723   __ movq(rdi, Operand(rsp, kSubjectOffset));
2724   __ JumpIfSmi(rdi, &runtime);
2725   Condition is_string = masm->IsObjectStringType(rdi, rbx, rbx);
2726   __ j(NegateCondition(is_string), &runtime);
2727
2728   // rdi: Subject string.
2729   // rax: RegExp data (FixedArray).
2730   // rdx: Number of capture registers.
2731   // Check that the third argument is a positive smi less than the string
2732   // length. A negative value will be greater (unsigned comparison).
2733   __ movq(rbx, Operand(rsp, kPreviousIndexOffset));
2734   __ JumpIfNotSmi(rbx, &runtime);
2735   __ SmiCompare(rbx, FieldOperand(rdi, String::kLengthOffset));
2736   __ j(above_equal, &runtime);
2737
2738   // rax: RegExp data (FixedArray)
2739   // rdx: Number of capture registers
2740   // Check that the fourth object is a JSArray object.
2741   __ movq(rdi, Operand(rsp, kLastMatchInfoOffset));
2742   __ JumpIfSmi(rdi, &runtime);
2743   __ CmpObjectType(rdi, JS_ARRAY_TYPE, kScratchRegister);
2744   __ j(not_equal, &runtime);
2745   // Check that the JSArray is in fast case.
2746   __ movq(rbx, FieldOperand(rdi, JSArray::kElementsOffset));
2747   __ movq(rdi, FieldOperand(rbx, HeapObject::kMapOffset));
2748   __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
2749                  Heap::kFixedArrayMapRootIndex);
2750   __ j(not_equal, &runtime);
2751   // Check that the last match info has space for the capture registers and the
2752   // additional information. Ensure no overflow in add.
2753   STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset);
2754   __ SmiToInteger32(rdi, FieldOperand(rbx, FixedArray::kLengthOffset));
2755   __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead));
2756   __ cmpl(rdx, rdi);
2757   __ j(greater, &runtime);
2758
2759   // Reset offset for possibly sliced string.
2760   __ Set(r14, 0);
2761   // rax: RegExp data (FixedArray)
2762   // Check the representation and encoding of the subject string.
2763   Label seq_ascii_string, seq_two_byte_string, check_code;
2764   __ movq(rdi, Operand(rsp, kSubjectOffset));
2765   // Make a copy of the original subject string.
2766   __ movq(r15, rdi);
2767   __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
2768   __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2769   // First check for flat two byte string.
2770   __ andb(rbx, Immediate(kIsNotStringMask |
2771                          kStringRepresentationMask |
2772                          kStringEncodingMask |
2773                          kShortExternalStringMask));
2774   STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
2775   __ j(zero, &seq_two_byte_string, Label::kNear);
2776   // Any other flat string must be a flat ASCII string.  None of the following
2777   // string type tests will succeed if subject is not a string or a short
2778   // external string.
2779   __ andb(rbx, Immediate(kIsNotStringMask |
2780                          kStringRepresentationMask |
2781                          kShortExternalStringMask));
2782   __ j(zero, &seq_ascii_string, Label::kNear);
2783
2784   // rbx: whether subject is a string and if yes, its string representation
2785   // Check for flat cons string or sliced string.
2786   // A flat cons string is a cons string where the second part is the empty
2787   // string. In that case the subject string is just the first part of the cons
2788   // string. Also in this case the first part of the cons string is known to be
2789   // a sequential string or an external string.
2790   // In the case of a sliced string its offset has to be taken into account.
2791   Label cons_string, external_string, check_encoding;
2792   STATIC_ASSERT(kConsStringTag < kExternalStringTag);
2793   STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
2794   STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
2795   STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
2796   __ cmpq(rbx, Immediate(kExternalStringTag));
2797   __ j(less, &cons_string, Label::kNear);
2798   __ j(equal, &external_string);
2799
2800   // Catch non-string subject or short external string.
2801   STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
2802   __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask));
2803   __ j(not_zero, &runtime);
2804
2805   // String is sliced.
2806   __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset));
2807   __ movq(rdi, FieldOperand(rdi, SlicedString::kParentOffset));
2808   // r14: slice offset
2809   // r15: original subject string
2810   // rdi: parent string
2811   __ jmp(&check_encoding, Label::kNear);
2812   // String is a cons string, check whether it is flat.
2813   __ bind(&cons_string);
2814   __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset),
2815                  Heap::kEmptyStringRootIndex);
2816   __ j(not_equal, &runtime);
2817   __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset));
2818   // rdi: first part of cons string or parent of sliced string.
2819   // rbx: map of first part of cons string or map of parent of sliced string.
2820   // Is first part of cons or parent of slice a flat two byte string?
2821   __ bind(&check_encoding);
2822   __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
2823   __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
2824            Immediate(kStringRepresentationMask | kStringEncodingMask));
2825   STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
2826   __ j(zero, &seq_two_byte_string, Label::kNear);
2827   // Any other flat string must be sequential ASCII or external.
2828   __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
2829            Immediate(kStringRepresentationMask));
2830   __ j(not_zero, &external_string);
2831
2832   __ bind(&seq_ascii_string);
2833   // rdi: subject string (sequential ASCII)
2834   // rax: RegExp data (FixedArray)
2835   __ movq(r11, FieldOperand(rax, JSRegExp::kDataAsciiCodeOffset));
2836   __ Set(rcx, 1);  // Type is ASCII.
2837   __ jmp(&check_code, Label::kNear);
2838
2839   __ bind(&seq_two_byte_string);
2840   // rdi: subject string (flat two-byte)
2841   // rax: RegExp data (FixedArray)
2842   __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset));
2843   __ Set(rcx, 0);  // Type is two byte.
2844
2845   __ bind(&check_code);
2846   // Check that the irregexp code has been generated for the actual string
2847   // encoding. If it has, the field contains a code object otherwise it contains
2848   // smi (code flushing support)
2849   __ JumpIfSmi(r11, &runtime);
2850
2851   // rdi: subject string
2852   // rcx: encoding of subject string (1 if ASCII, 0 if two_byte);
2853   // r11: code
2854   // Load used arguments before starting to push arguments for call to native
2855   // RegExp code to avoid handling changing stack height.
2856   __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset));
2857
2858   // rdi: subject string
2859   // rbx: previous index
2860   // rcx: encoding of subject string (1 if ASCII 0 if two_byte);
2861   // r11: code
2862   // All checks done. Now push arguments for native regexp code.
2863   Counters* counters = masm->isolate()->counters();
2864   __ IncrementCounter(counters->regexp_entry_native(), 1);
2865
2866   // Isolates: note we add an additional parameter here (isolate pointer).
2867   static const int kRegExpExecuteArguments = 8;
2868   int argument_slots_on_stack =
2869       masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments);
2870   __ EnterApiExitFrame(argument_slots_on_stack);
2871
2872   // Argument 8: Pass current isolate address.
2873   // __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize),
2874   //     Immediate(ExternalReference::isolate_address()));
2875   __ LoadAddress(kScratchRegister, ExternalReference::isolate_address());
2876   __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize),
2877           kScratchRegister);
2878
2879   // Argument 7: Indicate that this is a direct call from JavaScript.
2880   __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kPointerSize),
2881           Immediate(1));
2882
2883   // Argument 6: Start (high end) of backtracking stack memory area.
2884   __ movq(kScratchRegister, address_of_regexp_stack_memory_address);
2885   __ movq(r9, Operand(kScratchRegister, 0));
2886   __ movq(kScratchRegister, address_of_regexp_stack_memory_size);
2887   __ addq(r9, Operand(kScratchRegister, 0));
2888   // Argument 6 passed in r9 on Linux and on the stack on Windows.
2889 #ifdef _WIN64
2890   __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kPointerSize), r9);
2891 #endif
2892
2893   // Argument 5: static offsets vector buffer.
2894   __ LoadAddress(r8,
2895                  ExternalReference::address_of_static_offsets_vector(isolate));
2896   // Argument 5 passed in r8 on Linux and on the stack on Windows.
2897 #ifdef _WIN64
2898   __ movq(Operand(rsp, (argument_slots_on_stack - 4) * kPointerSize), r8);
2899 #endif
2900
2901   // First four arguments are passed in registers on both Linux and Windows.
2902 #ifdef _WIN64
2903   Register arg4 = r9;
2904   Register arg3 = r8;
2905   Register arg2 = rdx;
2906   Register arg1 = rcx;
2907 #else
2908   Register arg4 = rcx;
2909   Register arg3 = rdx;
2910   Register arg2 = rsi;
2911   Register arg1 = rdi;
2912 #endif
2913
2914   // Keep track on aliasing between argX defined above and the registers used.
2915   // rdi: subject string
2916   // rbx: previous index
2917   // rcx: encoding of subject string (1 if ASCII 0 if two_byte);
2918   // r11: code
2919   // r14: slice offset
2920   // r15: original subject string
2921
2922   // Argument 2: Previous index.
2923   __ movq(arg2, rbx);
2924
2925   // Argument 4: End of string data
2926   // Argument 3: Start of string data
2927   Label setup_two_byte, setup_rest, got_length, length_not_from_slice;
2928   // Prepare start and end index of the input.
2929   // Load the length from the original sliced string if that is the case.
2930   __ addq(rbx, r14);
2931   __ SmiToInteger32(arg3, FieldOperand(r15, String::kLengthOffset));
2932   __ addq(r14, arg3);  // Using arg3 as scratch.
2933
2934   // rbx: start index of the input
2935   // r14: end index of the input
2936   // r15: original subject string
2937   __ testb(rcx, rcx);  // Last use of rcx as encoding of subject string.
2938   __ j(zero, &setup_two_byte, Label::kNear);
2939   __ lea(arg4, FieldOperand(rdi, r14, times_1, SeqAsciiString::kHeaderSize));
2940   __ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqAsciiString::kHeaderSize));
2941   __ jmp(&setup_rest, Label::kNear);
2942   __ bind(&setup_two_byte);
2943   __ lea(arg4, FieldOperand(rdi, r14, times_2, SeqTwoByteString::kHeaderSize));
2944   __ lea(arg3, FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize));
2945   __ bind(&setup_rest);
2946
2947   // Argument 1: Original subject string.
2948   // The original subject is in the previous stack frame. Therefore we have to
2949   // use rbp, which points exactly to one pointer size below the previous rsp.
2950   // (Because creating a new stack frame pushes the previous rbp onto the stack
2951   // and thereby moves up rsp by one kPointerSize.)
2952   __ movq(arg1, r15);
2953
2954   // Locate the code entry and call it.
2955   __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag));
2956   __ call(r11);
2957
2958   __ LeaveApiExitFrame();
2959
2960   // Check the result.
2961   Label success;
2962   Label exception;
2963   __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS));
2964   __ j(equal, &success, Label::kNear);
2965   __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION));
2966   __ j(equal, &exception);
2967   __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE));
2968   // If none of the above, it can only be retry.
2969   // Handle that in the runtime system.
2970   __ j(not_equal, &runtime);
2971
2972   // For failure return null.
2973   __ LoadRoot(rax, Heap::kNullValueRootIndex);
2974   __ ret(4 * kPointerSize);
2975
2976   // Load RegExp data.
2977   __ bind(&success);
2978   __ movq(rax, Operand(rsp, kJSRegExpOffset));
2979   __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset));
2980   __ SmiToInteger32(rax,
2981                     FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset));
2982   // Calculate number of capture registers (number_of_captures + 1) * 2.
2983   __ leal(rdx, Operand(rax, rax, times_1, 2));
2984
2985   // rdx: Number of capture registers
2986   // Load last_match_info which is still known to be a fast case JSArray.
2987   __ movq(rax, Operand(rsp, kLastMatchInfoOffset));
2988   __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset));
2989
2990   // rbx: last_match_info backing store (FixedArray)
2991   // rdx: number of capture registers
2992   // Store the capture count.
2993   __ Integer32ToSmi(kScratchRegister, rdx);
2994   __ movq(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset),
2995           kScratchRegister);
2996   // Store last subject and last input.
2997   __ movq(rax, Operand(rsp, kSubjectOffset));
2998   __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax);
2999   __ RecordWriteField(rbx,
3000                       RegExpImpl::kLastSubjectOffset,
3001                       rax,
3002                       rdi,
3003                       kDontSaveFPRegs);
3004   __ movq(rax, Operand(rsp, kSubjectOffset));
3005   __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax);
3006   __ RecordWriteField(rbx,
3007                       RegExpImpl::kLastInputOffset,
3008                       rax,
3009                       rdi,
3010                       kDontSaveFPRegs);
3011
3012   // Get the static offsets vector filled by the native regexp code.
3013   __ LoadAddress(rcx,
3014                  ExternalReference::address_of_static_offsets_vector(isolate));
3015
3016   // rbx: last_match_info backing store (FixedArray)
3017   // rcx: offsets vector
3018   // rdx: number of capture registers
3019   Label next_capture, done;
3020   // Capture register counter starts from number of capture registers and
3021   // counts down until wraping after zero.
3022   __ bind(&next_capture);
3023   __ subq(rdx, Immediate(1));
3024   __ j(negative, &done, Label::kNear);
3025   // Read the value from the static offsets vector buffer and make it a smi.
3026   __ movl(rdi, Operand(rcx, rdx, times_int_size, 0));
3027   __ Integer32ToSmi(rdi, rdi);
3028   // Store the smi value in the last match info.
3029   __ movq(FieldOperand(rbx,
3030                        rdx,
3031                        times_pointer_size,
3032                        RegExpImpl::kFirstCaptureOffset),
3033           rdi);
3034   __ jmp(&next_capture);
3035   __ bind(&done);
3036
3037   // Return last match info.
3038   __ movq(rax, Operand(rsp, kLastMatchInfoOffset));
3039   __ ret(4 * kPointerSize);
3040
3041   __ bind(&exception);
3042   // Result must now be exception. If there is no pending exception already a
3043   // stack overflow (on the backtrack stack) was detected in RegExp code but
3044   // haven't created the exception yet. Handle that in the runtime system.
3045   // TODO(592): Rerunning the RegExp to get the stack overflow exception.
3046   ExternalReference pending_exception_address(
3047       Isolate::kPendingExceptionAddress, isolate);
3048   Operand pending_exception_operand =
3049       masm->ExternalOperand(pending_exception_address, rbx);
3050   __ movq(rax, pending_exception_operand);
3051   __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
3052   __ cmpq(rax, rdx);
3053   __ j(equal, &runtime);
3054   __ movq(pending_exception_operand, rdx);
3055
3056   __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex);
3057   Label termination_exception;
3058   __ j(equal, &termination_exception, Label::kNear);
3059   __ Throw(rax);
3060
3061   __ bind(&termination_exception);
3062   __ ThrowUncatchable(rax);
3063
3064   // External string.  Short external strings have already been ruled out.
3065   // rdi: subject string (expected to be external)
3066   // rbx: scratch
3067   __ bind(&external_string);
3068   __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
3069   __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
3070   if (FLAG_debug_code) {
3071     // Assert that we do not have a cons or slice (indirect strings) here.
3072     // Sequential strings have already been ruled out.
3073     __ testb(rbx, Immediate(kIsIndirectStringMask));
3074     __ Assert(zero, "external string expected, but not found");
3075   }
3076   __ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset));
3077   // Move the pointer so that offset-wise, it looks like a sequential string.
3078   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize);
3079   __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
3080   STATIC_ASSERT(kTwoByteStringTag == 0);
3081   __ testb(rbx, Immediate(kStringEncodingMask));
3082   __ j(not_zero, &seq_ascii_string);
3083   __ jmp(&seq_two_byte_string);
3084
3085   // Do the runtime call to execute the regexp.
3086   __ bind(&runtime);
3087   __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
3088 #endif  // V8_INTERPRETED_REGEXP
3089 }
3090
3091
3092 void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
3093   const int kMaxInlineLength = 100;
3094   Label slowcase;
3095   Label done;
3096   __ movq(r8, Operand(rsp, kPointerSize * 3));
3097   __ JumpIfNotSmi(r8, &slowcase);
3098   __ SmiToInteger32(rbx, r8);
3099   __ cmpl(rbx, Immediate(kMaxInlineLength));
3100   __ j(above, &slowcase);
3101   // Smi-tagging is equivalent to multiplying by 2.
3102   STATIC_ASSERT(kSmiTag == 0);
3103   STATIC_ASSERT(kSmiTagSize == 1);
3104   // Allocate RegExpResult followed by FixedArray with size in rbx.
3105   // JSArray:   [Map][empty properties][Elements][Length-smi][index][input]
3106   // Elements:  [Map][Length][..elements..]
3107   __ AllocateInNewSpace(JSRegExpResult::kSize + FixedArray::kHeaderSize,
3108                         times_pointer_size,
3109                         rbx,  // In: Number of elements.
3110                         rax,  // Out: Start of allocation (tagged).
3111                         rcx,  // Out: End of allocation.
3112                         rdx,  // Scratch register
3113                         &slowcase,
3114                         TAG_OBJECT);
3115   // rax: Start of allocated area, object-tagged.
3116   // rbx: Number of array elements as int32.
3117   // r8: Number of array elements as smi.
3118
3119   // Set JSArray map to global.regexp_result_map().
3120   __ movq(rdx, ContextOperand(rsi, Context::GLOBAL_INDEX));
3121   __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalContextOffset));
3122   __ movq(rdx, ContextOperand(rdx, Context::REGEXP_RESULT_MAP_INDEX));
3123   __ movq(FieldOperand(rax, HeapObject::kMapOffset), rdx);
3124
3125   // Set empty properties FixedArray.
3126   __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex);
3127   __ movq(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister);
3128
3129   // Set elements to point to FixedArray allocated right after the JSArray.
3130   __ lea(rcx, Operand(rax, JSRegExpResult::kSize));
3131   __ movq(FieldOperand(rax, JSObject::kElementsOffset), rcx);
3132
3133   // Set input, index and length fields from arguments.
3134   __ movq(r8, Operand(rsp, kPointerSize * 1));
3135   __ movq(FieldOperand(rax, JSRegExpResult::kInputOffset), r8);
3136   __ movq(r8, Operand(rsp, kPointerSize * 2));
3137   __ movq(FieldOperand(rax, JSRegExpResult::kIndexOffset), r8);
3138   __ movq(r8, Operand(rsp, kPointerSize * 3));
3139   __ movq(FieldOperand(rax, JSArray::kLengthOffset), r8);
3140
3141   // Fill out the elements FixedArray.
3142   // rax: JSArray.
3143   // rcx: FixedArray.
3144   // rbx: Number of elements in array as int32.
3145
3146   // Set map.
3147   __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex);
3148   __ movq(FieldOperand(rcx, HeapObject::kMapOffset), kScratchRegister);
3149   // Set length.
3150   __ Integer32ToSmi(rdx, rbx);
3151   __ movq(FieldOperand(rcx, FixedArray::kLengthOffset), rdx);
3152   // Fill contents of fixed-array with the-hole.
3153   __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
3154   __ lea(rcx, FieldOperand(rcx, FixedArray::kHeaderSize));
3155   // Fill fixed array elements with hole.
3156   // rax: JSArray.
3157   // rbx: Number of elements in array that remains to be filled, as int32.
3158   // rcx: Start of elements in FixedArray.
3159   // rdx: the hole.
3160   Label loop;
3161   __ testl(rbx, rbx);
3162   __ bind(&loop);
3163   __ j(less_equal, &done);  // Jump if rcx is negative or zero.
3164   __ subl(rbx, Immediate(1));
3165   __ movq(Operand(rcx, rbx, times_pointer_size, 0), rdx);
3166   __ jmp(&loop);
3167
3168   __ bind(&done);
3169   __ ret(3 * kPointerSize);
3170
3171   __ bind(&slowcase);
3172   __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1);
3173 }
3174
3175
3176 void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
3177                                                          Register object,
3178                                                          Register result,
3179                                                          Register scratch1,
3180                                                          Register scratch2,
3181                                                          bool object_is_smi,
3182                                                          Label* not_found) {
3183   // Use of registers. Register result is used as a temporary.
3184   Register number_string_cache = result;
3185   Register mask = scratch1;
3186   Register scratch = scratch2;
3187
3188   // Load the number string cache.
3189   __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
3190
3191   // Make the hash mask from the length of the number string cache. It
3192   // contains two elements (number and string) for each cache entry.
3193   __ SmiToInteger32(
3194       mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
3195   __ shrl(mask, Immediate(1));
3196   __ subq(mask, Immediate(1));  // Make mask.
3197
3198   // Calculate the entry in the number string cache. The hash value in the
3199   // number string cache for smis is just the smi value, and the hash for
3200   // doubles is the xor of the upper and lower words. See
3201   // Heap::GetNumberStringCache.
3202   Label is_smi;
3203   Label load_result_from_cache;
3204   Factory* factory = masm->isolate()->factory();
3205   if (!object_is_smi) {
3206     __ JumpIfSmi(object, &is_smi);
3207     __ CheckMap(object,
3208                 factory->heap_number_map(),
3209                 not_found,
3210                 DONT_DO_SMI_CHECK);
3211
3212     STATIC_ASSERT(8 == kDoubleSize);
3213     __ movl(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
3214     __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset));
3215     GenerateConvertHashCodeToIndex(masm, scratch, mask);
3216
3217     Register index = scratch;
3218     Register probe = mask;
3219     __ movq(probe,
3220             FieldOperand(number_string_cache,
3221                          index,
3222                          times_1,
3223                          FixedArray::kHeaderSize));
3224     __ JumpIfSmi(probe, not_found);
3225     __ movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
3226     __ movsd(xmm1, FieldOperand(probe, HeapNumber::kValueOffset));
3227     __ ucomisd(xmm0, xmm1);
3228     __ j(parity_even, not_found);  // Bail out if NaN is involved.
3229     __ j(not_equal, not_found);  // The cache did not contain this value.
3230     __ jmp(&load_result_from_cache);
3231   }
3232
3233   __ bind(&is_smi);
3234   __ SmiToInteger32(scratch, object);
3235   GenerateConvertHashCodeToIndex(masm, scratch, mask);
3236
3237   Register index = scratch;
3238   // Check if the entry is the smi we are looking for.
3239   __ cmpq(object,
3240           FieldOperand(number_string_cache,
3241                        index,
3242                        times_1,
3243                        FixedArray::kHeaderSize));
3244   __ j(not_equal, not_found);
3245
3246   // Get the result from the cache.
3247   __ bind(&load_result_from_cache);
3248   __ movq(result,
3249           FieldOperand(number_string_cache,
3250                        index,
3251                        times_1,
3252                        FixedArray::kHeaderSize + kPointerSize));
3253   Counters* counters = masm->isolate()->counters();
3254   __ IncrementCounter(counters->number_to_string_native(), 1);
3255 }
3256
3257
3258 void NumberToStringStub::GenerateConvertHashCodeToIndex(MacroAssembler* masm,
3259                                                         Register hash,
3260                                                         Register mask) {
3261   __ and_(hash, mask);
3262   // Each entry in string cache consists of two pointer sized fields,
3263   // but times_twice_pointer_size (multiplication by 16) scale factor
3264   // is not supported by addrmode on x64 platform.
3265   // So we have to premultiply entry index before lookup.
3266   __ shl(hash, Immediate(kPointerSizeLog2 + 1));
3267 }
3268
3269
3270 void NumberToStringStub::Generate(MacroAssembler* masm) {
3271   Label runtime;
3272
3273   __ movq(rbx, Operand(rsp, kPointerSize));
3274
3275   // Generate code to lookup number in the number string cache.
3276   GenerateLookupNumberStringCache(masm, rbx, rax, r8, r9, false, &runtime);
3277   __ ret(1 * kPointerSize);
3278
3279   __ bind(&runtime);
3280   // Handle number to string in the runtime system if not found in the cache.
3281   __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1);
3282 }
3283
3284
3285 static int NegativeComparisonResult(Condition cc) {
3286   ASSERT(cc != equal);
3287   ASSERT((cc == less) || (cc == less_equal)
3288       || (cc == greater) || (cc == greater_equal));
3289   return (cc == greater || cc == greater_equal) ? LESS : GREATER;
3290 }
3291
3292
3293 void CompareStub::Generate(MacroAssembler* masm) {
3294   ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
3295
3296   Label check_unequal_objects, done;
3297   Factory* factory = masm->isolate()->factory();
3298
3299   // Compare two smis if required.
3300   if (include_smi_compare_) {
3301     Label non_smi, smi_done;
3302     __ JumpIfNotBothSmi(rax, rdx, &non_smi);
3303     __ subq(rdx, rax);
3304     __ j(no_overflow, &smi_done);
3305     __ not_(rdx);  // Correct sign in case of overflow. rdx cannot be 0 here.
3306     __ bind(&smi_done);
3307     __ movq(rax, rdx);
3308     __ ret(0);
3309     __ bind(&non_smi);
3310   } else if (FLAG_debug_code) {
3311     Label ok;
3312     __ JumpIfNotSmi(rdx, &ok);
3313     __ JumpIfNotSmi(rax, &ok);
3314     __ Abort("CompareStub: smi operands");
3315     __ bind(&ok);
3316   }
3317
3318   // The compare stub returns a positive, negative, or zero 64-bit integer
3319   // value in rax, corresponding to result of comparing the two inputs.
3320   // NOTICE! This code is only reached after a smi-fast-case check, so
3321   // it is certain that at least one operand isn't a smi.
3322
3323   // Two identical objects are equal unless they are both NaN or undefined.
3324   {
3325     Label not_identical;
3326     __ cmpq(rax, rdx);
3327     __ j(not_equal, &not_identical, Label::kNear);
3328
3329     if (cc_ != equal) {
3330       // Check for undefined.  undefined OP undefined is false even though
3331       // undefined == undefined.
3332       Label check_for_nan;
3333       __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
3334       __ j(not_equal, &check_for_nan, Label::kNear);
3335       __ Set(rax, NegativeComparisonResult(cc_));
3336       __ ret(0);
3337       __ bind(&check_for_nan);
3338     }
3339
3340     // Test for NaN. Sadly, we can't just compare to FACTORY->nan_value(),
3341     // so we do the second best thing - test it ourselves.
3342     // Note: if cc_ != equal, never_nan_nan_ is not used.
3343     // We cannot set rax to EQUAL until just before return because
3344     // rax must be unchanged on jump to not_identical.
3345     if (never_nan_nan_ && (cc_ == equal)) {
3346       __ Set(rax, EQUAL);
3347       __ ret(0);
3348     } else {
3349       Label heap_number;
3350       // If it's not a heap number, then return equal for (in)equality operator.
3351       __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
3352              factory->heap_number_map());
3353       __ j(equal, &heap_number, Label::kNear);
3354       if (cc_ != equal) {
3355         // Call runtime on identical objects.  Otherwise return equal.
3356         __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
3357         __ j(above_equal, &not_identical, Label::kNear);
3358       }
3359       __ Set(rax, EQUAL);
3360       __ ret(0);
3361
3362       __ bind(&heap_number);
3363       // It is a heap number, so return  equal if it's not NaN.
3364       // For NaN, return 1 for every condition except greater and
3365       // greater-equal.  Return -1 for them, so the comparison yields
3366       // false for all conditions except not-equal.
3367       __ Set(rax, EQUAL);
3368       __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
3369       __ ucomisd(xmm0, xmm0);
3370       __ setcc(parity_even, rax);
3371       // rax is 0 for equal non-NaN heapnumbers, 1 for NaNs.
3372       if (cc_ == greater_equal || cc_ == greater) {
3373         __ neg(rax);
3374       }
3375       __ ret(0);
3376     }
3377
3378     __ bind(&not_identical);
3379   }
3380
3381   if (cc_ == equal) {  // Both strict and non-strict.
3382     Label slow;  // Fallthrough label.
3383
3384     // If we're doing a strict equality comparison, we don't have to do
3385     // type conversion, so we generate code to do fast comparison for objects
3386     // and oddballs. Non-smi numbers and strings still go through the usual
3387     // slow-case code.
3388     if (strict_) {
3389       // If either is a Smi (we know that not both are), then they can only
3390       // be equal if the other is a HeapNumber. If so, use the slow case.
3391       {
3392         Label not_smis;
3393         __ SelectNonSmi(rbx, rax, rdx, &not_smis);
3394
3395         // Check if the non-smi operand is a heap number.
3396         __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
3397                factory->heap_number_map());
3398         // If heap number, handle it in the slow case.
3399         __ j(equal, &slow);
3400         // Return non-equal.  ebx (the lower half of rbx) is not zero.
3401         __ movq(rax, rbx);
3402         __ ret(0);
3403
3404         __ bind(&not_smis);
3405       }
3406
3407       // If either operand is a JSObject or an oddball value, then they are not
3408       // equal since their pointers are different
3409       // There is no test for undetectability in strict equality.
3410
3411       // If the first object is a JS object, we have done pointer comparison.
3412       STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
3413       Label first_non_object;
3414       __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
3415       __ j(below, &first_non_object, Label::kNear);
3416       // Return non-zero (eax (not rax) is not zero)
3417       Label return_not_equal;
3418       STATIC_ASSERT(kHeapObjectTag != 0);
3419       __ bind(&return_not_equal);
3420       __ ret(0);
3421
3422       __ bind(&first_non_object);
3423       // Check for oddballs: true, false, null, undefined.
3424       __ CmpInstanceType(rcx, ODDBALL_TYPE);
3425       __ j(equal, &return_not_equal);
3426
3427       __ CmpObjectType(rdx, FIRST_SPEC_OBJECT_TYPE, rcx);
3428       __ j(above_equal, &return_not_equal);
3429
3430       // Check for oddballs: true, false, null, undefined.
3431       __ CmpInstanceType(rcx, ODDBALL_TYPE);
3432       __ j(equal, &return_not_equal);
3433
3434       // Fall through to the general case.
3435     }
3436     __ bind(&slow);
3437   }
3438
3439   // Generate the number comparison code.
3440   if (include_number_compare_) {
3441     Label non_number_comparison;
3442     Label unordered;
3443     FloatingPointHelper::LoadSSE2UnknownOperands(masm, &non_number_comparison);
3444     __ xorl(rax, rax);
3445     __ xorl(rcx, rcx);
3446     __ ucomisd(xmm0, xmm1);
3447
3448     // Don't base result on EFLAGS when a NaN is involved.
3449     __ j(parity_even, &unordered, Label::kNear);
3450     // Return a result of -1, 0, or 1, based on EFLAGS.
3451     __ setcc(above, rax);
3452     __ setcc(below, rcx);
3453     __ subq(rax, rcx);
3454     __ ret(0);
3455
3456     // If one of the numbers was NaN, then the result is always false.
3457     // The cc is never not-equal.
3458     __ bind(&unordered);
3459     ASSERT(cc_ != not_equal);
3460     if (cc_ == less || cc_ == less_equal) {
3461       __ Set(rax, 1);
3462     } else {
3463       __ Set(rax, -1);
3464     }
3465     __ ret(0);
3466
3467     // The number comparison code did not provide a valid result.
3468     __ bind(&non_number_comparison);
3469   }
3470
3471   // Fast negative check for symbol-to-symbol equality.
3472   Label check_for_strings;
3473   if (cc_ == equal) {
3474     BranchIfNonSymbol(masm, &check_for_strings, rax, kScratchRegister);
3475     BranchIfNonSymbol(masm, &check_for_strings, rdx, kScratchRegister);
3476
3477     // We've already checked for object identity, so if both operands
3478     // are symbols they aren't equal. Register eax (not rax) already holds a
3479     // non-zero value, which indicates not equal, so just return.
3480     __ ret(0);
3481   }
3482
3483   __ bind(&check_for_strings);
3484
3485   __ JumpIfNotBothSequentialAsciiStrings(
3486       rdx, rax, rcx, rbx, &check_unequal_objects);
3487
3488   // Inline comparison of ASCII strings.
3489   if (cc_ == equal) {
3490     StringCompareStub::GenerateFlatAsciiStringEquals(masm,
3491                                                      rdx,
3492                                                      rax,
3493                                                      rcx,
3494                                                      rbx);
3495   } else {
3496     StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
3497                                                        rdx,
3498                                                        rax,
3499                                                        rcx,
3500                                                        rbx,
3501                                                        rdi,
3502                                                        r8);
3503   }
3504
3505 #ifdef DEBUG
3506   __ Abort("Unexpected fall-through from string comparison");
3507 #endif
3508
3509   __ bind(&check_unequal_objects);
3510   if (cc_ == equal && !strict_) {
3511     // Not strict equality.  Objects are unequal if
3512     // they are both JSObjects and not undetectable,
3513     // and their pointers are different.
3514     Label not_both_objects, return_unequal;
3515     // At most one is a smi, so we can test for smi by adding the two.
3516     // A smi plus a heap object has the low bit set, a heap object plus
3517     // a heap object has the low bit clear.
3518     STATIC_ASSERT(kSmiTag == 0);
3519     STATIC_ASSERT(kSmiTagMask == 1);
3520     __ lea(rcx, Operand(rax, rdx, times_1, 0));
3521     __ testb(rcx, Immediate(kSmiTagMask));
3522     __ j(not_zero, &not_both_objects, Label::kNear);
3523     __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx);
3524     __ j(below, &not_both_objects, Label::kNear);
3525     __ CmpObjectType(rdx, FIRST_SPEC_OBJECT_TYPE, rcx);
3526     __ j(below, &not_both_objects, Label::kNear);
3527     __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
3528              Immediate(1 << Map::kIsUndetectable));
3529     __ j(zero, &return_unequal, Label::kNear);
3530     __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
3531              Immediate(1 << Map::kIsUndetectable));
3532     __ j(zero, &return_unequal, Label::kNear);
3533     // The objects are both undetectable, so they both compare as the value
3534     // undefined, and are equal.
3535     __ Set(rax, EQUAL);
3536     __ bind(&return_unequal);
3537     // Return non-equal by returning the non-zero object pointer in rax,
3538     // or return equal if we fell through to here.
3539     __ ret(0);
3540     __ bind(&not_both_objects);
3541   }
3542
3543   // Push arguments below the return address to prepare jump to builtin.
3544   __ pop(rcx);
3545   __ push(rdx);
3546   __ push(rax);
3547
3548   // Figure out which native to call and setup the arguments.
3549   Builtins::JavaScript builtin;
3550   if (cc_ == equal) {
3551     builtin = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
3552   } else {
3553     builtin = Builtins::COMPARE;
3554     __ Push(Smi::FromInt(NegativeComparisonResult(cc_)));
3555   }
3556
3557   // Restore return address on the stack.
3558   __ push(rcx);
3559
3560   // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
3561   // tagged as a small integer.
3562   __ InvokeBuiltin(builtin, JUMP_FUNCTION);
3563 }
3564
3565
3566 void CompareStub::BranchIfNonSymbol(MacroAssembler* masm,
3567                                     Label* label,
3568                                     Register object,
3569                                     Register scratch) {
3570   __ JumpIfSmi(object, label);
3571   __ movq(scratch, FieldOperand(object, HeapObject::kMapOffset));
3572   __ movzxbq(scratch,
3573              FieldOperand(scratch, Map::kInstanceTypeOffset));
3574   // Ensure that no non-strings have the symbol bit set.
3575   STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsSymbolMask);
3576   STATIC_ASSERT(kSymbolTag != 0);
3577   __ testb(scratch, Immediate(kIsSymbolMask));
3578   __ j(zero, label);
3579 }
3580
3581
3582 void StackCheckStub::Generate(MacroAssembler* masm) {
3583   __ TailCallRuntime(Runtime::kStackGuard, 0, 1);
3584 }
3585
3586
3587 void InterruptStub::Generate(MacroAssembler* masm) {
3588   __ TailCallRuntime(Runtime::kInterrupt, 0, 1);
3589 }
3590
3591
3592 static void GenerateRecordCallTarget(MacroAssembler* masm) {
3593   // Cache the called function in a global property cell.  Cache states
3594   // are uninitialized, monomorphic (indicated by a JSFunction), and
3595   // megamorphic.
3596   // rbx : cache cell for call target
3597   // rdi : the function to call
3598   Isolate* isolate = masm->isolate();
3599   Label initialize, done;
3600
3601   // Load the cache state into rcx.
3602   __ movq(rcx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
3603
3604   // A monomorphic cache hit or an already megamorphic state: invoke the
3605   // function without changing the state.
3606   __ cmpq(rcx, rdi);
3607   __ j(equal, &done, Label::kNear);
3608   __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate));
3609   __ j(equal, &done, Label::kNear);
3610
3611   // A monomorphic miss (i.e, here the cache is not uninitialized) goes
3612   // megamorphic.
3613   __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate));
3614   __ j(equal, &initialize, Label::kNear);
3615   // MegamorphicSentinel is an immortal immovable object (undefined) so no
3616   // write-barrier is needed.
3617   __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
3618           TypeFeedbackCells::MegamorphicSentinel(isolate));
3619   __ jmp(&done, Label::kNear);
3620
3621   // An uninitialized cache is patched with the function.
3622   __ bind(&initialize);
3623   __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rdi);
3624   // No need for a write barrier here - cells are rescanned.
3625
3626   __ bind(&done);
3627 }
3628
3629
3630 void CallFunctionStub::Generate(MacroAssembler* masm) {
3631   // rdi : the function to call
3632   // rbx : cache cell for call target
3633   Label slow, non_function;
3634
3635   // The receiver might implicitly be the global object. This is
3636   // indicated by passing the hole as the receiver to the call
3637   // function stub.
3638   if (ReceiverMightBeImplicit()) {
3639     Label call;
3640     // Get the receiver from the stack.
3641     // +1 ~ return address
3642     __ movq(rax, Operand(rsp, (argc_ + 1) * kPointerSize));
3643     // Call as function is indicated with the hole.
3644     __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
3645     __ j(not_equal, &call, Label::kNear);
3646     // Patch the receiver on the stack with the global receiver object.
3647     __ movq(rbx, GlobalObjectOperand());
3648     __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
3649     __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rbx);
3650     __ bind(&call);
3651   }
3652
3653   // Check that the function really is a JavaScript function.
3654   __ JumpIfSmi(rdi, &non_function);
3655   // Goto slow case if we do not have a function.
3656   __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
3657   __ j(not_equal, &slow);
3658
3659   // Fast-case: Just invoke the function.
3660   ParameterCount actual(argc_);
3661
3662   if (ReceiverMightBeImplicit()) {
3663     Label call_as_function;
3664     __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
3665     __ j(equal, &call_as_function);
3666     __ InvokeFunction(rdi,
3667                       actual,
3668                       JUMP_FUNCTION,
3669                       NullCallWrapper(),
3670                       CALL_AS_METHOD);
3671     __ bind(&call_as_function);
3672   }
3673   __ InvokeFunction(rdi,
3674                     actual,
3675                     JUMP_FUNCTION,
3676                     NullCallWrapper(),
3677                     CALL_AS_FUNCTION);
3678
3679   // Slow-case: Non-function called.
3680   __ bind(&slow);
3681   // Check for function proxy.
3682   __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
3683   __ j(not_equal, &non_function);
3684   __ pop(rcx);
3685   __ push(rdi);  // put proxy as additional argument under return address
3686   __ push(rcx);
3687   __ Set(rax, argc_ + 1);
3688   __ Set(rbx, 0);
3689   __ SetCallKind(rcx, CALL_AS_METHOD);
3690   __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
3691   {
3692     Handle<Code> adaptor =
3693       masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
3694     __ jmp(adaptor, RelocInfo::CODE_TARGET);
3695   }
3696
3697   // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
3698   // of the original receiver from the call site).
3699   __ bind(&non_function);
3700   __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdi);
3701   __ Set(rax, argc_);
3702   __ Set(rbx, 0);
3703   __ SetCallKind(rcx, CALL_AS_METHOD);
3704   __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
3705   Handle<Code> adaptor =
3706       Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline();
3707   __ Jump(adaptor, RelocInfo::CODE_TARGET);
3708 }
3709
3710
3711 void CallConstructStub::Generate(MacroAssembler* masm) {
3712   // rax : number of arguments
3713   // rbx : cache cell for call target
3714   // rdi : constructor function
3715   Label slow, non_function_call;
3716
3717   // Check that function is not a smi.
3718   __ JumpIfSmi(rdi, &non_function_call);
3719   // Check that function is a JSFunction.
3720   __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
3721   __ j(not_equal, &slow);
3722
3723   if (RecordCallTarget()) {
3724     GenerateRecordCallTarget(masm);
3725   }
3726
3727   // Jump to the function-specific construct stub.
3728   __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
3729   __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kConstructStubOffset));
3730   __ lea(rbx, FieldOperand(rbx, Code::kHeaderSize));
3731   __ jmp(rbx);
3732
3733   // rdi: called object
3734   // rax: number of arguments
3735   // rcx: object map
3736   Label do_call;
3737   __ bind(&slow);
3738   __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
3739   __ j(not_equal, &non_function_call);
3740   __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
3741   __ jmp(&do_call);
3742
3743   __ bind(&non_function_call);
3744   __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
3745   __ bind(&do_call);
3746   // Set expected number of arguments to zero (not changing rax).
3747   __ Set(rbx, 0);
3748   __ SetCallKind(rcx, CALL_AS_METHOD);
3749   __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
3750           RelocInfo::CODE_TARGET);
3751 }
3752
3753
3754 bool CEntryStub::NeedsImmovableCode() {
3755   return false;
3756 }
3757
3758
3759 bool CEntryStub::IsPregenerated() {
3760 #ifdef _WIN64
3761   return result_size_ == 1;
3762 #else
3763   return true;
3764 #endif
3765 }
3766
3767
3768 void CodeStub::GenerateStubsAheadOfTime() {
3769   CEntryStub::GenerateAheadOfTime();
3770   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime();
3771   // It is important that the store buffer overflow stubs are generated first.
3772   RecordWriteStub::GenerateFixedRegStubsAheadOfTime();
3773 }
3774
3775
3776 void CodeStub::GenerateFPStubs() {
3777 }
3778
3779
3780 void CEntryStub::GenerateAheadOfTime() {
3781   CEntryStub stub(1, kDontSaveFPRegs);
3782   stub.GetCode()->set_is_pregenerated(true);
3783   CEntryStub save_doubles(1, kSaveFPRegs);
3784   save_doubles.GetCode()->set_is_pregenerated(true);
3785 }
3786
3787
3788 void CEntryStub::GenerateCore(MacroAssembler* masm,
3789                               Label* throw_normal_exception,
3790                               Label* throw_termination_exception,
3791                               Label* throw_out_of_memory_exception,
3792                               bool do_gc,
3793                               bool always_allocate_scope) {
3794   // rax: result parameter for PerformGC, if any.
3795   // rbx: pointer to C function  (C callee-saved).
3796   // rbp: frame pointer  (restored after C call).
3797   // rsp: stack pointer  (restored after C call).
3798   // r14: number of arguments including receiver (C callee-saved).
3799   // r15: pointer to the first argument (C callee-saved).
3800   //      This pointer is reused in LeaveExitFrame(), so it is stored in a
3801   //      callee-saved register.
3802
3803   // Simple results returned in rax (both AMD64 and Win64 calling conventions).
3804   // Complex results must be written to address passed as first argument.
3805   // AMD64 calling convention: a struct of two pointers in rax+rdx
3806
3807   // Check stack alignment.
3808   if (FLAG_debug_code) {
3809     __ CheckStackAlignment();
3810   }
3811
3812   if (do_gc) {
3813     // Pass failure code returned from last attempt as first argument to
3814     // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the
3815     // stack is known to be aligned. This function takes one argument which is
3816     // passed in register.
3817 #ifdef _WIN64
3818     __ movq(rcx, rax);
3819 #else  // _WIN64
3820     __ movq(rdi, rax);
3821 #endif
3822     __ movq(kScratchRegister,
3823             FUNCTION_ADDR(Runtime::PerformGC),
3824             RelocInfo::RUNTIME_ENTRY);
3825     __ call(kScratchRegister);
3826   }
3827
3828   ExternalReference scope_depth =
3829       ExternalReference::heap_always_allocate_scope_depth(masm->isolate());
3830   if (always_allocate_scope) {
3831     Operand scope_depth_operand = masm->ExternalOperand(scope_depth);
3832     __ incl(scope_depth_operand);
3833   }
3834
3835   // Call C function.
3836 #ifdef _WIN64
3837   // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9
3838   // Store Arguments object on stack, below the 4 WIN64 ABI parameter slots.
3839   __ movq(StackSpaceOperand(0), r14);  // argc.
3840   __ movq(StackSpaceOperand(1), r15);  // argv.
3841   if (result_size_ < 2) {
3842     // Pass a pointer to the Arguments object as the first argument.
3843     // Return result in single register (rax).
3844     __ lea(rcx, StackSpaceOperand(0));
3845     __ LoadAddress(rdx, ExternalReference::isolate_address());
3846   } else {
3847     ASSERT_EQ(2, result_size_);
3848     // Pass a pointer to the result location as the first argument.
3849     __ lea(rcx, StackSpaceOperand(2));
3850     // Pass a pointer to the Arguments object as the second argument.
3851     __ lea(rdx, StackSpaceOperand(0));
3852     __ LoadAddress(r8, ExternalReference::isolate_address());
3853   }
3854
3855 #else  // _WIN64
3856   // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9.
3857   __ movq(rdi, r14);  // argc.
3858   __ movq(rsi, r15);  // argv.
3859   __ movq(rdx, ExternalReference::isolate_address());
3860 #endif
3861   __ call(rbx);
3862   // Result is in rax - do not destroy this register!
3863
3864   if (always_allocate_scope) {
3865     Operand scope_depth_operand = masm->ExternalOperand(scope_depth);
3866     __ decl(scope_depth_operand);
3867   }
3868
3869   // Check for failure result.
3870   Label failure_returned;
3871   STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
3872 #ifdef _WIN64
3873   // If return value is on the stack, pop it to registers.
3874   if (result_size_ > 1) {
3875     ASSERT_EQ(2, result_size_);
3876     // Read result values stored on stack. Result is stored
3877     // above the four argument mirror slots and the two
3878     // Arguments object slots.
3879     __ movq(rax, Operand(rsp, 6 * kPointerSize));
3880     __ movq(rdx, Operand(rsp, 7 * kPointerSize));
3881   }
3882 #endif
3883   __ lea(rcx, Operand(rax, 1));
3884   // Lower 2 bits of rcx are 0 iff rax has failure tag.
3885   __ testl(rcx, Immediate(kFailureTagMask));
3886   __ j(zero, &failure_returned);
3887
3888   // Exit the JavaScript to C++ exit frame.
3889   __ LeaveExitFrame(save_doubles_);
3890   __ ret(0);
3891
3892   // Handling of failure.
3893   __ bind(&failure_returned);
3894
3895   Label retry;
3896   // If the returned exception is RETRY_AFTER_GC continue at retry label
3897   STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
3898   __ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
3899   __ j(zero, &retry, Label::kNear);
3900
3901   // Special handling of out of memory exceptions.
3902   __ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE);
3903   __ cmpq(rax, kScratchRegister);
3904   __ j(equal, throw_out_of_memory_exception);
3905
3906   // Retrieve the pending exception and clear the variable.
3907   ExternalReference pending_exception_address(
3908       Isolate::kPendingExceptionAddress, masm->isolate());
3909   Operand pending_exception_operand =
3910       masm->ExternalOperand(pending_exception_address);
3911   __ movq(rax, pending_exception_operand);
3912   __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
3913   __ movq(pending_exception_operand, rdx);
3914
3915   // Special handling of termination exceptions which are uncatchable
3916   // by javascript code.
3917   __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex);
3918   __ j(equal, throw_termination_exception);
3919
3920   // Handle normal exception.
3921   __ jmp(throw_normal_exception);
3922
3923   // Retry.
3924   __ bind(&retry);
3925 }
3926
3927
3928 void CEntryStub::Generate(MacroAssembler* masm) {
3929   // rax: number of arguments including receiver
3930   // rbx: pointer to C function  (C callee-saved)
3931   // rbp: frame pointer of calling JS frame (restored after C call)
3932   // rsp: stack pointer  (restored after C call)
3933   // rsi: current context (restored)
3934
3935   // NOTE: Invocations of builtins may return failure objects
3936   // instead of a proper result. The builtin entry handles
3937   // this by performing a garbage collection and retrying the
3938   // builtin once.
3939
3940   // Enter the exit frame that transitions from JavaScript to C++.
3941 #ifdef _WIN64
3942   int arg_stack_space = (result_size_ < 2 ? 2 : 4);
3943 #else
3944   int arg_stack_space = 0;
3945 #endif
3946   __ EnterExitFrame(arg_stack_space, save_doubles_);
3947
3948   // rax: Holds the context at this point, but should not be used.
3949   //      On entry to code generated by GenerateCore, it must hold
3950   //      a failure result if the collect_garbage argument to GenerateCore
3951   //      is true.  This failure result can be the result of code
3952   //      generated by a previous call to GenerateCore.  The value
3953   //      of rax is then passed to Runtime::PerformGC.
3954   // rbx: pointer to builtin function  (C callee-saved).
3955   // rbp: frame pointer of exit frame  (restored after C call).
3956   // rsp: stack pointer (restored after C call).
3957   // r14: number of arguments including receiver (C callee-saved).
3958   // r15: argv pointer (C callee-saved).
3959
3960   Label throw_normal_exception;
3961   Label throw_termination_exception;
3962   Label throw_out_of_memory_exception;
3963
3964   // Call into the runtime system.
3965   GenerateCore(masm,
3966                &throw_normal_exception,
3967                &throw_termination_exception,
3968                &throw_out_of_memory_exception,
3969                false,
3970                false);
3971
3972   // Do space-specific GC and retry runtime call.
3973   GenerateCore(masm,
3974                &throw_normal_exception,
3975                &throw_termination_exception,
3976                &throw_out_of_memory_exception,
3977                true,
3978                false);
3979
3980   // Do full GC and retry runtime call one final time.
3981   Failure* failure = Failure::InternalError();
3982   __ movq(rax, failure, RelocInfo::NONE);
3983   GenerateCore(masm,
3984                &throw_normal_exception,
3985                &throw_termination_exception,
3986                &throw_out_of_memory_exception,
3987                true,
3988                true);
3989
3990   __ bind(&throw_out_of_memory_exception);
3991   // Set external caught exception to false.
3992   Isolate* isolate = masm->isolate();
3993   ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress,
3994                                     isolate);
3995   __ Set(rax, static_cast<int64_t>(false));
3996   __ Store(external_caught, rax);
3997
3998   // Set pending exception and rax to out of memory exception.
3999   ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
4000                                       isolate);
4001   __ movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE);
4002   __ Store(pending_exception, rax);
4003   // Fall through to the next label.
4004
4005   __ bind(&throw_termination_exception);
4006   __ ThrowUncatchable(rax);
4007
4008   __ bind(&throw_normal_exception);
4009   __ Throw(rax);
4010 }
4011
4012
4013 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
4014   Label invoke, handler_entry, exit;
4015   Label not_outermost_js, not_outermost_js_2;
4016   {  // NOLINT. Scope block confuses linter.
4017     MacroAssembler::NoRootArrayScope uninitialized_root_register(masm);
4018     // Set up frame.
4019     __ push(rbp);
4020     __ movq(rbp, rsp);
4021
4022     // Push the stack frame type marker twice.
4023     int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
4024     // Scratch register is neither callee-save, nor an argument register on any
4025     // platform. It's free to use at this point.
4026     // Cannot use smi-register for loading yet.
4027     __ movq(kScratchRegister,
4028             reinterpret_cast<uint64_t>(Smi::FromInt(marker)),
4029             RelocInfo::NONE);
4030     __ push(kScratchRegister);  // context slot
4031     __ push(kScratchRegister);  // function slot
4032     // Save callee-saved registers (X64/Win64 calling conventions).
4033     __ push(r12);
4034     __ push(r13);
4035     __ push(r14);
4036     __ push(r15);
4037 #ifdef _WIN64
4038     __ push(rdi);  // Only callee save in Win64 ABI, argument in AMD64 ABI.
4039     __ push(rsi);  // Only callee save in Win64 ABI, argument in AMD64 ABI.
4040 #endif
4041     __ push(rbx);
4042     // TODO(X64): On Win64, if we ever use XMM6-XMM15, the low low 64 bits are
4043     // callee save as well.
4044
4045     // Set up the roots and smi constant registers.
4046     // Needs to be done before any further smi loads.
4047     __ InitializeSmiConstantRegister();
4048     __ InitializeRootRegister();
4049   }
4050
4051   Isolate* isolate = masm->isolate();
4052
4053   // Save copies of the top frame descriptor on the stack.
4054   ExternalReference c_entry_fp(Isolate::kCEntryFPAddress, isolate);
4055   {
4056     Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp);
4057     __ push(c_entry_fp_operand);
4058   }
4059
4060   // If this is the outermost JS call, set js_entry_sp value.
4061   ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate);
4062   __ Load(rax, js_entry_sp);
4063   __ testq(rax, rax);
4064   __ j(not_zero, &not_outermost_js);
4065   __ Push(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
4066   __ movq(rax, rbp);
4067   __ Store(js_entry_sp, rax);
4068   Label cont;
4069   __ jmp(&cont);
4070   __ bind(&not_outermost_js);
4071   __ Push(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME));
4072   __ bind(&cont);
4073
4074   // Jump to a faked try block that does the invoke, with a faked catch
4075   // block that sets the pending exception.
4076   __ jmp(&invoke);
4077   __ bind(&handler_entry);
4078   handler_offset_ = handler_entry.pos();
4079   // Caught exception: Store result (exception) in the pending exception
4080   // field in the JSEnv and return a failure sentinel.
4081   ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
4082                                       isolate);
4083   __ Store(pending_exception, rax);
4084   __ movq(rax, Failure::Exception(), RelocInfo::NONE);
4085   __ jmp(&exit);
4086
4087   // Invoke: Link this frame into the handler chain.  There's only one
4088   // handler block in this code object, so its index is 0.
4089   __ bind(&invoke);
4090   __ PushTryHandler(StackHandler::JS_ENTRY, 0);
4091
4092   // Clear any pending exceptions.
4093   __ LoadRoot(rax, Heap::kTheHoleValueRootIndex);
4094   __ Store(pending_exception, rax);
4095
4096   // Fake a receiver (NULL).
4097   __ push(Immediate(0));  // receiver
4098
4099   // Invoke the function by calling through JS entry trampoline builtin and
4100   // pop the faked function when we return. We load the address from an
4101   // external reference instead of inlining the call target address directly
4102   // in the code, because the builtin stubs may not have been generated yet
4103   // at the time this code is generated.
4104   if (is_construct) {
4105     ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
4106                                       isolate);
4107     __ Load(rax, construct_entry);
4108   } else {
4109     ExternalReference entry(Builtins::kJSEntryTrampoline, isolate);
4110     __ Load(rax, entry);
4111   }
4112   __ lea(kScratchRegister, FieldOperand(rax, Code::kHeaderSize));
4113   __ call(kScratchRegister);
4114
4115   // Unlink this frame from the handler chain.
4116   __ PopTryHandler();
4117
4118   __ bind(&exit);
4119   // Check if the current stack frame is marked as the outermost JS frame.
4120   __ pop(rbx);
4121   __ Cmp(rbx, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
4122   __ j(not_equal, &not_outermost_js_2);
4123   __ movq(kScratchRegister, js_entry_sp);
4124   __ movq(Operand(kScratchRegister, 0), Immediate(0));
4125   __ bind(&not_outermost_js_2);
4126
4127   // Restore the top frame descriptor from the stack.
4128   { Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp);
4129     __ pop(c_entry_fp_operand);
4130   }
4131
4132   // Restore callee-saved registers (X64 conventions).
4133   __ pop(rbx);
4134 #ifdef _WIN64
4135   // Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI.
4136   __ pop(rsi);
4137   __ pop(rdi);
4138 #endif
4139   __ pop(r15);
4140   __ pop(r14);
4141   __ pop(r13);
4142   __ pop(r12);
4143   __ addq(rsp, Immediate(2 * kPointerSize));  // remove markers
4144
4145   // Restore frame pointer and return.
4146   __ pop(rbp);
4147   __ ret(0);
4148 }
4149
4150
4151 void InstanceofStub::Generate(MacroAssembler* masm) {
4152   // Implements "value instanceof function" operator.
4153   // Expected input state with no inline cache:
4154   //   rsp[0] : return address
4155   //   rsp[1] : function pointer
4156   //   rsp[2] : value
4157   // Expected input state with an inline one-element cache:
4158   //   rsp[0] : return address
4159   //   rsp[1] : offset from return address to location of inline cache
4160   //   rsp[2] : function pointer
4161   //   rsp[3] : value
4162   // Returns a bitwise zero to indicate that the value
4163   // is and instance of the function and anything else to
4164   // indicate that the value is not an instance.
4165
4166   static const int kOffsetToMapCheckValue = 2;
4167   static const int kOffsetToResultValue = 18;
4168   // The last 4 bytes of the instruction sequence
4169   //   movq(rdi, FieldOperand(rax, HeapObject::kMapOffset))
4170   //   Move(kScratchRegister, FACTORY->the_hole_value())
4171   // in front of the hole value address.
4172   static const unsigned int kWordBeforeMapCheckValue = 0xBA49FF78;
4173   // The last 4 bytes of the instruction sequence
4174   //   __ j(not_equal, &cache_miss);
4175   //   __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex);
4176   // before the offset of the hole value in the root array.
4177   static const unsigned int kWordBeforeResultValue = 0x458B4909;
4178   // Only the inline check flag is supported on X64.
4179   ASSERT(flags_ == kNoFlags || HasCallSiteInlineCheck());
4180   int extra_stack_space = HasCallSiteInlineCheck() ? kPointerSize : 0;
4181
4182   // Get the object - go slow case if it's a smi.
4183   Label slow;
4184
4185   __ movq(rax, Operand(rsp, 2 * kPointerSize + extra_stack_space));
4186   __ JumpIfSmi(rax, &slow);
4187
4188   // Check that the left hand is a JS object. Leave its map in rax.
4189   __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax);
4190   __ j(below, &slow);
4191   __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE);
4192   __ j(above, &slow);
4193
4194   // Get the prototype of the function.
4195   __ movq(rdx, Operand(rsp, 1 * kPointerSize + extra_stack_space));
4196   // rdx is function, rax is map.
4197
4198   // If there is a call site cache don't look in the global cache, but do the
4199   // real lookup and update the call site cache.
4200   if (!HasCallSiteInlineCheck()) {
4201     // Look up the function and the map in the instanceof cache.
4202     Label miss;
4203     __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
4204     __ j(not_equal, &miss, Label::kNear);
4205     __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex);
4206     __ j(not_equal, &miss, Label::kNear);
4207     __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
4208     __ ret(2 * kPointerSize);
4209     __ bind(&miss);
4210   }
4211
4212   __ TryGetFunctionPrototype(rdx, rbx, &slow, true);
4213
4214   // Check that the function prototype is a JS object.
4215   __ JumpIfSmi(rbx, &slow);
4216   __ CmpObjectType(rbx, FIRST_SPEC_OBJECT_TYPE, kScratchRegister);
4217   __ j(below, &slow);
4218   __ CmpInstanceType(kScratchRegister, LAST_SPEC_OBJECT_TYPE);
4219   __ j(above, &slow);
4220
4221   // Register mapping:
4222   //   rax is object map.
4223   //   rdx is function.
4224   //   rbx is function prototype.
4225   if (!HasCallSiteInlineCheck()) {
4226     __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
4227     __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex);
4228   } else {
4229     // Get return address and delta to inlined map check.
4230     __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize));
4231     __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize));
4232     if (FLAG_debug_code) {
4233       __ movl(rdi, Immediate(kWordBeforeMapCheckValue));
4234       __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi);
4235       __ Assert(equal, "InstanceofStub unexpected call site cache (check).");
4236     }
4237     __ movq(kScratchRegister,
4238             Operand(kScratchRegister, kOffsetToMapCheckValue));
4239     __ movq(Operand(kScratchRegister, 0), rax);
4240   }
4241
4242   __ movq(rcx, FieldOperand(rax, Map::kPrototypeOffset));
4243
4244   // Loop through the prototype chain looking for the function prototype.
4245   Label loop, is_instance, is_not_instance;
4246   __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex);
4247   __ bind(&loop);
4248   __ cmpq(rcx, rbx);
4249   __ j(equal, &is_instance, Label::kNear);
4250   __ cmpq(rcx, kScratchRegister);
4251   // The code at is_not_instance assumes that kScratchRegister contains a
4252   // non-zero GCable value (the null object in this case).
4253   __ j(equal, &is_not_instance, Label::kNear);
4254   __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
4255   __ movq(rcx, FieldOperand(rcx, Map::kPrototypeOffset));
4256   __ jmp(&loop);
4257
4258   __ bind(&is_instance);
4259   if (!HasCallSiteInlineCheck()) {
4260     __ xorl(rax, rax);
4261     // Store bitwise zero in the cache.  This is a Smi in GC terms.
4262     STATIC_ASSERT(kSmiTag == 0);
4263     __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
4264   } else {
4265     // Store offset of true in the root array at the inline check site.
4266     int true_offset = 0x100 +
4267         (Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias;
4268     // Assert it is a 1-byte signed value.
4269     ASSERT(true_offset >= 0 && true_offset < 0x100);
4270     __ movl(rax, Immediate(true_offset));
4271     __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize));
4272     __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize));
4273     __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax);
4274     if (FLAG_debug_code) {
4275       __ movl(rax, Immediate(kWordBeforeResultValue));
4276       __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
4277       __ Assert(equal, "InstanceofStub unexpected call site cache (mov).");
4278     }
4279     __ Set(rax, 0);
4280   }
4281   __ ret(2 * kPointerSize + extra_stack_space);
4282
4283   __ bind(&is_not_instance);
4284   if (!HasCallSiteInlineCheck()) {
4285     // We have to store a non-zero value in the cache.
4286     __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex);
4287   } else {
4288     // Store offset of false in the root array at the inline check site.
4289     int false_offset = 0x100 +
4290         (Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias;
4291     // Assert it is a 1-byte signed value.
4292     ASSERT(false_offset >= 0 && false_offset < 0x100);
4293     __ movl(rax, Immediate(false_offset));
4294     __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize));
4295     __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize));
4296     __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax);
4297     if (FLAG_debug_code) {
4298       __ movl(rax, Immediate(kWordBeforeResultValue));
4299       __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
4300       __ Assert(equal, "InstanceofStub unexpected call site cache (mov)");
4301     }
4302   }
4303   __ ret(2 * kPointerSize + extra_stack_space);
4304
4305   // Slow-case: Go through the JavaScript implementation.
4306   __ bind(&slow);
4307   if (HasCallSiteInlineCheck()) {
4308     // Remove extra value from the stack.
4309     __ pop(rcx);
4310     __ pop(rax);
4311     __ push(rcx);
4312   }
4313   __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
4314 }
4315
4316
4317 // Passing arguments in registers is not supported.
4318 Register InstanceofStub::left() { return no_reg; }
4319
4320
4321 Register InstanceofStub::right() { return no_reg; }
4322
4323
4324 int CompareStub::MinorKey() {
4325   // Encode the three parameters in a unique 16 bit value. To avoid duplicate
4326   // stubs the never NaN NaN condition is only taken into account if the
4327   // condition is equals.
4328   ASSERT(static_cast<unsigned>(cc_) < (1 << 12));
4329   ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
4330   return ConditionField::encode(static_cast<unsigned>(cc_))
4331          | RegisterField::encode(false)    // lhs_ and rhs_ are not used
4332          | StrictField::encode(strict_)
4333          | NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false)
4334          | IncludeNumberCompareField::encode(include_number_compare_)
4335          | IncludeSmiCompareField::encode(include_smi_compare_);
4336 }
4337
4338
4339 // Unfortunately you have to run without snapshots to see most of these
4340 // names in the profile since most compare stubs end up in the snapshot.
4341 void CompareStub::PrintName(StringStream* stream) {
4342   ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
4343   const char* cc_name;
4344   switch (cc_) {
4345     case less: cc_name = "LT"; break;
4346     case greater: cc_name = "GT"; break;
4347     case less_equal: cc_name = "LE"; break;
4348     case greater_equal: cc_name = "GE"; break;
4349     case equal: cc_name = "EQ"; break;
4350     case not_equal: cc_name = "NE"; break;
4351     default: cc_name = "UnknownCondition"; break;
4352   }
4353   bool is_equality = cc_ == equal || cc_ == not_equal;
4354   stream->Add("CompareStub_%s", cc_name);
4355   if (strict_ && is_equality) stream->Add("_STRICT");
4356   if (never_nan_nan_ && is_equality) stream->Add("_NO_NAN");
4357   if (!include_number_compare_) stream->Add("_NO_NUMBER");
4358   if (!include_smi_compare_) stream->Add("_NO_SMI");
4359 }
4360
4361
4362 // -------------------------------------------------------------------------
4363 // StringCharCodeAtGenerator
4364
4365 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
4366   Label flat_string;
4367   Label ascii_string;
4368   Label got_char_code;
4369   Label sliced_string;
4370
4371   // If the receiver is a smi trigger the non-string case.
4372   __ JumpIfSmi(object_, receiver_not_string_);
4373
4374   // Fetch the instance type of the receiver into result register.
4375   __ movq(result_, FieldOperand(object_, HeapObject::kMapOffset));
4376   __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
4377   // If the receiver is not a string trigger the non-string case.
4378   __ testb(result_, Immediate(kIsNotStringMask));
4379   __ j(not_zero, receiver_not_string_);
4380
4381   // If the index is non-smi trigger the non-smi case.
4382   __ JumpIfNotSmi(index_, &index_not_smi_);
4383   __ bind(&got_smi_index_);
4384
4385   // Check for index out of range.
4386   __ SmiCompare(index_, FieldOperand(object_, String::kLengthOffset));
4387   __ j(above_equal, index_out_of_range_);
4388
4389   __ SmiToInteger32(index_, index_);
4390
4391   StringCharLoadGenerator::Generate(
4392       masm, object_, index_, result_, &call_runtime_);
4393
4394   __ Integer32ToSmi(result_, result_);
4395   __ bind(&exit_);
4396 }
4397
4398
4399 void StringCharCodeAtGenerator::GenerateSlow(
4400     MacroAssembler* masm,
4401     const RuntimeCallHelper& call_helper) {
4402   __ Abort("Unexpected fallthrough to CharCodeAt slow case");
4403
4404   Factory* factory = masm->isolate()->factory();
4405   // Index is not a smi.
4406   __ bind(&index_not_smi_);
4407   // If index is a heap number, try converting it to an integer.
4408   __ CheckMap(index_,
4409               factory->heap_number_map(),
4410               index_not_number_,
4411               DONT_DO_SMI_CHECK);
4412   call_helper.BeforeCall(masm);
4413   __ push(object_);
4414   __ push(index_);  // Consumed by runtime conversion function.
4415   if (index_flags_ == STRING_INDEX_IS_NUMBER) {
4416     __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
4417   } else {
4418     ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
4419     // NumberToSmi discards numbers that are not exact integers.
4420     __ CallRuntime(Runtime::kNumberToSmi, 1);
4421   }
4422   if (!index_.is(rax)) {
4423     // Save the conversion result before the pop instructions below
4424     // have a chance to overwrite it.
4425     __ movq(index_, rax);
4426   }
4427   __ pop(object_);
4428   // Reload the instance type.
4429   __ movq(result_, FieldOperand(object_, HeapObject::kMapOffset));
4430   __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
4431   call_helper.AfterCall(masm);
4432   // If index is still not a smi, it must be out of range.
4433   __ JumpIfNotSmi(index_, index_out_of_range_);
4434   // Otherwise, return to the fast path.
4435   __ jmp(&got_smi_index_);
4436
4437   // Call runtime. We get here when the receiver is a string and the
4438   // index is a number, but the code of getting the actual character
4439   // is too complex (e.g., when the string needs to be flattened).
4440   __ bind(&call_runtime_);
4441   call_helper.BeforeCall(masm);
4442   __ push(object_);
4443   __ Integer32ToSmi(index_, index_);
4444   __ push(index_);
4445   __ CallRuntime(Runtime::kStringCharCodeAt, 2);
4446   if (!result_.is(rax)) {
4447     __ movq(result_, rax);
4448   }
4449   call_helper.AfterCall(masm);
4450   __ jmp(&exit_);
4451
4452   __ Abort("Unexpected fallthrough from CharCodeAt slow case");
4453 }
4454
4455
4456 // -------------------------------------------------------------------------
4457 // StringCharFromCodeGenerator
4458
4459 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
4460   // Fast case of Heap::LookupSingleCharacterStringFromCode.
4461   __ JumpIfNotSmi(code_, &slow_case_);
4462   __ SmiCompare(code_, Smi::FromInt(String::kMaxAsciiCharCode));
4463   __ j(above, &slow_case_);
4464
4465   __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
4466   SmiIndex index = masm->SmiToIndex(kScratchRegister, code_, kPointerSizeLog2);
4467   __ movq(result_, FieldOperand(result_, index.reg, index.scale,
4468                                 FixedArray::kHeaderSize));
4469   __ CompareRoot(result_, Heap::kUndefinedValueRootIndex);
4470   __ j(equal, &slow_case_);
4471   __ bind(&exit_);
4472 }
4473
4474
4475 void StringCharFromCodeGenerator::GenerateSlow(
4476     MacroAssembler* masm,
4477     const RuntimeCallHelper& call_helper) {
4478   __ Abort("Unexpected fallthrough to CharFromCode slow case");
4479
4480   __ bind(&slow_case_);
4481   call_helper.BeforeCall(masm);
4482   __ push(code_);
4483   __ CallRuntime(Runtime::kCharFromCode, 1);
4484   if (!result_.is(rax)) {
4485     __ movq(result_, rax);
4486   }
4487   call_helper.AfterCall(masm);
4488   __ jmp(&exit_);
4489
4490   __ Abort("Unexpected fallthrough from CharFromCode slow case");
4491 }
4492
4493
4494 // -------------------------------------------------------------------------
4495 // StringCharAtGenerator
4496
4497 void StringCharAtGenerator::GenerateFast(MacroAssembler* masm) {
4498   char_code_at_generator_.GenerateFast(masm);
4499   char_from_code_generator_.GenerateFast(masm);
4500 }
4501
4502
4503 void StringCharAtGenerator::GenerateSlow(
4504     MacroAssembler* masm,
4505     const RuntimeCallHelper& call_helper) {
4506   char_code_at_generator_.GenerateSlow(masm, call_helper);
4507   char_from_code_generator_.GenerateSlow(masm, call_helper);
4508 }
4509
4510
4511 void StringAddStub::Generate(MacroAssembler* masm) {
4512   Label call_runtime, call_builtin;
4513   Builtins::JavaScript builtin_id = Builtins::ADD;
4514
4515   // Load the two arguments.
4516   __ movq(rax, Operand(rsp, 2 * kPointerSize));  // First argument (left).
4517   __ movq(rdx, Operand(rsp, 1 * kPointerSize));  // Second argument (right).
4518
4519   // Make sure that both arguments are strings if not known in advance.
4520   if (flags_ == NO_STRING_ADD_FLAGS) {
4521     __ JumpIfSmi(rax, &call_runtime);
4522     __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8);
4523     __ j(above_equal, &call_runtime);
4524
4525     // First argument is a a string, test second.
4526     __ JumpIfSmi(rdx, &call_runtime);
4527     __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9);
4528     __ j(above_equal, &call_runtime);
4529   } else {
4530     // Here at least one of the arguments is definitely a string.
4531     // We convert the one that is not known to be a string.
4532     if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) {
4533       ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0);
4534       GenerateConvertArgument(masm, 2 * kPointerSize, rax, rbx, rcx, rdi,
4535                               &call_builtin);
4536       builtin_id = Builtins::STRING_ADD_RIGHT;
4537     } else if ((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) == 0) {
4538       ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0);
4539       GenerateConvertArgument(masm, 1 * kPointerSize, rdx, rbx, rcx, rdi,
4540                               &call_builtin);
4541       builtin_id = Builtins::STRING_ADD_LEFT;
4542     }
4543   }
4544
4545   // Both arguments are strings.
4546   // rax: first string
4547   // rdx: second string
4548   // Check if either of the strings are empty. In that case return the other.
4549   Label second_not_zero_length, both_not_zero_length;
4550   __ movq(rcx, FieldOperand(rdx, String::kLengthOffset));
4551   __ SmiTest(rcx);
4552   __ j(not_zero, &second_not_zero_length, Label::kNear);
4553   // Second string is empty, result is first string which is already in rax.
4554   Counters* counters = masm->isolate()->counters();
4555   __ IncrementCounter(counters->string_add_native(), 1);
4556   __ ret(2 * kPointerSize);
4557   __ bind(&second_not_zero_length);
4558   __ movq(rbx, FieldOperand(rax, String::kLengthOffset));
4559   __ SmiTest(rbx);
4560   __ j(not_zero, &both_not_zero_length, Label::kNear);
4561   // First string is empty, result is second string which is in rdx.
4562   __ movq(rax, rdx);
4563   __ IncrementCounter(counters->string_add_native(), 1);
4564   __ ret(2 * kPointerSize);
4565
4566   // Both strings are non-empty.
4567   // rax: first string
4568   // rbx: length of first string
4569   // rcx: length of second string
4570   // rdx: second string
4571   // r8: map of first string (if flags_ == NO_STRING_ADD_FLAGS)
4572   // r9: map of second string (if flags_ == NO_STRING_ADD_FLAGS)
4573   Label string_add_flat_result, longer_than_two;
4574   __ bind(&both_not_zero_length);
4575
4576   // If arguments where known to be strings, maps are not loaded to r8 and r9
4577   // by the code above.
4578   if (flags_ != NO_STRING_ADD_FLAGS) {
4579     __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset));
4580     __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset));
4581   }
4582   // Get the instance types of the two strings as they will be needed soon.
4583   __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset));
4584   __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset));
4585
4586   // Look at the length of the result of adding the two strings.
4587   STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue / 2);
4588   __ SmiAdd(rbx, rbx, rcx);
4589   // Use the symbol table when adding two one character strings, as it
4590   // helps later optimizations to return a symbol here.
4591   __ SmiCompare(rbx, Smi::FromInt(2));
4592   __ j(not_equal, &longer_than_two);
4593
4594   // Check that both strings are non-external ASCII strings.
4595   __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx,
4596                                                   &call_runtime);
4597
4598   // Get the two characters forming the sub string.
4599   __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize));
4600   __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize));
4601
4602   // Try to lookup two character string in symbol table. If it is not found
4603   // just allocate a new one.
4604   Label make_two_character_string, make_flat_ascii_string;
4605   StringHelper::GenerateTwoCharacterSymbolTableProbe(
4606       masm, rbx, rcx, r14, r11, rdi, r15, &make_two_character_string);
4607   __ IncrementCounter(counters->string_add_native(), 1);
4608   __ ret(2 * kPointerSize);
4609
4610   __ bind(&make_two_character_string);
4611   __ Set(rdi, 2);
4612   __ AllocateAsciiString(rax, rdi, r8, r9, r11, &call_runtime);
4613   // rbx - first byte: first character
4614   // rbx - second byte: *maybe* second character
4615   // Make sure that the second byte of rbx contains the second character.
4616   __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize));
4617   __ shll(rcx, Immediate(kBitsPerByte));
4618   __ orl(rbx, rcx);
4619   // Write both characters to the new string.
4620   __ movw(FieldOperand(rax, SeqAsciiString::kHeaderSize), rbx);
4621   __ IncrementCounter(counters->string_add_native(), 1);
4622   __ ret(2 * kPointerSize);
4623
4624   __ bind(&longer_than_two);
4625   // Check if resulting string will be flat.
4626   __ SmiCompare(rbx, Smi::FromInt(ConsString::kMinLength));
4627   __ j(below, &string_add_flat_result);
4628   // Handle exceptionally long strings in the runtime system.
4629   STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0);
4630   __ SmiCompare(rbx, Smi::FromInt(String::kMaxLength));
4631   __ j(above, &call_runtime);
4632
4633   // If result is not supposed to be flat, allocate a cons string object. If
4634   // both strings are ASCII the result is an ASCII cons string.
4635   // rax: first string
4636   // rbx: length of resulting flat string
4637   // rdx: second string
4638   // r8: instance type of first string
4639   // r9: instance type of second string
4640   Label non_ascii, allocated, ascii_data;
4641   __ movl(rcx, r8);
4642   __ and_(rcx, r9);
4643   STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
4644   STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
4645   __ testl(rcx, Immediate(kStringEncodingMask));
4646   __ j(zero, &non_ascii);
4647   __ bind(&ascii_data);
4648   // Allocate an ASCII cons string.
4649   __ AllocateAsciiConsString(rcx, rdi, no_reg, &call_runtime);
4650   __ bind(&allocated);
4651   // Fill the fields of the cons string.
4652   __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx);
4653   __ movq(FieldOperand(rcx, ConsString::kHashFieldOffset),
4654           Immediate(String::kEmptyHashField));
4655   __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax);
4656   __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx);
4657   __ movq(rax, rcx);
4658   __ IncrementCounter(counters->string_add_native(), 1);
4659   __ ret(2 * kPointerSize);
4660   __ bind(&non_ascii);
4661   // At least one of the strings is two-byte. Check whether it happens
4662   // to contain only ASCII characters.
4663   // rcx: first instance type AND second instance type.
4664   // r8: first instance type.
4665   // r9: second instance type.
4666   __ testb(rcx, Immediate(kAsciiDataHintMask));
4667   __ j(not_zero, &ascii_data);
4668   __ xor_(r8, r9);
4669   STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0);
4670   __ andb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag));
4671   __ cmpb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag));
4672   __ j(equal, &ascii_data);
4673   // Allocate a two byte cons string.
4674   __ AllocateTwoByteConsString(rcx, rdi, no_reg, &call_runtime);
4675   __ jmp(&allocated);
4676
4677   // We cannot encounter sliced strings or cons strings here since:
4678   STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
4679   // Handle creating a flat result from either external or sequential strings.
4680   // Locate the first characters' locations.
4681   // rax: first string
4682   // rbx: length of resulting flat string as smi
4683   // rdx: second string
4684   // r8: instance type of first string
4685   // r9: instance type of first string
4686   Label first_prepared, second_prepared;
4687   Label first_is_sequential, second_is_sequential;
4688   __ bind(&string_add_flat_result);
4689
4690   __ SmiToInteger32(r14, FieldOperand(rax, SeqString::kLengthOffset));
4691   // r14: length of first string
4692   STATIC_ASSERT(kSeqStringTag == 0);
4693   __ testb(r8, Immediate(kStringRepresentationMask));
4694   __ j(zero, &first_is_sequential, Label::kNear);
4695   // Rule out short external string and load string resource.
4696   STATIC_ASSERT(kShortExternalStringTag != 0);
4697   __ testb(r8, Immediate(kShortExternalStringMask));
4698   __ j(not_zero, &call_runtime);
4699   __ movq(rcx, FieldOperand(rax, ExternalString::kResourceDataOffset));
4700   __ jmp(&first_prepared, Label::kNear);
4701   __ bind(&first_is_sequential);
4702   STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
4703   __ lea(rcx, FieldOperand(rax, SeqAsciiString::kHeaderSize));
4704   __ bind(&first_prepared);
4705
4706   // Check whether both strings have same encoding.
4707   __ xorl(r8, r9);
4708   __ testb(r8, Immediate(kStringEncodingMask));
4709   __ j(not_zero, &call_runtime);
4710
4711   __ SmiToInteger32(r15, FieldOperand(rdx, SeqString::kLengthOffset));
4712   // r15: length of second string
4713   STATIC_ASSERT(kSeqStringTag == 0);
4714   __ testb(r9, Immediate(kStringRepresentationMask));
4715   __ j(zero, &second_is_sequential, Label::kNear);
4716   // Rule out short external string and load string resource.
4717   STATIC_ASSERT(kShortExternalStringTag != 0);
4718   __ testb(r9, Immediate(kShortExternalStringMask));
4719   __ j(not_zero, &call_runtime);
4720   __ movq(rdx, FieldOperand(rdx, ExternalString::kResourceDataOffset));
4721   __ jmp(&second_prepared, Label::kNear);
4722   __ bind(&second_is_sequential);
4723   STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
4724   __ lea(rdx, FieldOperand(rdx, SeqAsciiString::kHeaderSize));
4725   __ bind(&second_prepared);
4726
4727   Label non_ascii_string_add_flat_result;
4728   // r9: instance type of second string
4729   // First string and second string have the same encoding.
4730   STATIC_ASSERT(kTwoByteStringTag == 0);
4731   __ SmiToInteger32(rbx, rbx);
4732   __ testb(r9, Immediate(kStringEncodingMask));
4733   __ j(zero, &non_ascii_string_add_flat_result);
4734
4735   __ bind(&make_flat_ascii_string);
4736   // Both strings are ASCII strings. As they are short they are both flat.
4737   __ AllocateAsciiString(rax, rbx, rdi, r8, r9, &call_runtime);
4738   // rax: result string
4739   // Locate first character of result.
4740   __ lea(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize));
4741   // rcx: first char of first string
4742   // rbx: first character of result
4743   // r14: length of first string
4744   StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, true);
4745   // rbx: next character of result
4746   // rdx: first char of second string
4747   // r15: length of second string
4748   StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, true);
4749   __ IncrementCounter(counters->string_add_native(), 1);
4750   __ ret(2 * kPointerSize);
4751
4752   __ bind(&non_ascii_string_add_flat_result);
4753   // Both strings are ASCII strings. As they are short they are both flat.
4754   __ AllocateTwoByteString(rax, rbx, rdi, r8, r9, &call_runtime);
4755   // rax: result string
4756   // Locate first character of result.
4757   __ lea(rbx, FieldOperand(rax, SeqTwoByteString::kHeaderSize));
4758   // rcx: first char of first string
4759   // rbx: first character of result
4760   // r14: length of first string
4761   StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, false);
4762   // rbx: next character of result
4763   // rdx: first char of second string
4764   // r15: length of second string
4765   StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, false);
4766   __ IncrementCounter(counters->string_add_native(), 1);
4767   __ ret(2 * kPointerSize);
4768
4769   // Just jump to runtime to add the two strings.
4770   __ bind(&call_runtime);
4771   __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
4772
4773   if (call_builtin.is_linked()) {
4774     __ bind(&call_builtin);
4775     __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
4776   }
4777 }
4778
4779
4780 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
4781                                             int stack_offset,
4782                                             Register arg,
4783                                             Register scratch1,
4784                                             Register scratch2,
4785                                             Register scratch3,
4786                                             Label* slow) {
4787   // First check if the argument is already a string.
4788   Label not_string, done;
4789   __ JumpIfSmi(arg, &not_string);
4790   __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1);
4791   __ j(below, &done);
4792
4793   // Check the number to string cache.
4794   Label not_cached;
4795   __ bind(&not_string);
4796   // Puts the cached result into scratch1.
4797   NumberToStringStub::GenerateLookupNumberStringCache(masm,
4798                                                       arg,
4799                                                       scratch1,
4800                                                       scratch2,
4801                                                       scratch3,
4802                                                       false,
4803                                                       &not_cached);
4804   __ movq(arg, scratch1);
4805   __ movq(Operand(rsp, stack_offset), arg);
4806   __ jmp(&done);
4807
4808   // Check if the argument is a safe string wrapper.
4809   __ bind(&not_cached);
4810   __ JumpIfSmi(arg, slow);
4811   __ CmpObjectType(arg, JS_VALUE_TYPE, scratch1);  // map -> scratch1.
4812   __ j(not_equal, slow);
4813   __ testb(FieldOperand(scratch1, Map::kBitField2Offset),
4814            Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
4815   __ j(zero, slow);
4816   __ movq(arg, FieldOperand(arg, JSValue::kValueOffset));
4817   __ movq(Operand(rsp, stack_offset), arg);
4818
4819   __ bind(&done);
4820 }
4821
4822
4823 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
4824                                           Register dest,
4825                                           Register src,
4826                                           Register count,
4827                                           bool ascii) {
4828   Label loop;
4829   __ bind(&loop);
4830   // This loop just copies one character at a time, as it is only used for very
4831   // short strings.
4832   if (ascii) {
4833     __ movb(kScratchRegister, Operand(src, 0));
4834     __ movb(Operand(dest, 0), kScratchRegister);
4835     __ incq(src);
4836     __ incq(dest);
4837   } else {
4838     __ movzxwl(kScratchRegister, Operand(src, 0));
4839     __ movw(Operand(dest, 0), kScratchRegister);
4840     __ addq(src, Immediate(2));
4841     __ addq(dest, Immediate(2));
4842   }
4843   __ decl(count);
4844   __ j(not_zero, &loop);
4845 }
4846
4847
4848 void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm,
4849                                              Register dest,
4850                                              Register src,
4851                                              Register count,
4852                                              bool ascii) {
4853   // Copy characters using rep movs of doublewords. Align destination on 4 byte
4854   // boundary before starting rep movs. Copy remaining characters after running
4855   // rep movs.
4856   // Count is positive int32, dest and src are character pointers.
4857   ASSERT(dest.is(rdi));  // rep movs destination
4858   ASSERT(src.is(rsi));  // rep movs source
4859   ASSERT(count.is(rcx));  // rep movs count
4860
4861   // Nothing to do for zero characters.
4862   Label done;
4863   __ testl(count, count);
4864   __ j(zero, &done, Label::kNear);
4865
4866   // Make count the number of bytes to copy.
4867   if (!ascii) {
4868     STATIC_ASSERT(2 == sizeof(uc16));
4869     __ addl(count, count);
4870   }
4871
4872   // Don't enter the rep movs if there are less than 4 bytes to copy.
4873   Label last_bytes;
4874   __ testl(count, Immediate(~7));
4875   __ j(zero, &last_bytes, Label::kNear);
4876
4877   // Copy from edi to esi using rep movs instruction.
4878   __ movl(kScratchRegister, count);
4879   __ shr(count, Immediate(3));  // Number of doublewords to copy.
4880   __ repmovsq();
4881
4882   // Find number of bytes left.
4883   __ movl(count, kScratchRegister);
4884   __ and_(count, Immediate(7));
4885
4886   // Check if there are more bytes to copy.
4887   __ bind(&last_bytes);
4888   __ testl(count, count);
4889   __ j(zero, &done, Label::kNear);
4890
4891   // Copy remaining characters.
4892   Label loop;
4893   __ bind(&loop);
4894   __ movb(kScratchRegister, Operand(src, 0));
4895   __ movb(Operand(dest, 0), kScratchRegister);
4896   __ incq(src);
4897   __ incq(dest);
4898   __ decl(count);
4899   __ j(not_zero, &loop);
4900
4901   __ bind(&done);
4902 }
4903
4904 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
4905                                                         Register c1,
4906                                                         Register c2,
4907                                                         Register scratch1,
4908                                                         Register scratch2,
4909                                                         Register scratch3,
4910                                                         Register scratch4,
4911                                                         Label* not_found) {
4912   // Register scratch3 is the general scratch register in this function.
4913   Register scratch = scratch3;
4914
4915   // Make sure that both characters are not digits as such strings has a
4916   // different hash algorithm. Don't try to look for these in the symbol table.
4917   Label not_array_index;
4918   __ leal(scratch, Operand(c1, -'0'));
4919   __ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
4920   __ j(above, &not_array_index, Label::kNear);
4921   __ leal(scratch, Operand(c2, -'0'));
4922   __ cmpl(scratch, Immediate(static_cast<int>('9' - '0')));
4923   __ j(below_equal, not_found);
4924
4925   __ bind(&not_array_index);
4926   // Calculate the two character string hash.
4927   Register hash = scratch1;
4928   GenerateHashInit(masm, hash, c1, scratch);
4929   GenerateHashAddCharacter(masm, hash, c2, scratch);
4930   GenerateHashGetHash(masm, hash, scratch);
4931
4932   // Collect the two characters in a register.
4933   Register chars = c1;
4934   __ shl(c2, Immediate(kBitsPerByte));
4935   __ orl(chars, c2);
4936
4937   // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
4938   // hash:  hash of two character string.
4939
4940   // Load the symbol table.
4941   Register symbol_table = c2;
4942   __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex);
4943
4944   // Calculate capacity mask from the symbol table capacity.
4945   Register mask = scratch2;
4946   __ SmiToInteger32(mask,
4947                     FieldOperand(symbol_table, SymbolTable::kCapacityOffset));
4948   __ decl(mask);
4949
4950   Register map = scratch4;
4951
4952   // Registers
4953   // chars:        two character string, char 1 in byte 0 and char 2 in byte 1.
4954   // hash:         hash of two character string (32-bit int)
4955   // symbol_table: symbol table
4956   // mask:         capacity mask (32-bit int)
4957   // map:          -
4958   // scratch:      -
4959
4960   // Perform a number of probes in the symbol table.
4961   static const int kProbes = 4;
4962   Label found_in_symbol_table;
4963   Label next_probe[kProbes];
4964   Register candidate = scratch;  // Scratch register contains candidate.
4965   for (int i = 0; i < kProbes; i++) {
4966     // Calculate entry in symbol table.
4967     __ movl(scratch, hash);
4968     if (i > 0) {
4969       __ addl(scratch, Immediate(SymbolTable::GetProbeOffset(i)));
4970     }
4971     __ andl(scratch, mask);
4972
4973     // Load the entry from the symbol table.
4974     STATIC_ASSERT(SymbolTable::kEntrySize == 1);
4975     __ movq(candidate,
4976             FieldOperand(symbol_table,
4977                          scratch,
4978                          times_pointer_size,
4979                          SymbolTable::kElementsStartOffset));
4980
4981     // If entry is undefined no string with this hash can be found.
4982     Label is_string;
4983     __ CmpObjectType(candidate, ODDBALL_TYPE, map);
4984     __ j(not_equal, &is_string, Label::kNear);
4985
4986     __ CompareRoot(candidate, Heap::kUndefinedValueRootIndex);
4987     __ j(equal, not_found);
4988     // Must be the hole (deleted entry).
4989     if (FLAG_debug_code) {
4990       __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
4991       __ cmpq(kScratchRegister, candidate);
4992       __ Assert(equal, "oddball in symbol table is not undefined or the hole");
4993     }
4994     __ jmp(&next_probe[i]);
4995
4996     __ bind(&is_string);
4997
4998     // If length is not 2 the string is not a candidate.
4999     __ SmiCompare(FieldOperand(candidate, String::kLengthOffset),
5000                   Smi::FromInt(2));
5001     __ j(not_equal, &next_probe[i]);
5002
5003     // We use kScratchRegister as a temporary register in assumption that
5004     // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly
5005     Register temp = kScratchRegister;
5006
5007     // Check that the candidate is a non-external ASCII string.
5008     __ movzxbl(temp, FieldOperand(map, Map::kInstanceTypeOffset));
5009     __ JumpIfInstanceTypeIsNotSequentialAscii(
5010         temp, temp, &next_probe[i]);
5011
5012     // Check if the two characters match.
5013     __ movl(temp, FieldOperand(candidate, SeqAsciiString::kHeaderSize));
5014     __ andl(temp, Immediate(0x0000ffff));
5015     __ cmpl(chars, temp);
5016     __ j(equal, &found_in_symbol_table);
5017     __ bind(&next_probe[i]);
5018   }
5019
5020   // No matching 2 character string found by probing.
5021   __ jmp(not_found);
5022
5023   // Scratch register contains result when we fall through to here.
5024   Register result = candidate;
5025   __ bind(&found_in_symbol_table);
5026   if (!result.is(rax)) {
5027     __ movq(rax, result);
5028   }
5029 }
5030
5031
5032 void StringHelper::GenerateHashInit(MacroAssembler* masm,
5033                                     Register hash,
5034                                     Register character,
5035                                     Register scratch) {
5036   // hash = (seed + character) + ((seed + character) << 10);
5037   __ LoadRoot(scratch, Heap::kHashSeedRootIndex);
5038   __ SmiToInteger32(scratch, scratch);
5039   __ addl(scratch, character);
5040   __ movl(hash, scratch);
5041   __ shll(scratch, Immediate(10));
5042   __ addl(hash, scratch);
5043   // hash ^= hash >> 6;
5044   __ movl(scratch, hash);
5045   __ shrl(scratch, Immediate(6));
5046   __ xorl(hash, scratch);
5047 }
5048
5049
5050 void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
5051                                             Register hash,
5052                                             Register character,
5053                                             Register scratch) {
5054   // hash += character;
5055   __ addl(hash, character);
5056   // hash += hash << 10;
5057   __ movl(scratch, hash);
5058   __ shll(scratch, Immediate(10));
5059   __ addl(hash, scratch);
5060   // hash ^= hash >> 6;
5061   __ movl(scratch, hash);
5062   __ shrl(scratch, Immediate(6));
5063   __ xorl(hash, scratch);
5064 }
5065
5066
5067 void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
5068                                        Register hash,
5069                                        Register scratch) {
5070   // hash += hash << 3;
5071   __ leal(hash, Operand(hash, hash, times_8, 0));
5072   // hash ^= hash >> 11;
5073   __ movl(scratch, hash);
5074   __ shrl(scratch, Immediate(11));
5075   __ xorl(hash, scratch);
5076   // hash += hash << 15;
5077   __ movl(scratch, hash);
5078   __ shll(scratch, Immediate(15));
5079   __ addl(hash, scratch);
5080
5081   __ andl(hash, Immediate(String::kHashBitMask));
5082
5083   // if (hash == 0) hash = 27;
5084   Label hash_not_zero;
5085   __ j(not_zero, &hash_not_zero);
5086   __ Set(hash, StringHasher::kZeroHash);
5087   __ bind(&hash_not_zero);
5088 }
5089
5090 void SubStringStub::Generate(MacroAssembler* masm) {
5091   Label runtime;
5092
5093   // Stack frame on entry.
5094   //  rsp[0]: return address
5095   //  rsp[8]: to
5096   //  rsp[16]: from
5097   //  rsp[24]: string
5098
5099   const int kToOffset = 1 * kPointerSize;
5100   const int kFromOffset = kToOffset + kPointerSize;
5101   const int kStringOffset = kFromOffset + kPointerSize;
5102   const int kArgumentsSize = (kStringOffset + kPointerSize) - kToOffset;
5103
5104   // Make sure first argument is a string.
5105   __ movq(rax, Operand(rsp, kStringOffset));
5106   STATIC_ASSERT(kSmiTag == 0);
5107   __ testl(rax, Immediate(kSmiTagMask));
5108   __ j(zero, &runtime);
5109   Condition is_string = masm->IsObjectStringType(rax, rbx, rbx);
5110   __ j(NegateCondition(is_string), &runtime);
5111
5112   // rax: string
5113   // rbx: instance type
5114   // Calculate length of sub string using the smi values.
5115   Label result_longer_than_two;
5116   __ movq(rcx, Operand(rsp, kToOffset));
5117   __ movq(rdx, Operand(rsp, kFromOffset));
5118   __ JumpUnlessBothNonNegativeSmi(rcx, rdx, &runtime);
5119
5120   __ SmiSub(rcx, rcx, rdx);  // Overflow doesn't happen.
5121   __ cmpq(FieldOperand(rax, String::kLengthOffset), rcx);
5122   Label not_original_string;
5123   __ j(not_equal, &not_original_string, Label::kNear);
5124   Counters* counters = masm->isolate()->counters();
5125   __ IncrementCounter(counters->sub_string_native(), 1);
5126   __ ret(kArgumentsSize);
5127   __ bind(&not_original_string);
5128   // Special handling of sub-strings of length 1 and 2. One character strings
5129   // are handled in the runtime system (looked up in the single character
5130   // cache). Two character strings are looked for in the symbol cache.
5131   __ SmiToInteger32(rcx, rcx);
5132   __ cmpl(rcx, Immediate(2));
5133   __ j(greater, &result_longer_than_two);
5134   __ j(less, &runtime);
5135
5136   // Sub string of length 2 requested.
5137   // rax: string
5138   // rbx: instance type
5139   // rcx: sub string length (value is 2)
5140   // rdx: from index (smi)
5141   __ JumpIfInstanceTypeIsNotSequentialAscii(rbx, rbx, &runtime);
5142
5143   // Get the two characters forming the sub string.
5144   __ SmiToInteger32(rdx, rdx);  // From index is no longer smi.
5145   __ movzxbq(rbx, FieldOperand(rax, rdx, times_1, SeqAsciiString::kHeaderSize));
5146   __ movzxbq(rdi,
5147              FieldOperand(rax, rdx, times_1, SeqAsciiString::kHeaderSize + 1));
5148
5149   // Try to lookup two character string in symbol table.
5150   Label make_two_character_string;
5151   StringHelper::GenerateTwoCharacterSymbolTableProbe(
5152       masm, rbx, rdi, r9, r11, r14, r15, &make_two_character_string);
5153   __ IncrementCounter(counters->sub_string_native(), 1);
5154   __ ret(3 * kPointerSize);
5155
5156   __ bind(&make_two_character_string);
5157   // Set up registers for allocating the two character string.
5158   __ movzxwq(rbx, FieldOperand(rax, rdx, times_1, SeqAsciiString::kHeaderSize));
5159   __ AllocateAsciiString(rax, rcx, r11, r14, r15, &runtime);
5160   __ movw(FieldOperand(rax, SeqAsciiString::kHeaderSize), rbx);
5161   __ IncrementCounter(counters->sub_string_native(), 1);
5162   __ ret(3 * kPointerSize);
5163
5164   __ bind(&result_longer_than_two);
5165   // rax: string
5166   // rbx: instance type
5167   // rcx: sub string length
5168   // rdx: from index (smi)
5169   // Deal with different string types: update the index if necessary
5170   // and put the underlying string into edi.
5171   Label underlying_unpacked, sliced_string, seq_or_external_string;
5172   // If the string is not indirect, it can only be sequential or external.
5173   STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
5174   STATIC_ASSERT(kIsIndirectStringMask != 0);
5175   __ testb(rbx, Immediate(kIsIndirectStringMask));
5176   __ j(zero, &seq_or_external_string, Label::kNear);
5177
5178   __ testb(rbx, Immediate(kSlicedNotConsMask));
5179   __ j(not_zero, &sliced_string, Label::kNear);
5180   // Cons string.  Check whether it is flat, then fetch first part.
5181   // Flat cons strings have an empty second part.
5182   __ CompareRoot(FieldOperand(rax, ConsString::kSecondOffset),
5183                  Heap::kEmptyStringRootIndex);
5184   __ j(not_equal, &runtime);
5185   __ movq(rdi, FieldOperand(rax, ConsString::kFirstOffset));
5186   // Update instance type.
5187   __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
5188   __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
5189   __ jmp(&underlying_unpacked, Label::kNear);
5190
5191   __ bind(&sliced_string);
5192   // Sliced string.  Fetch parent and correct start index by offset.
5193   __ addq(rdx, FieldOperand(rax, SlicedString::kOffsetOffset));
5194   __ movq(rdi, FieldOperand(rax, SlicedString::kParentOffset));
5195   // Update instance type.
5196   __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
5197   __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
5198   __ jmp(&underlying_unpacked, Label::kNear);
5199
5200   __ bind(&seq_or_external_string);
5201   // Sequential or external string.  Just move string to the correct register.
5202   __ movq(rdi, rax);
5203
5204   __ bind(&underlying_unpacked);
5205
5206   if (FLAG_string_slices) {
5207     Label copy_routine;
5208     // rdi: underlying subject string
5209     // rbx: instance type of underlying subject string
5210     // rdx: adjusted start index (smi)
5211     // rcx: length
5212     // If coming from the make_two_character_string path, the string
5213     // is too short to be sliced anyways.
5214     __ cmpq(rcx, Immediate(SlicedString::kMinLength));
5215     // Short slice.  Copy instead of slicing.
5216     __ j(less, &copy_routine);
5217     // Allocate new sliced string.  At this point we do not reload the instance
5218     // type including the string encoding because we simply rely on the info
5219     // provided by the original string.  It does not matter if the original
5220     // string's encoding is wrong because we always have to recheck encoding of
5221     // the newly created string's parent anyways due to externalized strings.
5222     Label two_byte_slice, set_slice_header;
5223     STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
5224     STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
5225     __ testb(rbx, Immediate(kStringEncodingMask));
5226     __ j(zero, &two_byte_slice, Label::kNear);
5227     __ AllocateAsciiSlicedString(rax, rbx, r14, &runtime);
5228     __ jmp(&set_slice_header, Label::kNear);
5229     __ bind(&two_byte_slice);
5230     __ AllocateTwoByteSlicedString(rax, rbx, r14, &runtime);
5231     __ bind(&set_slice_header);
5232     __ Integer32ToSmi(rcx, rcx);
5233     __ movq(FieldOperand(rax, SlicedString::kLengthOffset), rcx);
5234     __ movq(FieldOperand(rax, SlicedString::kHashFieldOffset),
5235            Immediate(String::kEmptyHashField));
5236     __ movq(FieldOperand(rax, SlicedString::kParentOffset), rdi);
5237     __ movq(FieldOperand(rax, SlicedString::kOffsetOffset), rdx);
5238     __ IncrementCounter(counters->sub_string_native(), 1);
5239     __ ret(kArgumentsSize);
5240
5241     __ bind(&copy_routine);
5242   }
5243
5244   // rdi: underlying subject string
5245   // rbx: instance type of underlying subject string
5246   // rdx: adjusted start index (smi)
5247   // rcx: length
5248   // The subject string can only be external or sequential string of either
5249   // encoding at this point.
5250   Label two_byte_sequential, sequential_string;
5251   STATIC_ASSERT(kExternalStringTag != 0);
5252   STATIC_ASSERT(kSeqStringTag == 0);
5253   __ testb(rbx, Immediate(kExternalStringTag));
5254   __ j(zero, &sequential_string);
5255
5256   // Handle external string.
5257   // Rule out short external strings.
5258   STATIC_CHECK(kShortExternalStringTag != 0);
5259   __ testb(rbx, Immediate(kShortExternalStringMask));
5260   __ j(not_zero, &runtime);
5261   __ movq(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset));
5262   // Move the pointer so that offset-wise, it looks like a sequential string.
5263   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize);
5264   __ subq(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
5265
5266   __ bind(&sequential_string);
5267   STATIC_ASSERT((kAsciiStringTag & kStringEncodingMask) != 0);
5268   __ testb(rbx, Immediate(kStringEncodingMask));
5269   __ j(zero, &two_byte_sequential);
5270
5271   // Allocate the result.
5272   __ AllocateAsciiString(rax, rcx, r11, r14, r15, &runtime);
5273
5274   // rax: result string
5275   // rcx: result string length
5276   __ movq(r14, rsi);  // esi used by following code.
5277   {  // Locate character of sub string start.
5278     SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_1);
5279     __ lea(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale,
5280                         SeqAsciiString::kHeaderSize - kHeapObjectTag));
5281   }
5282   // Locate first character of result.
5283   __ lea(rdi, FieldOperand(rax, SeqAsciiString::kHeaderSize));
5284
5285   // rax: result string
5286   // rcx: result length
5287   // rdi: first character of result
5288   // rsi: character of sub string start
5289   // r14: original value of rsi
5290   StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true);
5291   __ movq(rsi, r14);  // Restore rsi.
5292   __ IncrementCounter(counters->sub_string_native(), 1);
5293   __ ret(kArgumentsSize);
5294
5295   __ bind(&two_byte_sequential);
5296   // Allocate the result.
5297   __ AllocateTwoByteString(rax, rcx, r11, r14, r15, &runtime);
5298
5299   // rax: result string
5300   // rcx: result string length
5301   __ movq(r14, rsi);  // esi used by following code.
5302   {  // Locate character of sub string start.
5303     SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2);
5304     __ lea(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale,
5305                         SeqAsciiString::kHeaderSize - kHeapObjectTag));
5306   }
5307   // Locate first character of result.
5308   __ lea(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize));
5309
5310   // rax: result string
5311   // rcx: result length
5312   // rdi: first character of result
5313   // rsi: character of sub string start
5314   // r14: original value of rsi
5315   StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false);
5316   __ movq(rsi, r14);  // Restore esi.
5317   __ IncrementCounter(counters->sub_string_native(), 1);
5318   __ ret(kArgumentsSize);
5319
5320   // Just jump to runtime to create the sub string.
5321   __ bind(&runtime);
5322   __ TailCallRuntime(Runtime::kSubString, 3, 1);
5323 }
5324
5325
5326 void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
5327                                                       Register left,
5328                                                       Register right,
5329                                                       Register scratch1,
5330                                                       Register scratch2) {
5331   Register length = scratch1;
5332
5333   // Compare lengths.
5334   Label check_zero_length;
5335   __ movq(length, FieldOperand(left, String::kLengthOffset));
5336   __ SmiCompare(length, FieldOperand(right, String::kLengthOffset));
5337   __ j(equal, &check_zero_length, Label::kNear);
5338   __ Move(rax, Smi::FromInt(NOT_EQUAL));
5339   __ ret(0);
5340
5341   // Check if the length is zero.
5342   Label compare_chars;
5343   __ bind(&check_zero_length);
5344   STATIC_ASSERT(kSmiTag == 0);
5345   __ SmiTest(length);
5346   __ j(not_zero, &compare_chars, Label::kNear);
5347   __ Move(rax, Smi::FromInt(EQUAL));
5348   __ ret(0);
5349
5350   // Compare characters.
5351   __ bind(&compare_chars);
5352   Label strings_not_equal;
5353   GenerateAsciiCharsCompareLoop(masm, left, right, length, scratch2,
5354                                 &strings_not_equal, Label::kNear);
5355
5356   // Characters are equal.
5357   __ Move(rax, Smi::FromInt(EQUAL));
5358   __ ret(0);
5359
5360   // Characters are not equal.
5361   __ bind(&strings_not_equal);
5362   __ Move(rax, Smi::FromInt(NOT_EQUAL));
5363   __ ret(0);
5364 }
5365
5366
5367 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
5368                                                         Register left,
5369                                                         Register right,
5370                                                         Register scratch1,
5371                                                         Register scratch2,
5372                                                         Register scratch3,
5373                                                         Register scratch4) {
5374   // Ensure that you can always subtract a string length from a non-negative
5375   // number (e.g. another length).
5376   STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
5377
5378   // Find minimum length and length difference.
5379   __ movq(scratch1, FieldOperand(left, String::kLengthOffset));
5380   __ movq(scratch4, scratch1);
5381   __ SmiSub(scratch4,
5382             scratch4,
5383             FieldOperand(right, String::kLengthOffset));
5384   // Register scratch4 now holds left.length - right.length.
5385   const Register length_difference = scratch4;
5386   Label left_shorter;
5387   __ j(less, &left_shorter, Label::kNear);
5388   // The right string isn't longer that the left one.
5389   // Get the right string's length by subtracting the (non-negative) difference
5390   // from the left string's length.
5391   __ SmiSub(scratch1, scratch1, length_difference);
5392   __ bind(&left_shorter);
5393   // Register scratch1 now holds Min(left.length, right.length).
5394   const Register min_length = scratch1;
5395
5396   Label compare_lengths;
5397   // If min-length is zero, go directly to comparing lengths.
5398   __ SmiTest(min_length);
5399   __ j(zero, &compare_lengths, Label::kNear);
5400
5401   // Compare loop.
5402   Label result_not_equal;
5403   GenerateAsciiCharsCompareLoop(masm, left, right, min_length, scratch2,
5404                                 &result_not_equal, Label::kNear);
5405
5406   // Completed loop without finding different characters.
5407   // Compare lengths (precomputed).
5408   __ bind(&compare_lengths);
5409   __ SmiTest(length_difference);
5410   __ j(not_zero, &result_not_equal, Label::kNear);
5411
5412   // Result is EQUAL.
5413   __ Move(rax, Smi::FromInt(EQUAL));
5414   __ ret(0);
5415
5416   Label result_greater;
5417   __ bind(&result_not_equal);
5418   // Unequal comparison of left to right, either character or length.
5419   __ j(greater, &result_greater, Label::kNear);
5420
5421   // Result is LESS.
5422   __ Move(rax, Smi::FromInt(LESS));
5423   __ ret(0);
5424
5425   // Result is GREATER.
5426   __ bind(&result_greater);
5427   __ Move(rax, Smi::FromInt(GREATER));
5428   __ ret(0);
5429 }
5430
5431
5432 void StringCompareStub::GenerateAsciiCharsCompareLoop(
5433     MacroAssembler* masm,
5434     Register left,
5435     Register right,
5436     Register length,
5437     Register scratch,
5438     Label* chars_not_equal,
5439     Label::Distance near_jump) {
5440   // Change index to run from -length to -1 by adding length to string
5441   // start. This means that loop ends when index reaches zero, which
5442   // doesn't need an additional compare.
5443   __ SmiToInteger32(length, length);
5444   __ lea(left,
5445          FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize));
5446   __ lea(right,
5447          FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize));
5448   __ neg(length);
5449   Register index = length;  // index = -length;
5450
5451   // Compare loop.
5452   Label loop;
5453   __ bind(&loop);
5454   __ movb(scratch, Operand(left, index, times_1, 0));
5455   __ cmpb(scratch, Operand(right, index, times_1, 0));
5456   __ j(not_equal, chars_not_equal, near_jump);
5457   __ incq(index);
5458   __ j(not_zero, &loop);
5459 }
5460
5461
5462 void StringCompareStub::Generate(MacroAssembler* masm) {
5463   Label runtime;
5464
5465   // Stack frame on entry.
5466   //  rsp[0]: return address
5467   //  rsp[8]: right string
5468   //  rsp[16]: left string
5469
5470   __ movq(rdx, Operand(rsp, 2 * kPointerSize));  // left
5471   __ movq(rax, Operand(rsp, 1 * kPointerSize));  // right
5472
5473   // Check for identity.
5474   Label not_same;
5475   __ cmpq(rdx, rax);
5476   __ j(not_equal, &not_same, Label::kNear);
5477   __ Move(rax, Smi::FromInt(EQUAL));
5478   Counters* counters = masm->isolate()->counters();
5479   __ IncrementCounter(counters->string_compare_native(), 1);
5480   __ ret(2 * kPointerSize);
5481
5482   __ bind(&not_same);
5483
5484   // Check that both are sequential ASCII strings.
5485   __ JumpIfNotBothSequentialAsciiStrings(rdx, rax, rcx, rbx, &runtime);
5486
5487   // Inline comparison of ASCII strings.
5488   __ IncrementCounter(counters->string_compare_native(), 1);
5489   // Drop arguments from the stack
5490   __ pop(rcx);
5491   __ addq(rsp, Immediate(2 * kPointerSize));
5492   __ push(rcx);
5493   GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8);
5494
5495   // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
5496   // tagged as a small integer.
5497   __ bind(&runtime);
5498   __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
5499 }
5500
5501
5502 void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
5503   ASSERT(state_ == CompareIC::SMIS);
5504   Label miss;
5505   __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear);
5506
5507   if (GetCondition() == equal) {
5508     // For equality we do not care about the sign of the result.
5509     __ subq(rax, rdx);
5510   } else {
5511     Label done;
5512     __ subq(rdx, rax);
5513     __ j(no_overflow, &done, Label::kNear);
5514     // Correct sign of result in case of overflow.
5515     __ SmiNot(rdx, rdx);
5516     __ bind(&done);
5517     __ movq(rax, rdx);
5518   }
5519   __ ret(0);
5520
5521   __ bind(&miss);
5522   GenerateMiss(masm);
5523 }
5524
5525
5526 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
5527   ASSERT(state_ == CompareIC::HEAP_NUMBERS);
5528
5529   Label generic_stub;
5530   Label unordered, maybe_undefined1, maybe_undefined2;
5531   Label miss;
5532   Condition either_smi = masm->CheckEitherSmi(rax, rdx);
5533   __ j(either_smi, &generic_stub, Label::kNear);
5534
5535   __ CmpObjectType(rax, HEAP_NUMBER_TYPE, rcx);
5536   __ j(not_equal, &maybe_undefined1, Label::kNear);
5537   __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx);
5538   __ j(not_equal, &maybe_undefined2, Label::kNear);
5539
5540   // Load left and right operand
5541   __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
5542   __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
5543
5544   // Compare operands
5545   __ ucomisd(xmm0, xmm1);
5546
5547   // Don't base result on EFLAGS when a NaN is involved.
5548   __ j(parity_even, &unordered, Label::kNear);
5549
5550   // Return a result of -1, 0, or 1, based on EFLAGS.
5551   // Performing mov, because xor would destroy the flag register.
5552   __ movl(rax, Immediate(0));
5553   __ movl(rcx, Immediate(0));
5554   __ setcc(above, rax);  // Add one to zero if carry clear and not equal.
5555   __ sbbq(rax, rcx);  // Subtract one if below (aka. carry set).
5556   __ ret(0);
5557
5558   __ bind(&unordered);
5559   CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS);
5560   __ bind(&generic_stub);
5561   __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET);
5562
5563   __ bind(&maybe_undefined1);
5564   if (Token::IsOrderedRelationalCompareOp(op_)) {
5565     __ Cmp(rax, masm->isolate()->factory()->undefined_value());
5566     __ j(not_equal, &miss);
5567     __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx);
5568     __ j(not_equal, &maybe_undefined2, Label::kNear);
5569     __ jmp(&unordered);
5570   }
5571
5572   __ bind(&maybe_undefined2);
5573   if (Token::IsOrderedRelationalCompareOp(op_)) {
5574     __ Cmp(rdx, masm->isolate()->factory()->undefined_value());
5575     __ j(equal, &unordered);
5576   }
5577
5578   __ bind(&miss);
5579   GenerateMiss(masm);
5580 }
5581
5582
5583 void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
5584   ASSERT(state_ == CompareIC::SYMBOLS);
5585   ASSERT(GetCondition() == equal);
5586
5587   // Registers containing left and right operands respectively.
5588   Register left = rdx;
5589   Register right = rax;
5590   Register tmp1 = rcx;
5591   Register tmp2 = rbx;
5592
5593   // Check that both operands are heap objects.
5594   Label miss;
5595   Condition cond = masm->CheckEitherSmi(left, right, tmp1);
5596   __ j(cond, &miss, Label::kNear);
5597
5598   // Check that both operands are symbols.
5599   __ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset));
5600   __ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset));
5601   __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
5602   __ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
5603   STATIC_ASSERT(kSymbolTag != 0);
5604   __ and_(tmp1, tmp2);
5605   __ testb(tmp1, Immediate(kIsSymbolMask));
5606   __ j(zero, &miss, Label::kNear);
5607
5608   // Symbols are compared by identity.
5609   Label done;
5610   __ cmpq(left, right);
5611   // Make sure rax is non-zero. At this point input operands are
5612   // guaranteed to be non-zero.
5613   ASSERT(right.is(rax));
5614   __ j(not_equal, &done, Label::kNear);
5615   STATIC_ASSERT(EQUAL == 0);
5616   STATIC_ASSERT(kSmiTag == 0);
5617   __ Move(rax, Smi::FromInt(EQUAL));
5618   __ bind(&done);
5619   __ ret(0);
5620
5621   __ bind(&miss);
5622   GenerateMiss(masm);
5623 }
5624
5625
5626 void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
5627   ASSERT(state_ == CompareIC::STRINGS);
5628   Label miss;
5629
5630   bool equality = Token::IsEqualityOp(op_);
5631
5632   // Registers containing left and right operands respectively.
5633   Register left = rdx;
5634   Register right = rax;
5635   Register tmp1 = rcx;
5636   Register tmp2 = rbx;
5637   Register tmp3 = rdi;
5638
5639   // Check that both operands are heap objects.
5640   Condition cond = masm->CheckEitherSmi(left, right, tmp1);
5641   __ j(cond, &miss);
5642
5643   // Check that both operands are strings. This leaves the instance
5644   // types loaded in tmp1 and tmp2.
5645   __ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset));
5646   __ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset));
5647   __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
5648   __ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
5649   __ movq(tmp3, tmp1);
5650   STATIC_ASSERT(kNotStringTag != 0);
5651   __ or_(tmp3, tmp2);
5652   __ testb(tmp3, Immediate(kIsNotStringMask));
5653   __ j(not_zero, &miss);
5654
5655   // Fast check for identical strings.
5656   Label not_same;
5657   __ cmpq(left, right);
5658   __ j(not_equal, &not_same, Label::kNear);
5659   STATIC_ASSERT(EQUAL == 0);
5660   STATIC_ASSERT(kSmiTag == 0);
5661   __ Move(rax, Smi::FromInt(EQUAL));
5662   __ ret(0);
5663
5664   // Handle not identical strings.
5665   __ bind(&not_same);
5666
5667   // Check that both strings are symbols. If they are, we're done
5668   // because we already know they are not identical.
5669   if (equality) {
5670     Label do_compare;
5671     STATIC_ASSERT(kSymbolTag != 0);
5672     __ and_(tmp1, tmp2);
5673     __ testb(tmp1, Immediate(kIsSymbolMask));
5674     __ j(zero, &do_compare, Label::kNear);
5675     // Make sure rax is non-zero. At this point input operands are
5676     // guaranteed to be non-zero.
5677     ASSERT(right.is(rax));
5678     __ ret(0);
5679     __ bind(&do_compare);
5680   }
5681
5682   // Check that both strings are sequential ASCII.
5683   Label runtime;
5684   __ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime);
5685
5686   // Compare flat ASCII strings. Returns when done.
5687   if (equality) {
5688     StringCompareStub::GenerateFlatAsciiStringEquals(
5689         masm, left, right, tmp1, tmp2);
5690   } else {
5691     StringCompareStub::GenerateCompareFlatAsciiStrings(
5692         masm, left, right, tmp1, tmp2, tmp3, kScratchRegister);
5693   }
5694
5695   // Handle more complex cases in runtime.
5696   __ bind(&runtime);
5697   __ pop(tmp1);  // Return address.
5698   __ push(left);
5699   __ push(right);
5700   __ push(tmp1);
5701   if (equality) {
5702     __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
5703   } else {
5704     __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
5705   }
5706
5707   __ bind(&miss);
5708   GenerateMiss(masm);
5709 }
5710
5711
5712 void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
5713   ASSERT(state_ == CompareIC::OBJECTS);
5714   Label miss;
5715   Condition either_smi = masm->CheckEitherSmi(rdx, rax);
5716   __ j(either_smi, &miss, Label::kNear);
5717
5718   __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx);
5719   __ j(not_equal, &miss, Label::kNear);
5720   __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
5721   __ j(not_equal, &miss, Label::kNear);
5722
5723   ASSERT(GetCondition() == equal);
5724   __ subq(rax, rdx);
5725   __ ret(0);
5726
5727   __ bind(&miss);
5728   GenerateMiss(masm);
5729 }
5730
5731
5732 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) {
5733   Label miss;
5734   Condition either_smi = masm->CheckEitherSmi(rdx, rax);
5735   __ j(either_smi, &miss, Label::kNear);
5736
5737   __ movq(rcx, FieldOperand(rax, HeapObject::kMapOffset));
5738   __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
5739   __ Cmp(rcx, known_map_);
5740   __ j(not_equal, &miss, Label::kNear);
5741   __ Cmp(rbx, known_map_);
5742   __ j(not_equal, &miss, Label::kNear);
5743
5744   __ subq(rax, rdx);
5745   __ ret(0);
5746
5747   __ bind(&miss);
5748   GenerateMiss(masm);
5749 }
5750
5751
5752 void ICCompareStub::GenerateMiss(MacroAssembler* masm) {
5753   {
5754     // Call the runtime system in a fresh internal frame.
5755     ExternalReference miss =
5756         ExternalReference(IC_Utility(IC::kCompareIC_Miss), masm->isolate());
5757
5758     FrameScope scope(masm, StackFrame::INTERNAL);
5759     __ push(rdx);
5760     __ push(rax);
5761     __ push(rdx);
5762     __ push(rax);
5763     __ Push(Smi::FromInt(op_));
5764     __ CallExternalReference(miss, 3);
5765
5766     // Compute the entry point of the rewritten stub.
5767     __ lea(rdi, FieldOperand(rax, Code::kHeaderSize));
5768     __ pop(rax);
5769     __ pop(rdx);
5770   }
5771
5772   // Do a tail call to the rewritten stub.
5773   __ jmp(rdi);
5774 }
5775
5776
5777 void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
5778                                                         Label* miss,
5779                                                         Label* done,
5780                                                         Register properties,
5781                                                         Handle<String> name,
5782                                                         Register r0) {
5783   // If names of slots in range from 1 to kProbes - 1 for the hash value are
5784   // not equal to the name and kProbes-th slot is not used (its name is the
5785   // undefined value), it guarantees the hash table doesn't contain the
5786   // property. It's true even if some slots represent deleted properties
5787   // (their names are the hole value).
5788   for (int i = 0; i < kInlinedProbes; i++) {
5789     // r0 points to properties hash.
5790     // Compute the masked index: (hash + i + i * i) & mask.
5791     Register index = r0;
5792     // Capacity is smi 2^n.
5793     __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset));
5794     __ decl(index);
5795     __ and_(index,
5796             Immediate(name->Hash() + StringDictionary::GetProbeOffset(i)));
5797
5798     // Scale the index by multiplying by the entry size.
5799     ASSERT(StringDictionary::kEntrySize == 3);
5800     __ lea(index, Operand(index, index, times_2, 0));  // index *= 3.
5801
5802     Register entity_name = r0;
5803     // Having undefined at this place means the name is not contained.
5804     ASSERT_EQ(kSmiTagSize, 1);
5805     __ movq(entity_name, Operand(properties,
5806                                  index,
5807                                  times_pointer_size,
5808                                  kElementsStartOffset - kHeapObjectTag));
5809     __ Cmp(entity_name, masm->isolate()->factory()->undefined_value());
5810     __ j(equal, done);
5811
5812     // Stop if found the property.
5813     __ Cmp(entity_name, Handle<String>(name));
5814     __ j(equal, miss);
5815
5816     Label the_hole;
5817     // Check for the hole and skip.
5818     __ CompareRoot(entity_name, Heap::kTheHoleValueRootIndex);
5819     __ j(equal, &the_hole, Label::kNear);
5820
5821     // Check if the entry name is not a symbol.
5822     __ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
5823     __ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
5824              Immediate(kIsSymbolMask));
5825     __ j(zero, miss);
5826
5827     __ bind(&the_hole);
5828   }
5829
5830   StringDictionaryLookupStub stub(properties,
5831                                   r0,
5832                                   r0,
5833                                   StringDictionaryLookupStub::NEGATIVE_LOOKUP);
5834   __ Push(Handle<Object>(name));
5835   __ push(Immediate(name->Hash()));
5836   __ CallStub(&stub);
5837   __ testq(r0, r0);
5838   __ j(not_zero, miss);
5839   __ jmp(done);
5840 }
5841
5842
5843 // Probe the string dictionary in the |elements| register. Jump to the
5844 // |done| label if a property with the given name is found leaving the
5845 // index into the dictionary in |r1|. Jump to the |miss| label
5846 // otherwise.
5847 void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
5848                                                         Label* miss,
5849                                                         Label* done,
5850                                                         Register elements,
5851                                                         Register name,
5852                                                         Register r0,
5853                                                         Register r1) {
5854   ASSERT(!elements.is(r0));
5855   ASSERT(!elements.is(r1));
5856   ASSERT(!name.is(r0));
5857   ASSERT(!name.is(r1));
5858
5859   // Assert that name contains a string.
5860   if (FLAG_debug_code) __ AbortIfNotString(name);
5861
5862   __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset));
5863   __ decl(r0);
5864
5865   for (int i = 0; i < kInlinedProbes; i++) {
5866     // Compute the masked index: (hash + i + i * i) & mask.
5867     __ movl(r1, FieldOperand(name, String::kHashFieldOffset));
5868     __ shrl(r1, Immediate(String::kHashShift));
5869     if (i > 0) {
5870       __ addl(r1, Immediate(StringDictionary::GetProbeOffset(i)));
5871     }
5872     __ and_(r1, r0);
5873
5874     // Scale the index by multiplying by the entry size.
5875     ASSERT(StringDictionary::kEntrySize == 3);
5876     __ lea(r1, Operand(r1, r1, times_2, 0));  // r1 = r1 * 3
5877
5878     // Check if the key is identical to the name.
5879     __ cmpq(name, Operand(elements, r1, times_pointer_size,
5880                           kElementsStartOffset - kHeapObjectTag));
5881     __ j(equal, done);
5882   }
5883
5884   StringDictionaryLookupStub stub(elements,
5885                                   r0,
5886                                   r1,
5887                                   POSITIVE_LOOKUP);
5888   __ push(name);
5889   __ movl(r0, FieldOperand(name, String::kHashFieldOffset));
5890   __ shrl(r0, Immediate(String::kHashShift));
5891   __ push(r0);
5892   __ CallStub(&stub);
5893
5894   __ testq(r0, r0);
5895   __ j(zero, miss);
5896   __ jmp(done);
5897 }
5898
5899
5900 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
5901   // This stub overrides SometimesSetsUpAFrame() to return false.  That means
5902   // we cannot call anything that could cause a GC from this stub.
5903   // Stack frame on entry:
5904   //  esp[0 * kPointerSize]: return address.
5905   //  esp[1 * kPointerSize]: key's hash.
5906   //  esp[2 * kPointerSize]: key.
5907   // Registers:
5908   //  dictionary_: StringDictionary to probe.
5909   //  result_: used as scratch.
5910   //  index_: will hold an index of entry if lookup is successful.
5911   //          might alias with result_.
5912   // Returns:
5913   //  result_ is zero if lookup failed, non zero otherwise.
5914
5915   Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
5916
5917   Register scratch = result_;
5918
5919   __ SmiToInteger32(scratch, FieldOperand(dictionary_, kCapacityOffset));
5920   __ decl(scratch);
5921   __ push(scratch);
5922
5923   // If names of slots in range from 1 to kProbes - 1 for the hash value are
5924   // not equal to the name and kProbes-th slot is not used (its name is the
5925   // undefined value), it guarantees the hash table doesn't contain the
5926   // property. It's true even if some slots represent deleted properties
5927   // (their names are the null value).
5928   for (int i = kInlinedProbes; i < kTotalProbes; i++) {
5929     // Compute the masked index: (hash + i + i * i) & mask.
5930     __ movq(scratch, Operand(rsp, 2 * kPointerSize));
5931     if (i > 0) {
5932       __ addl(scratch, Immediate(StringDictionary::GetProbeOffset(i)));
5933     }
5934     __ and_(scratch, Operand(rsp, 0));
5935
5936     // Scale the index by multiplying by the entry size.
5937     ASSERT(StringDictionary::kEntrySize == 3);
5938     __ lea(index_, Operand(scratch, scratch, times_2, 0));  // index *= 3.
5939
5940     // Having undefined at this place means the name is not contained.
5941     __ movq(scratch, Operand(dictionary_,
5942                              index_,
5943                              times_pointer_size,
5944                              kElementsStartOffset - kHeapObjectTag));
5945
5946     __ Cmp(scratch, masm->isolate()->factory()->undefined_value());
5947     __ j(equal, &not_in_dictionary);
5948
5949     // Stop if found the property.
5950     __ cmpq(scratch, Operand(rsp, 3 * kPointerSize));
5951     __ j(equal, &in_dictionary);
5952
5953     if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
5954       // If we hit a non symbol key during negative lookup
5955       // we have to bailout as this key might be equal to the
5956       // key we are looking for.
5957
5958       // Check if the entry name is not a symbol.
5959       __ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
5960       __ testb(FieldOperand(scratch, Map::kInstanceTypeOffset),
5961                Immediate(kIsSymbolMask));
5962       __ j(zero, &maybe_in_dictionary);
5963     }
5964   }
5965
5966   __ bind(&maybe_in_dictionary);
5967   // If we are doing negative lookup then probing failure should be
5968   // treated as a lookup success. For positive lookup probing failure
5969   // should be treated as lookup failure.
5970   if (mode_ == POSITIVE_LOOKUP) {
5971     __ movq(scratch, Immediate(0));
5972     __ Drop(1);
5973     __ ret(2 * kPointerSize);
5974   }
5975
5976   __ bind(&in_dictionary);
5977   __ movq(scratch, Immediate(1));
5978   __ Drop(1);
5979   __ ret(2 * kPointerSize);
5980
5981   __ bind(&not_in_dictionary);
5982   __ movq(scratch, Immediate(0));
5983   __ Drop(1);
5984   __ ret(2 * kPointerSize);
5985 }
5986
5987
5988 struct AheadOfTimeWriteBarrierStubList {
5989   Register object, value, address;
5990   RememberedSetAction action;
5991 };
5992
5993
5994 #define REG(Name) { kRegister_ ## Name ## _Code }
5995
5996 struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
5997   // Used in RegExpExecStub.
5998   { REG(rbx), REG(rax), REG(rdi), EMIT_REMEMBERED_SET },
5999   // Used in CompileArrayPushCall.
6000   { REG(rbx), REG(rcx), REG(rdx), EMIT_REMEMBERED_SET },
6001   // Used in CompileStoreGlobal.
6002   { REG(rbx), REG(rcx), REG(rdx), OMIT_REMEMBERED_SET },
6003   // Used in StoreStubCompiler::CompileStoreField and
6004   // KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField.
6005   { REG(rdx), REG(rcx), REG(rbx), EMIT_REMEMBERED_SET },
6006   // GenerateStoreField calls the stub with two different permutations of
6007   // registers.  This is the second.
6008   { REG(rbx), REG(rcx), REG(rdx), EMIT_REMEMBERED_SET },
6009   // StoreIC::GenerateNormal via GenerateDictionaryStore.
6010   { REG(rbx), REG(r8), REG(r9), EMIT_REMEMBERED_SET },
6011   // KeyedStoreIC::GenerateGeneric.
6012   { REG(rbx), REG(rdx), REG(rcx), EMIT_REMEMBERED_SET},
6013   // KeyedStoreStubCompiler::GenerateStoreFastElement.
6014   { REG(rdi), REG(rbx), REG(rcx), EMIT_REMEMBERED_SET},
6015   { REG(rdx), REG(rdi), REG(rbx), EMIT_REMEMBERED_SET},
6016   // ElementsTransitionGenerator::GenerateSmiOnlyToObject
6017   // and ElementsTransitionGenerator::GenerateSmiOnlyToObject
6018   // and ElementsTransitionGenerator::GenerateDoubleToObject
6019   { REG(rdx), REG(rbx), REG(rdi), EMIT_REMEMBERED_SET},
6020   { REG(rdx), REG(rbx), REG(rdi), OMIT_REMEMBERED_SET},
6021   // ElementsTransitionGenerator::GenerateSmiOnlyToDouble
6022   // and ElementsTransitionGenerator::GenerateDoubleToObject
6023   { REG(rdx), REG(r11), REG(r15), EMIT_REMEMBERED_SET},
6024   // ElementsTransitionGenerator::GenerateDoubleToObject
6025   { REG(r11), REG(rax), REG(r15), EMIT_REMEMBERED_SET},
6026   // StoreArrayLiteralElementStub::Generate
6027   { REG(rbx), REG(rax), REG(rcx), EMIT_REMEMBERED_SET},
6028   // Null termination.
6029   { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET}
6030 };
6031
6032 #undef REG
6033
6034 bool RecordWriteStub::IsPregenerated() {
6035   for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
6036        !entry->object.is(no_reg);
6037        entry++) {
6038     if (object_.is(entry->object) &&
6039         value_.is(entry->value) &&
6040         address_.is(entry->address) &&
6041         remembered_set_action_ == entry->action &&
6042         save_fp_regs_mode_ == kDontSaveFPRegs) {
6043       return true;
6044     }
6045   }
6046   return false;
6047 }
6048
6049
6050 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime() {
6051   StoreBufferOverflowStub stub1(kDontSaveFPRegs);
6052   stub1.GetCode()->set_is_pregenerated(true);
6053   StoreBufferOverflowStub stub2(kSaveFPRegs);
6054   stub2.GetCode()->set_is_pregenerated(true);
6055 }
6056
6057
6058 void RecordWriteStub::GenerateFixedRegStubsAheadOfTime() {
6059   for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
6060        !entry->object.is(no_reg);
6061        entry++) {
6062     RecordWriteStub stub(entry->object,
6063                          entry->value,
6064                          entry->address,
6065                          entry->action,
6066                          kDontSaveFPRegs);
6067     stub.GetCode()->set_is_pregenerated(true);
6068   }
6069 }
6070
6071
6072 // Takes the input in 3 registers: address_ value_ and object_.  A pointer to
6073 // the value has just been written into the object, now this stub makes sure
6074 // we keep the GC informed.  The word in the object where the value has been
6075 // written is in the address register.
6076 void RecordWriteStub::Generate(MacroAssembler* masm) {
6077   Label skip_to_incremental_noncompacting;
6078   Label skip_to_incremental_compacting;
6079
6080   // The first two instructions are generated with labels so as to get the
6081   // offset fixed up correctly by the bind(Label*) call.  We patch it back and
6082   // forth between a compare instructions (a nop in this position) and the
6083   // real branch when we start and stop incremental heap marking.
6084   // See RecordWriteStub::Patch for details.
6085   __ jmp(&skip_to_incremental_noncompacting, Label::kNear);
6086   __ jmp(&skip_to_incremental_compacting, Label::kFar);
6087
6088   if (remembered_set_action_ == EMIT_REMEMBERED_SET) {
6089     __ RememberedSetHelper(object_,
6090                            address_,
6091                            value_,
6092                            save_fp_regs_mode_,
6093                            MacroAssembler::kReturnAtEnd);
6094   } else {
6095     __ ret(0);
6096   }
6097
6098   __ bind(&skip_to_incremental_noncompacting);
6099   GenerateIncremental(masm, INCREMENTAL);
6100
6101   __ bind(&skip_to_incremental_compacting);
6102   GenerateIncremental(masm, INCREMENTAL_COMPACTION);
6103
6104   // Initial mode of the stub is expected to be STORE_BUFFER_ONLY.
6105   // Will be checked in IncrementalMarking::ActivateGeneratedStub.
6106   masm->set_byte_at(0, kTwoByteNopInstruction);
6107   masm->set_byte_at(2, kFiveByteNopInstruction);
6108 }
6109
6110
6111 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) {
6112   regs_.Save(masm);
6113
6114   if (remembered_set_action_ == EMIT_REMEMBERED_SET) {
6115     Label dont_need_remembered_set;
6116
6117     __ movq(regs_.scratch0(), Operand(regs_.address(), 0));
6118     __ JumpIfNotInNewSpace(regs_.scratch0(),
6119                            regs_.scratch0(),
6120                            &dont_need_remembered_set);
6121
6122     __ CheckPageFlag(regs_.object(),
6123                      regs_.scratch0(),
6124                      1 << MemoryChunk::SCAN_ON_SCAVENGE,
6125                      not_zero,
6126                      &dont_need_remembered_set);
6127
6128     // First notify the incremental marker if necessary, then update the
6129     // remembered set.
6130     CheckNeedsToInformIncrementalMarker(
6131         masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode);
6132     InformIncrementalMarker(masm, mode);
6133     regs_.Restore(masm);
6134     __ RememberedSetHelper(object_,
6135                            address_,
6136                            value_,
6137                            save_fp_regs_mode_,
6138                            MacroAssembler::kReturnAtEnd);
6139
6140     __ bind(&dont_need_remembered_set);
6141   }
6142
6143   CheckNeedsToInformIncrementalMarker(
6144       masm, kReturnOnNoNeedToInformIncrementalMarker, mode);
6145   InformIncrementalMarker(masm, mode);
6146   regs_.Restore(masm);
6147   __ ret(0);
6148 }
6149
6150
6151 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm, Mode mode) {
6152   regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_);
6153 #ifdef _WIN64
6154   Register arg3 = r8;
6155   Register arg2 = rdx;
6156   Register arg1 = rcx;
6157 #else
6158   Register arg3 = rdx;
6159   Register arg2 = rsi;
6160   Register arg1 = rdi;
6161 #endif
6162   Register address =
6163       arg1.is(regs_.address()) ? kScratchRegister : regs_.address();
6164   ASSERT(!address.is(regs_.object()));
6165   ASSERT(!address.is(arg1));
6166   __ Move(address, regs_.address());
6167   __ Move(arg1, regs_.object());
6168   if (mode == INCREMENTAL_COMPACTION) {
6169     // TODO(gc) Can we just set address arg2 in the beginning?
6170     __ Move(arg2, address);
6171   } else {
6172     ASSERT(mode == INCREMENTAL);
6173     __ movq(arg2, Operand(address, 0));
6174   }
6175   __ LoadAddress(arg3, ExternalReference::isolate_address());
6176   int argument_count = 3;
6177
6178   AllowExternalCallThatCantCauseGC scope(masm);
6179   __ PrepareCallCFunction(argument_count);
6180   if (mode == INCREMENTAL_COMPACTION) {
6181     __ CallCFunction(
6182         ExternalReference::incremental_evacuation_record_write_function(
6183             masm->isolate()),
6184         argument_count);
6185   } else {
6186     ASSERT(mode == INCREMENTAL);
6187     __ CallCFunction(
6188         ExternalReference::incremental_marking_record_write_function(
6189             masm->isolate()),
6190         argument_count);
6191   }
6192   regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_);
6193 }
6194
6195
6196 void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
6197     MacroAssembler* masm,
6198     OnNoNeedToInformIncrementalMarker on_no_need,
6199     Mode mode) {
6200   Label on_black;
6201   Label need_incremental;
6202   Label need_incremental_pop_object;
6203
6204   // Let's look at the color of the object:  If it is not black we don't have
6205   // to inform the incremental marker.
6206   __ JumpIfBlack(regs_.object(),
6207                  regs_.scratch0(),
6208                  regs_.scratch1(),
6209                  &on_black,
6210                  Label::kNear);
6211
6212   regs_.Restore(masm);
6213   if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
6214     __ RememberedSetHelper(object_,
6215                            address_,
6216                            value_,
6217                            save_fp_regs_mode_,
6218                            MacroAssembler::kReturnAtEnd);
6219   } else {
6220     __ ret(0);
6221   }
6222
6223   __ bind(&on_black);
6224
6225   // Get the value from the slot.
6226   __ movq(regs_.scratch0(), Operand(regs_.address(), 0));
6227
6228   if (mode == INCREMENTAL_COMPACTION) {
6229     Label ensure_not_white;
6230
6231     __ CheckPageFlag(regs_.scratch0(),  // Contains value.
6232                      regs_.scratch1(),  // Scratch.
6233                      MemoryChunk::kEvacuationCandidateMask,
6234                      zero,
6235                      &ensure_not_white,
6236                      Label::kNear);
6237
6238     __ CheckPageFlag(regs_.object(),
6239                      regs_.scratch1(),  // Scratch.
6240                      MemoryChunk::kSkipEvacuationSlotsRecordingMask,
6241                      zero,
6242                      &need_incremental);
6243
6244     __ bind(&ensure_not_white);
6245   }
6246
6247   // We need an extra register for this, so we push the object register
6248   // temporarily.
6249   __ push(regs_.object());
6250   __ EnsureNotWhite(regs_.scratch0(),  // The value.
6251                     regs_.scratch1(),  // Scratch.
6252                     regs_.object(),  // Scratch.
6253                     &need_incremental_pop_object,
6254                     Label::kNear);
6255   __ pop(regs_.object());
6256
6257   regs_.Restore(masm);
6258   if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
6259     __ RememberedSetHelper(object_,
6260                            address_,
6261                            value_,
6262                            save_fp_regs_mode_,
6263                            MacroAssembler::kReturnAtEnd);
6264   } else {
6265     __ ret(0);
6266   }
6267
6268   __ bind(&need_incremental_pop_object);
6269   __ pop(regs_.object());
6270
6271   __ bind(&need_incremental);
6272
6273   // Fall through when we need to inform the incremental marker.
6274 }
6275
6276
6277 void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
6278   // ----------- S t a t e -------------
6279   //  -- rax    : element value to store
6280   //  -- rbx    : array literal
6281   //  -- rdi    : map of array literal
6282   //  -- rcx    : element index as smi
6283   //  -- rdx    : array literal index in function
6284   //  -- rsp[0] : return address
6285   // -----------------------------------
6286
6287   Label element_done;
6288   Label double_elements;
6289   Label smi_element;
6290   Label slow_elements;
6291   Label fast_elements;
6292
6293   __ CheckFastElements(rdi, &double_elements);
6294
6295   // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
6296   __ JumpIfSmi(rax, &smi_element);
6297   __ CheckFastSmiOnlyElements(rdi, &fast_elements);
6298
6299   // Store into the array literal requires a elements transition. Call into
6300   // the runtime.
6301
6302   __ bind(&slow_elements);
6303   __ pop(rdi);  // Pop return address and remember to put back later for tail
6304                 // call.
6305   __ push(rbx);
6306   __ push(rcx);
6307   __ push(rax);
6308   __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
6309   __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
6310   __ push(rdx);
6311   __ push(rdi);  // Return return address so that tail call returns to right
6312                  // place.
6313   __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
6314
6315   // Array literal has ElementsKind of FAST_ELEMENTS and value is an object.
6316   __ bind(&fast_elements);
6317   __ SmiToInteger32(kScratchRegister, rcx);
6318   __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
6319   __ lea(rcx, FieldOperand(rbx, kScratchRegister, times_pointer_size,
6320                            FixedArrayBase::kHeaderSize));
6321   __ movq(Operand(rcx, 0), rax);
6322   // Update the write barrier for the array store.
6323   __ RecordWrite(rbx, rcx, rax,
6324                  kDontSaveFPRegs,
6325                  EMIT_REMEMBERED_SET,
6326                  OMIT_SMI_CHECK);
6327   __ ret(0);
6328
6329   // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
6330   // FAST_ELEMENTS, and value is Smi.
6331   __ bind(&smi_element);
6332   __ SmiToInteger32(kScratchRegister, rcx);
6333   __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
6334   __ movq(FieldOperand(rbx, kScratchRegister, times_pointer_size,
6335                        FixedArrayBase::kHeaderSize), rax);
6336   __ ret(0);
6337
6338   // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
6339   __ bind(&double_elements);
6340
6341   __ movq(r9, FieldOperand(rbx, JSObject::kElementsOffset));
6342   __ SmiToInteger32(r11, rcx);
6343   __ StoreNumberToDoubleElements(rax,
6344                                  r9,
6345                                  r11,
6346                                  xmm0,
6347                                  &slow_elements);
6348   __ ret(0);
6349 }
6350
6351 #undef __
6352
6353 } }  // namespace v8::internal
6354
6355 #endif  // V8_TARGET_ARCH_X64