Home | History | Annotate | Download | only in x64
      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
   6356