LCOV - code coverage report
Current view: top level - src/crankshaft/x64 - lithium-codegen-x64.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2238 2445 91.5 %
Date: 2017-04-26 Functions: 223 266 83.8 %

          Line data    Source code
       1             : // Copyright 2013 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #if V8_TARGET_ARCH_X64
       6             : 
       7             : #include "src/crankshaft/x64/lithium-codegen-x64.h"
       8             : 
       9             : #include "src/base/bits.h"
      10             : #include "src/builtins/builtins-constructor.h"
      11             : #include "src/code-factory.h"
      12             : #include "src/code-stubs.h"
      13             : #include "src/crankshaft/hydrogen-osr.h"
      14             : #include "src/ic/ic.h"
      15             : #include "src/ic/stub-cache.h"
      16             : #include "src/objects-inl.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : 
      21             : 
      22             : // When invoking builtins, we need to record the safepoint in the middle of
      23             : // the invoke instruction sequence generated by the macro assembler.
      24             : class SafepointGenerator final : public CallWrapper {
      25             :  public:
      26             :   SafepointGenerator(LCodeGen* codegen,
      27             :                      LPointerMap* pointers,
      28             :                      Safepoint::DeoptMode mode)
      29             :       : codegen_(codegen),
      30             :         pointers_(pointers),
      31      865338 :         deopt_mode_(mode) { }
      32           0 :   virtual ~SafepointGenerator() {}
      33             : 
      34       22524 :   void BeforeCall(int call_size) const override {}
      35             : 
      36      869947 :   void AfterCall() const override {
      37      869947 :     codegen_->RecordSafepoint(pointers_, deopt_mode_);
      38      869949 :   }
      39             : 
      40             :  private:
      41             :   LCodeGen* codegen_;
      42             :   LPointerMap* pointers_;
      43             :   Safepoint::DeoptMode deopt_mode_;
      44             : };
      45             : 
      46             : 
      47             : #define __ masm()->
      48             : 
      49      278815 : bool LCodeGen::GenerateCode() {
      50             :   LPhase phase("Z_Code generation", chunk());
      51             :   DCHECK(is_unused());
      52      278816 :   status_ = GENERATING;
      53             : 
      54             :   // Open a frame scope to indicate that there is a frame on the stack.  The
      55             :   // MANUAL indicates that the scope shouldn't actually generate code to set up
      56             :   // the frame (that is done in GeneratePrologue).
      57      557632 :   FrameScope frame_scope(masm_, StackFrame::MANUAL);
      58             : 
      59      557630 :   return GeneratePrologue() &&
      60      557597 :       GenerateBody() &&
      61      557564 :       GenerateDeferredCode() &&
      62      836380 :       GenerateJumpTable() &&
      63      278815 :       GenerateSafepointTable();
      64             : }
      65             : 
      66             : 
      67      278783 : void LCodeGen::FinishCode(Handle<Code> code) {
      68             :   DCHECK(is_done());
      69      557566 :   code->set_stack_slots(GetTotalFrameSlotCount());
      70      557566 :   code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
      71      278783 :   PopulateDeoptimizationData(code);
      72      278783 : }
      73             : 
      74             : 
      75             : #ifdef _MSC_VER
      76             : void LCodeGen::MakeSureStackPagesMapped(int offset) {
      77             :   const int kPageSize = 4 * KB;
      78             :   for (offset -= kPageSize; offset > 0; offset -= kPageSize) {
      79             :     __ movp(Operand(rsp, offset), rax);
      80             :   }
      81             : }
      82             : #endif
      83             : 
      84             : 
      85         110 : void LCodeGen::SaveCallerDoubles() {
      86             :   DCHECK(info()->saves_caller_doubles());
      87             :   DCHECK(NeedsEagerFrame());
      88         134 :   Comment(";;; Save clobbered callee double registers");
      89             :   int count = 0;
      90          55 :   BitVector* doubles = chunk()->allocated_double_registers();
      91             :   BitVector::Iterator save_iterator(doubles);
      92         268 :   while (!save_iterator.Done()) {
      93             :     __ Movsd(MemOperand(rsp, count * kDoubleSize),
      94         158 :              XMMRegister::from_code(save_iterator.Current()));
      95          79 :     save_iterator.Advance();
      96          79 :     count++;
      97             :   }
      98          55 : }
      99             : 
     100             : 
     101         362 : void LCodeGen::RestoreCallerDoubles() {
     102             :   DCHECK(info()->saves_caller_doubles());
     103             :   DCHECK(NeedsEagerFrame());
     104         458 :   Comment(";;; Restore clobbered callee double registers");
     105         181 :   BitVector* doubles = chunk()->allocated_double_registers();
     106             :   BitVector::Iterator save_iterator(doubles);
     107             :   int count = 0;
     108        1097 :   while (!save_iterator.Done()) {
     109             :     __ Movsd(XMMRegister::from_code(save_iterator.Current()),
     110         554 :              MemOperand(rsp, count * kDoubleSize));
     111         277 :     save_iterator.Advance();
     112         277 :     count++;
     113             :   }
     114         181 : }
     115             : 
     116             : 
     117      278816 : bool LCodeGen::GeneratePrologue() {
     118             :   DCHECK(is_generating());
     119             : 
     120     1877819 :   if (info()->IsOptimizing()) {
     121      255333 :     ProfileEntryHookStub::MaybeCallEntryHook(masm_);
     122             :   }
     123             : 
     124      278815 :   info()->set_prologue_offset(masm_->pc_offset());
     125      278815 :   if (NeedsEagerFrame()) {
     126             :     DCHECK(!frame_is_built_);
     127      260248 :     frame_is_built_ = true;
     128      260248 :     if (info()->IsStub()) {
     129        4915 :       __ StubPrologue(StackFrame::STUB);
     130             :     } else {
     131      510665 :       __ Prologue(info()->GeneratePreagedPrologue());
     132             :     }
     133             :   }
     134             : 
     135             :   // Reserve space for the stack slots needed by the code.
     136             :   int slots = GetStackSlotCount();
     137      278815 :   if (slots > 0) {
     138      260247 :     if (FLAG_debug_code) {
     139          96 :       __ subp(rsp, Immediate(slots * kPointerSize));
     140             : #ifdef _MSC_VER
     141             :       MakeSureStackPagesMapped(slots * kPointerSize);
     142             : #endif
     143          48 :       __ Push(rax);
     144          96 :       __ Set(rax, slots);
     145          48 :       __ Set(kScratchRegister, kSlotsZapValue);
     146             :       Label loop;
     147          48 :       __ bind(&loop);
     148             :       __ movp(MemOperand(rsp, rax, times_pointer_size, 0),
     149         144 :               kScratchRegister);
     150          48 :       __ decl(rax);
     151          48 :       __ j(not_zero, &loop);
     152          48 :       __ Pop(rax);
     153             :     } else {
     154      520398 :       __ subp(rsp, Immediate(slots * kPointerSize));
     155             : #ifdef _MSC_VER
     156             :       MakeSureStackPagesMapped(slots * kPointerSize);
     157             : #endif
     158             :     }
     159             : 
     160      260247 :     if (info()->saves_caller_doubles()) {
     161          55 :       SaveCallerDoubles();
     162             :     }
     163             :   }
     164      278815 :   return !is_aborted();
     165             : }
     166             : 
     167             : 
     168      255331 : void LCodeGen::DoPrologue(LPrologue* instr) {
     169      322140 :   Comment(";;; Prologue begin");
     170             : 
     171             :   // Possibly allocate a local context.
     172      510666 :   if (info_->scope()->NeedsContext()) {
     173        6471 :     Comment(";;; Allocate local context");
     174             :     bool need_write_barrier = true;
     175             :     // Argument to NewContext is the function, which is still in rdi.
     176        6471 :     int slots = info_->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
     177             :     Safepoint::DeoptMode deopt_mode = Safepoint::kNoLazyDeopt;
     178        6471 :     if (info()->scope()->is_script_scope()) {
     179         532 :       __ Push(rdi);
     180        1064 :       __ Push(info()->scope()->scope_info());
     181         532 :       __ CallRuntime(Runtime::kNewScriptContext);
     182             :       deopt_mode = Safepoint::kLazyDeopt;
     183             :     } else {
     184        5939 :       if (slots <= ConstructorBuiltins::MaximumFunctionContextSlots()) {
     185             :         Callable callable = CodeFactory::FastNewFunctionContext(
     186        5939 :             isolate(), info()->scope()->scope_type());
     187       11878 :         __ Set(FastNewFunctionContextDescriptor::SlotsRegister(), slots);
     188        5939 :         __ Call(callable.code(), RelocInfo::CODE_TARGET);
     189             :         // Result of FastNewFunctionContextStub is always in new space.
     190             :         need_write_barrier = false;
     191             :       } else {
     192           0 :         __ Push(rdi);
     193           0 :         __ Push(Smi::FromInt(info()->scope()->scope_type()));
     194           0 :         __ CallRuntime(Runtime::kNewFunctionContext);
     195             :       }
     196             :     }
     197        6471 :     RecordSafepoint(deopt_mode);
     198             : 
     199             :     // Context is returned in rax.  It replaces the context passed to us.
     200             :     // It's saved in the stack and kept live in rsi.
     201        6471 :     __ movp(rsi, rax);
     202       19413 :     __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax);
     203             : 
     204             :     // Copy any necessary parameters into the context.
     205        6471 :     int num_parameters = info()->scope()->num_parameters();
     206       12942 :     int first_parameter = info()->scope()->has_this_declaration() ? -1 : 0;
     207       15166 :     for (int i = first_parameter; i < num_parameters; i++) {
     208        6776 :       Variable* var = (i == -1) ? info()->scope()->receiver()
     209       13521 :                                 : info()->scope()->parameter(i);
     210        8695 :       if (var->IsContextSlot()) {
     211        2907 :         int parameter_offset = StandardFrameConstants::kCallerSPOffset +
     212        5814 :             (num_parameters - 1 - i) * kPointerSize;
     213             :         // Load parameter from stack.
     214        8721 :         __ movp(rax, Operand(rbp, parameter_offset));
     215             :         // Store it in the context.
     216             :         int context_offset = Context::SlotOffset(var->index());
     217        8721 :         __ movp(Operand(rsi, context_offset), rax);
     218             :         // Update the write barrier. This clobbers rax and rbx.
     219        2907 :         if (need_write_barrier) {
     220             :           __ RecordWriteContextSlot(rsi, context_offset, rax, rbx, kSaveFPRegs);
     221        2907 :         } else if (FLAG_debug_code) {
     222             :           Label done;
     223             :           __ JumpIfInNewSpace(rsi, rax, &done, Label::kNear);
     224           0 :           __ Abort(kExpectedNewSpaceObject);
     225           0 :           __ bind(&done);
     226             :         }
     227             :       }
     228             :     }
     229        6471 :     Comment(";;; End allocate local context");
     230             :   }
     231             : 
     232      255333 :   Comment(";;; Prologue end");
     233      255331 : }
     234             : 
     235             : 
     236       16440 : void LCodeGen::GenerateOsrPrologue() {
     237             :   // Generate the OSR entry prologue at the first unknown OSR value, or if there
     238             :   // are none, at the OSR entrypoint instruction.
     239       32880 :   if (osr_pc_offset_ >= 0) return;
     240             : 
     241        4730 :   osr_pc_offset_ = masm()->pc_offset();
     242             : 
     243             :   // Adjust the frame size, subsuming the unoptimized frame into the
     244             :   // optimized frame.
     245        2365 :   int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots();
     246             :   DCHECK(slots >= 0);
     247        4730 :   __ subp(rsp, Immediate(slots * kPointerSize));
     248             : }
     249             : 
     250             : 
     251    30787701 : void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
     252    30787701 :   if (instr->IsCall()) {
     253     1675209 :     EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
     254             :   }
     255    30787691 :   if (!instr->IsLazyBailout() && !instr->IsGap()) {
     256             :     safepoints_.BumpLastLazySafepointIndex();
     257             :   }
     258    30787667 : }
     259             : 
     260             : 
     261    37916926 : void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) {
     262             :   if (FLAG_debug_code && FLAG_enable_slow_asserts && instr->HasResult() &&
     263             :       instr->hydrogen_value()->representation().IsInteger32() &&
     264             :       instr->result()->IsRegister()) {
     265        8489 :     __ AssertZeroExtended(ToRegister(instr->result()));
     266             :   }
     267             : 
     268    37916926 :   if (instr->HasResult() && instr->MustSignExtendResult(chunk())) {
     269             :     // We sign extend the dehoisted key at the definition point when the pointer
     270             :     // size is 64-bit. For x32 port, we sign extend the dehoisted key at the use
     271             :     // points and MustSignExtendResult is always false. We can't use
     272             :     // STATIC_ASSERT here as the pointer size is 32-bit for x32.
     273             :     DCHECK(kPointerSize == kInt64Size);
     274       16978 :     if (instr->result()->IsRegister()) {
     275       16978 :       Register result_reg = ToRegister(instr->result());
     276        8489 :       __ movsxlq(result_reg, result_reg);
     277             :     } else {
     278             :       // Sign extend the 32bit result in the stack slots.
     279             :       DCHECK(instr->result()->IsStackSlot());
     280           0 :       Operand src = ToOperand(instr->result());
     281           0 :       __ movsxlq(kScratchRegister, src);
     282           0 :       __ movq(src, kScratchRegister);
     283             :     }
     284             :   }
     285    30787693 : }
     286             : 
     287             : 
     288      278782 : bool LCodeGen::GenerateJumpTable() {
     289     3436695 :   if (jump_table_.length() == 0) return !is_aborted();
     290             : 
     291             :   Label needs_frame;
     292      113401 :   Comment(";;; -------------------- Jump table --------------------");
     293     1340280 :   for (int i = 0; i < jump_table_.length(); i++) {
     294             :     Deoptimizer::JumpTableEntry* table_entry = &jump_table_[i];
     295     1113478 :     __ bind(&table_entry->label);
     296      556739 :     Address entry = table_entry->address;
     297      556739 :     DeoptComment(table_entry->deopt_info);
     298      556739 :     if (table_entry->needs_frame) {
     299             :       DCHECK(!info()->saves_caller_doubles());
     300       24106 :       __ Move(kScratchRegister, ExternalReference::ForDeoptEntry(entry));
     301       24106 :       __ call(&needs_frame);
     302             :     } else {
     303      532633 :       if (info()->saves_caller_doubles()) {
     304             :         DCHECK(info()->IsStub());
     305         126 :         RestoreCallerDoubles();
     306             :       }
     307      532633 :       __ call(entry, RelocInfo::RUNTIME_ENTRY);
     308             :     }
     309             :   }
     310             : 
     311      113401 :   if (needs_frame.is_linked()) {
     312       18427 :     __ bind(&needs_frame);
     313             :     /* stack layout
     314             :        3: return address  <-- rsp
     315             :        2: garbage
     316             :        1: garbage
     317             :        0: garbage
     318             :     */
     319             :     // Reserve space for stub marker.
     320       18427 :     __ subp(rsp, Immediate(TypedFrameConstants::kFrameTypeSize));
     321             :     __ Push(MemOperand(
     322       36854 :         rsp, TypedFrameConstants::kFrameTypeSize));  // Copy return address.
     323       18427 :     __ Push(kScratchRegister);
     324             : 
     325             :     /* stack layout
     326             :        3: return address
     327             :        2: garbage
     328             :        1: return address
     329             :        0: entry address  <-- rsp
     330             :     */
     331             : 
     332             :     // Create a stack frame.
     333       55281 :     __ movp(MemOperand(rsp, 3 * kPointerSize), rbp);
     334       55281 :     __ leap(rbp, MemOperand(rsp, 3 * kPointerSize));
     335             : 
     336             :     // This variant of deopt can only be used with stubs. Since we don't
     337             :     // have a function pointer to install in the stack frame that we're
     338             :     // building, install a special marker there instead.
     339             :     DCHECK(info()->IsStub());
     340             :     __ movp(MemOperand(rsp, 2 * kPointerSize),
     341       55281 :             Immediate(StackFrame::TypeToMarker(StackFrame::STUB)));
     342             : 
     343             :     /* stack layout
     344             :        3: old rbp
     345             :        2: stub marker
     346             :        1: return address
     347             :        0: entry address  <-- rsp
     348             :     */
     349       18427 :     __ ret(0);
     350             :   }
     351             : 
     352      113401 :   return !is_aborted();
     353             : }
     354             : 
     355             : 
     356      278782 : bool LCodeGen::GenerateDeferredCode() {
     357             :   DCHECK(is_generating());
     358      490527 :   if (deferred_.length() > 0) {
     359      577336 :     for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
     360      307692 :       LDeferredCode* code = deferred_[i];
     361             : 
     362             :       HValue* value =
     363      307692 :           instructions_->at(code->instruction_index())->hydrogen_value();
     364     1246723 :       RecordAndWritePosition(value->position());
     365             : 
     366             :       Comment(";;; <@%d,#%d> "
     367             :               "-------------------- Deferred %s --------------------",
     368             :               code->instruction_index(),
     369      153846 :               code->instr()->hydrogen_value()->id(),
     370      461538 :               code->instr()->Mnemonic());
     371      307692 :       __ bind(code->entry());
     372      153846 :       if (NeedsDeferredFrame()) {
     373        2646 :         Comment(";;; Build frame");
     374             :         DCHECK(!frame_is_built_);
     375             :         DCHECK(info()->IsStub());
     376        2646 :         frame_is_built_ = true;
     377             :         // Build the frame in such a way that esi isn't trashed.
     378        2646 :         __ pushq(rbp);  // Caller's frame pointer.
     379        2646 :         __ Push(Immediate(StackFrame::TypeToMarker(StackFrame::STUB)));
     380        7938 :         __ leap(rbp, Operand(rsp, TypedFrameConstants::kFixedFrameSizeFromFp));
     381        2646 :         Comment(";;; Deferred code");
     382             :       }
     383      153846 :       code->Generate();
     384      153846 :       if (NeedsDeferredFrame()) {
     385        2646 :         __ bind(code->done());
     386        2646 :         Comment(";;; Destroy frame");
     387             :         DCHECK(frame_is_built_);
     388        2646 :         frame_is_built_ = false;
     389        2646 :         __ movp(rsp, rbp);
     390        2646 :         __ popq(rbp);
     391             :       }
     392      153846 :       __ jmp(code->exit());
     393             :     }
     394             :   }
     395             : 
     396             :   // Deferred code is the last part of the instruction sequence. Mark
     397             :   // the generated code as done unless we bailed out.
     398      278782 :   if (!is_aborted()) status_ = DONE;
     399      278782 :   return !is_aborted();
     400             : }
     401             : 
     402             : 
     403           0 : bool LCodeGen::GenerateSafepointTable() {
     404             :   DCHECK(is_done());
     405      278782 :   safepoints_.Emit(masm(), GetTotalFrameSlotCount());
     406           0 :   return !is_aborted();
     407             : }
     408             : 
     409             : 
     410           0 : Register LCodeGen::ToRegister(int index) const {
     411           0 :   return Register::from_code(index);
     412             : }
     413             : 
     414             : 
     415           0 : XMMRegister LCodeGen::ToDoubleRegister(int index) const {
     416           0 :   return XMMRegister::from_code(index);
     417             : }
     418             : 
     419             : 
     420     6047490 : Register LCodeGen::ToRegister(LOperand* op) const {
     421             :   DCHECK(op->IsRegister());
     422     6047490 :   return ToRegister(op->index());
     423             : }
     424             : 
     425             : 
     426      158502 : XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
     427             :   DCHECK(op->IsDoubleRegister());
     428      158502 :   return ToDoubleRegister(op->index());
     429             : }
     430             : 
     431             : 
     432      252999 : bool LCodeGen::IsInteger32Constant(LConstantOperand* op) const {
     433      505998 :   return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32();
     434             : }
     435             : 
     436             : 
     437           0 : bool LCodeGen::IsExternalConstant(LConstantOperand* op) const {
     438      152306 :   return chunk_->LookupLiteralRepresentation(op).IsExternal();
     439             : }
     440             : 
     441             : 
     442       29269 : bool LCodeGen::IsDehoistedKeyConstant(LConstantOperand* op) const {
     443       58538 :   return op->IsConstantOperand() &&
     444       58538 :       chunk_->IsDehoistedKey(chunk_->LookupConstant(op));
     445             : }
     446             : 
     447             : 
     448      150782 : bool LCodeGen::IsSmiConstant(LConstantOperand* op) const {
     449      301564 :   return chunk_->LookupLiteralRepresentation(op).IsSmi();
     450             : }
     451             : 
     452             : 
     453       31367 : int32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
     454       31367 :   return ToRepresentation(op, Representation::Integer32());
     455             : }
     456             : 
     457             : 
     458           0 : int32_t LCodeGen::ToRepresentation(LConstantOperand* op,
     459             :                                    const Representation& r) const {
     460      802785 :   HConstant* constant = chunk_->LookupConstant(op);
     461             :   int32_t value = constant->Integer32Value();
     462      188951 :   if (r.IsInteger32()) return value;
     463             :   DCHECK(SmiValuesAre31Bits() && r.IsSmiOrTagged());
     464             :   return static_cast<int32_t>(reinterpret_cast<intptr_t>(Smi::FromInt(value)));
     465             : }
     466             : 
     467             : 
     468           5 : Smi* LCodeGen::ToSmi(LConstantOperand* op) const {
     469          95 :   HConstant* constant = chunk_->LookupConstant(op);
     470           5 :   return Smi::FromInt(constant->Integer32Value());
     471             : }
     472             : 
     473             : 
     474           0 : double LCodeGen::ToDouble(LConstantOperand* op) const {
     475        9119 :   HConstant* constant = chunk_->LookupConstant(op);
     476             :   DCHECK(constant->HasDoubleValue());
     477           0 :   return constant->DoubleValue();
     478             : }
     479             : 
     480             : 
     481           0 : ExternalReference LCodeGen::ToExternalReference(LConstantOperand* op) const {
     482           0 :   HConstant* constant = chunk_->LookupConstant(op);
     483             :   DCHECK(constant->HasExternalReferenceValue());
     484           0 :   return constant->ExternalReferenceValue();
     485             : }
     486             : 
     487             : 
     488     1774554 : Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
     489     1774554 :   HConstant* constant = chunk_->LookupConstant(op);
     490             :   DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
     491     1774554 :   return constant->handle(isolate());
     492             : }
     493             : 
     494             : 
     495             : static int ArgumentsOffsetWithoutFrame(int index) {
     496             :   DCHECK(index < 0);
     497           0 :   return -(index + 1) * kPointerSize + kPCOnStackSize;
     498             : }
     499             : 
     500             : 
     501     3284732 : Operand LCodeGen::ToOperand(LOperand* op) const {
     502             :   // Does not handle registers. In X64 assembler, plain registers are not
     503             :   // representable as an Operand.
     504             :   DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
     505     3284732 :   if (NeedsEagerFrame()) {
     506     3284733 :     return Operand(rbp, FrameSlotToFPOffset(op->index()));
     507             :   } else {
     508             :     // Retrieve parameter without eager stack-frame relative to the
     509             :     // stack-pointer.
     510           0 :     return Operand(rsp, ArgumentsOffsetWithoutFrame(op->index()));
     511             :   }
     512             : }
     513             : 
     514             : 
     515    11491924 : void LCodeGen::WriteTranslation(LEnvironment* environment,
     516             :                                 Translation* translation) {
     517     9242333 :   if (environment == NULL) return;
     518             : 
     519             :   // The translation includes one command per value in the environment.
     520             :   int translation_size = environment->translation_size();
     521             : 
     522     4580505 :   WriteTranslation(environment->outer(), translation);
     523     4580506 :   WriteTranslationFrame(environment, translation);
     524             : 
     525     4580512 :   int object_index = 0;
     526     4580512 :   int dematerialized_index = 0;
     527    33465098 :   for (int i = 0; i < translation_size; ++i) {
     528    28884590 :     LOperand* value = environment->values()->at(i);
     529             :     AddToTranslation(
     530             :         environment, translation, value, environment->HasTaggedValueAt(i),
     531    57769183 :         environment->HasUint32ValueAt(i), &object_index, &dematerialized_index);
     532             :   }
     533             : }
     534             : 
     535             : 
     536    28938646 : void LCodeGen::AddToTranslation(LEnvironment* environment,
     537             :                                 Translation* translation,
     538             :                                 LOperand* op,
     539             :                                 bool is_tagged,
     540             :                                 bool is_uint32,
     541             :                                 int* object_index_pointer,
     542    13226103 :                                 int* dematerialized_index_pointer) {
     543    28926531 :   if (op == LEnvironment::materialization_marker()) {
     544       13611 :     int object_index = (*object_index_pointer)++;
     545       13611 :     if (environment->ObjectIsDuplicateAt(object_index)) {
     546             :       int dupe_of = environment->ObjectDuplicateOfAt(object_index);
     547        1496 :       translation->DuplicateObject(dupe_of);
     548        1496 :       return;
     549             :     }
     550             :     int object_length = environment->ObjectLengthAt(object_index);
     551       12115 :     if (environment->ObjectIsArgumentsAt(object_index)) {
     552        6395 :       translation->BeginArgumentsObject(object_length);
     553             :     } else {
     554        5720 :       translation->BeginCapturedObject(object_length);
     555             :     }
     556       12115 :     int dematerialized_index = *dematerialized_index_pointer;
     557       12115 :     int env_offset = environment->translation_size() + dematerialized_index;
     558       12115 :     *dematerialized_index_pointer += object_length;
     559       54045 :     for (int i = 0; i < object_length; ++i) {
     560       83860 :       LOperand* value = environment->values()->at(env_offset + i);
     561             :       AddToTranslation(environment,
     562             :                        translation,
     563             :                        value,
     564             :                        environment->HasTaggedValueAt(env_offset + i),
     565             :                        environment->HasUint32ValueAt(env_offset + i),
     566             :                        object_index_pointer,
     567       83860 :                        dematerialized_index_pointer);
     568             :     }
     569             :     return;
     570             :   }
     571             : 
     572    28912920 :   if (op->IsStackSlot()) {
     573             :     int index = op->index();
     574    13324615 :     if (is_tagged) {
     575    12810584 :       translation->StoreStackSlot(index);
     576      514031 :     } else if (is_uint32) {
     577        1833 :       translation->StoreUint32StackSlot(index);
     578             :     } else {
     579      512198 :       translation->StoreInt32StackSlot(index);
     580             :     }
     581    15588305 :   } else if (op->IsDoubleStackSlot()) {
     582             :     int index = op->index();
     583      131287 :     translation->StoreDoubleStackSlot(index);
     584    15457018 :   } else if (op->IsRegister()) {
     585     2200527 :     Register reg = ToRegister(op);
     586     2200527 :     if (is_tagged) {
     587     2068703 :       translation->StoreRegister(reg);
     588      131824 :     } else if (is_uint32) {
     589          90 :       translation->StoreUint32Register(reg);
     590             :     } else {
     591      131734 :       translation->StoreInt32Register(reg);
     592             :     }
     593    13256491 :   } else if (op->IsDoubleRegister()) {
     594       30388 :     XMMRegister reg = ToDoubleRegister(op);
     595       30388 :     translation->StoreDoubleRegister(reg);
     596    13226103 :   } else if (op->IsConstantOperand()) {
     597    13226103 :     HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
     598    13226103 :     int src_index = DefineDeoptimizationLiteral(constant->handle(isolate()));
     599    13226104 :     translation->StoreLiteral(src_index);
     600             :   } else {
     601           0 :     UNREACHABLE();
     602             :   }
     603             : }
     604             : 
     605             : 
     606      575118 : void LCodeGen::CallCodeGeneric(Handle<Code> code,
     607             :                                RelocInfo::Mode mode,
     608             :                                LInstruction* instr,
     609             :                                SafepointMode safepoint_mode,
     610             :                                int argc) {
     611             :   DCHECK(instr != NULL);
     612      822152 :   __ call(code, mode);
     613      575118 :   RecordSafepointWithLazyDeopt(instr, safepoint_mode, argc);
     614             : 
     615             :   // Signal that we don't inline smi code before these stubs in the
     616             :   // optimizing code generator.
     617      575119 :   if (code->kind() == Code::BINARY_OP_IC ||
     618             :       code->kind() == Code::COMPARE_IC) {
     619      247034 :     __ nop();
     620             :   }
     621      575119 : }
     622             : 
     623             : 
     624           0 : void LCodeGen::CallCode(Handle<Code> code,
     625             :                         RelocInfo::Mode mode,
     626             :                         LInstruction* instr) {
     627      575118 :   CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, 0);
     628           0 : }
     629             : 
     630             : 
     631      116070 : void LCodeGen::CallRuntime(const Runtime::Function* function,
     632             :                            int num_arguments,
     633             :                            LInstruction* instr,
     634             :                            SaveFPRegsMode save_doubles) {
     635             :   DCHECK(instr != NULL);
     636             :   DCHECK(instr->HasPointerMap());
     637             : 
     638      116070 :   __ CallRuntime(function, num_arguments, save_doubles);
     639             : 
     640      116070 :   RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0);
     641      116070 : }
     642             : 
     643             : 
     644       21334 : void LCodeGen::LoadContextFromDeferred(LOperand* context) {
     645       21334 :   if (context->IsRegister()) {
     646        1144 :     if (!ToRegister(context).is(rsi)) {
     647       21279 :       __ movp(rsi, ToRegister(context));
     648             :     }
     649       20190 :   } else if (context->IsStackSlot()) {
     650       28744 :     __ movp(rsi, ToOperand(context));
     651        5818 :   } else if (context->IsConstantOperand()) {
     652             :     HConstant* constant =
     653        5818 :         chunk_->LookupConstant(LConstantOperand::cast(context));
     654       11636 :     __ Move(rsi, Handle<Object>::cast(constant->handle(isolate())));
     655             :   } else {
     656           0 :     UNREACHABLE();
     657             :   }
     658       21334 : }
     659             : 
     660             : 
     661             : 
     662       21334 : void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
     663             :                                        int argc,
     664             :                                        LInstruction* instr,
     665             :                                        LOperand* context) {
     666       21334 :   LoadContextFromDeferred(context);
     667             : 
     668       21334 :   __ CallRuntimeSaveDoubles(id);
     669             :   RecordSafepointWithRegisters(
     670             :       instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
     671       21334 : }
     672             : 
     673             : 
     674     2486409 : void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
     675             :                                                     Safepoint::DeoptMode mode) {
     676     4817326 :   environment->set_has_been_used();
     677     2486409 :   if (!environment->HasBeenRegistered()) {
     678             :     // Physical stack frame layout:
     679             :     // -x ............. -4  0 ..................................... y
     680             :     // [incoming arguments] [spill slots] [pushed outgoing arguments]
     681             : 
     682             :     // Layout of the environment:
     683             :     // 0 ..................................................... size-1
     684             :     // [parameters] [locals] [expression stack including arguments]
     685             : 
     686             :     // Layout of the translation:
     687             :     // 0 ........................................................ size - 1 + 4
     688             :     // [expression stack including arguments] [locals] [4 words] [parameters]
     689             :     // |>------------  translation_size ------------<|
     690             : 
     691             :     int frame_count = 0;
     692             :     int jsframe_count = 0;
     693     9161008 :     for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
     694     4580504 :       ++frame_count;
     695     4580504 :       if (e->frame_type() == JS_FUNCTION) {
     696     3988397 :         ++jsframe_count;
     697             :       }
     698             :     }
     699     4661830 :     Translation translation(&translations_, frame_count, jsframe_count, zone());
     700     2330915 :     WriteTranslation(environment, &translation);
     701     2330917 :     int deoptimization_index = deoptimizations_.length();
     702     2330917 :     int pc_offset = masm()->pc_offset();
     703             :     environment->Register(deoptimization_index,
     704             :                           translation.index(),
     705     2330917 :                           (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
     706             :     deoptimizations_.Add(environment, environment->zone());
     707             :   }
     708     2486413 : }
     709             : 
     710      777716 : void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
     711             :                             DeoptimizeReason deopt_reason,
     712             :                             Deoptimizer::BailoutType bailout_type) {
     713      777716 :   LEnvironment* environment = instr->environment();
     714      777716 :   RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
     715             :   DCHECK(environment->HasBeenRegistered());
     716             :   int id = environment->deoptimization_index();
     717             :   Address entry =
     718     2972404 :       Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
     719      777716 :   if (entry == NULL) {
     720           0 :     Abort(kBailoutWasNotPrepared);
     721      777716 :     return;
     722             :   }
     723             : 
     724      777716 :   if (DeoptEveryNTimes()) {
     725         332 :     ExternalReference count = ExternalReference::stress_deopt_count(isolate());
     726             :     Label no_deopt;
     727         332 :     __ pushfq();
     728         332 :     __ pushq(rax);
     729         332 :     Operand count_operand = masm()->ExternalOperand(count, kScratchRegister);
     730         332 :     __ movl(rax, count_operand);
     731         332 :     __ subl(rax, Immediate(1));
     732         332 :     __ j(not_zero, &no_deopt, Label::kNear);
     733         332 :     if (FLAG_trap_on_deopt) __ int3();
     734         664 :     __ movl(rax, Immediate(FLAG_deopt_every_n_times));
     735         332 :     __ movl(count_operand, rax);
     736         332 :     __ popq(rax);
     737         332 :     __ popfq();
     738             :     DCHECK(frame_is_built_);
     739         332 :     __ call(entry, RelocInfo::RUNTIME_ENTRY);
     740         332 :     __ bind(&no_deopt);
     741         332 :     __ movl(count_operand, rax);
     742         332 :     __ popq(rax);
     743         332 :     __ popfq();
     744             :   }
     745             : 
     746      777716 :   if (info()->ShouldTrapOnDeopt()) {
     747             :     Label done;
     748           0 :     if (cc != no_condition) {
     749           0 :       __ j(NegateCondition(cc), &done, Label::kNear);
     750             :     }
     751           0 :     __ int3();
     752           0 :     __ bind(&done);
     753             :   }
     754             : 
     755      777716 :   Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason, id);
     756             : 
     757             :   DCHECK(info()->IsStub() || frame_is_built_);
     758             :   // Go through jump table if we need to handle condition, build frame, or
     759             :   // restore caller doubles.
     760      855010 :   if (cc == no_condition && frame_is_built_ &&
     761             :       !info()->saves_caller_doubles()) {
     762       77294 :     DeoptComment(deopt_info);
     763       77294 :     __ call(entry, RelocInfo::RUNTIME_ENTRY);
     764             :   } else {
     765             :     Deoptimizer::JumpTableEntry table_entry(entry, deopt_info, bailout_type,
     766      700422 :                                             !frame_is_built_);
     767             :     // We often have several deopts to the same entry, reuse the last
     768             :     // jump entry if this is the case.
     769     2101027 :     if (FLAG_trace_deopt || isolate()->is_profiling() ||
     770     1987431 :         jump_table_.is_empty() ||
     771             :         !table_entry.IsEquivalentTo(jump_table_.last())) {
     772             :       jump_table_.Add(table_entry, zone());
     773             :     }
     774      700422 :     if (cc == no_condition) {
     775       28158 :       __ jmp(&jump_table_.last().label);
     776             :     } else {
     777     1372686 :       __ j(cc, &jump_table_.last().label);
     778             :     }
     779             :   }
     780             : }
     781             : 
     782           0 : void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
     783             :                             DeoptimizeReason deopt_reason) {
     784      745809 :   Deoptimizer::BailoutType bailout_type = info()->IsStub()
     785             :       ? Deoptimizer::LAZY
     786      745809 :       : Deoptimizer::EAGER;
     787      745809 :   DeoptimizeIf(cc, instr, deopt_reason, bailout_type);
     788           0 : }
     789             : 
     790             : 
     791      833484 : void LCodeGen::RecordSafepointWithLazyDeopt(
     792             :     LInstruction* instr, SafepointMode safepoint_mode, int argc) {
     793      833484 :   if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
     794             :     RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
     795             :   } else {
     796             :     DCHECK(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS);
     797             :     RecordSafepointWithRegisters(
     798             :         instr->pointer_map(), argc, Safepoint::kLazyDeopt);
     799             :   }
     800      833485 : }
     801             : 
     802             : 
     803     1760447 : void LCodeGen::RecordSafepoint(
     804             :     LPointerMap* pointers,
     805             :     Safepoint::Kind kind,
     806             :     int arguments,
     807             :     Safepoint::DeoptMode deopt_mode) {
     808             :   DCHECK(kind == expected_safepoint_kind_);
     809             : 
     810     1760447 :   const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands();
     811             : 
     812     7229937 :   Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
     813     1760447 :       kind, arguments, deopt_mode);
     814    23252522 :   for (int i = 0; i < operands->length(); i++) {
     815    21492071 :     LOperand* pointer = operands->at(i);
     816     9865810 :     if (pointer->IsStackSlot()) {
     817     5311855 :       safepoint.DefinePointerSlot(pointer->index(), zone());
     818     4553955 :     } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
     819      157635 :       safepoint.DefinePointerRegister(ToRegister(pointer), zone());
     820             :     }
     821             :   }
     822     1760451 : }
     823             : 
     824             : 
     825           0 : void LCodeGen::RecordSafepoint(LPointerMap* pointers,
     826             :                                Safepoint::DeoptMode deopt_mode) {
     827     1675847 :   RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode);
     828           0 : }
     829             : 
     830             : 
     831        6471 : void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) {
     832        6471 :   LPointerMap empty_pointers(zone());
     833             :   RecordSafepoint(&empty_pointers, deopt_mode);
     834        6471 : }
     835             : 
     836             : 
     837           0 : void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
     838             :                                             int arguments,
     839             :                                             Safepoint::DeoptMode deopt_mode) {
     840       84601 :   RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, deopt_mode);
     841           0 : }
     842             : 
     843             : 
     844             : static const char* LabelType(LLabel* label) {
     845     2013017 :   if (label->is_loop_header()) return " (loop header)";
     846     1962514 :   if (label->is_osr_entry()) return " (OSR entry)";
     847             :   return "";
     848             : }
     849             : 
     850             : 
     851     2013017 : void LCodeGen::DoLabel(LLabel* label) {
     852             :   Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------",
     853             :           current_instruction_,
     854             :           label->hydrogen_value()->id(),
     855             :           label->block_id(),
     856     4026033 :           LabelType(label));
     857     4026032 :   __ bind(label->label());
     858     2013015 :   current_block_ = label->block_id();
     859     2013015 :   DoGap(label);
     860     2013015 : }
     861             : 
     862             : 
     863           0 : void LCodeGen::DoParallelMove(LParallelMove* move) {
     864    24528529 :   resolver_.Resolve(move);
     865           0 : }
     866             : 
     867             : 
     868    17406858 : void LCodeGen::DoGap(LGap* gap) {
     869    87034205 :   for (int i = LGap::FIRST_INNER_POSITION;
     870             :        i <= LGap::LAST_INNER_POSITION;
     871             :        i++) {
     872             :     LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
     873             :     LParallelMove* move = gap->GetParallelMove(inner_pos);
     874    69627315 :     if (move != NULL) DoParallelMove(move);
     875             :   }
     876    17406890 : }
     877             : 
     878             : 
     879    15393872 : void LCodeGen::DoInstructionGap(LInstructionGap* instr) {
     880    15393872 :   DoGap(instr);
     881    15393883 : }
     882             : 
     883             : 
     884      449915 : void LCodeGen::DoParameter(LParameter* instr) {
     885             :   // Nothing to do.
     886      449915 : }
     887             : 
     888             : 
     889       14075 : void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
     890       14075 :   GenerateOsrPrologue();
     891       14075 : }
     892             : 
     893             : 
     894        2128 : void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
     895             :   Register dividend = ToRegister(instr->dividend());
     896             :   int32_t divisor = instr->divisor();
     897             :   DCHECK(dividend.is(ToRegister(instr->result())));
     898             : 
     899             :   // Theoretically, a variation of the branch-free code for integer division by
     900             :   // a power of 2 (calculating the remainder via an additional multiplication
     901             :   // (which gets simplified to an 'and') and subtraction) should be faster, and
     902             :   // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to
     903             :   // indicate that positive dividends are heavily favored, so the branching
     904             :   // version performs better.
     905             :   HMod* hmod = instr->hydrogen();
     906        1064 :   int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
     907             :   Label dividend_is_not_negative, done;
     908        3168 :   if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
     909        9432 :     __ testl(dividend, dividend);
     910        1040 :     __ j(not_sign, &dividend_is_not_negative, Label::kNear);
     911             :     // Note that this is correct even for kMinInt operands.
     912        1040 :     __ negl(dividend);
     913        1040 :     __ andl(dividend, Immediate(mask));
     914        1040 :     __ negl(dividend);
     915        1040 :     if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
     916             :       DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
     917             :     }
     918        1040 :     __ jmp(&done, Label::kNear);
     919             :   }
     920             : 
     921        1064 :   __ bind(&dividend_is_not_negative);
     922        1064 :   __ andl(dividend, Immediate(mask));
     923        1064 :   __ bind(&done);
     924        1064 : }
     925             : 
     926             : 
     927        3134 : void LCodeGen::DoModByConstI(LModByConstI* instr) {
     928             :   Register dividend = ToRegister(instr->dividend());
     929             :   int32_t divisor = instr->divisor();
     930             :   DCHECK(ToRegister(instr->result()).is(rax));
     931             : 
     932        1567 :   if (divisor == 0) {
     933             :     DeoptimizeIf(no_condition, instr, DeoptimizeReason::kDivisionByZero);
     934        1567 :     return;
     935             :   }
     936             : 
     937        4980 :   __ TruncatingDiv(dividend, Abs(divisor));
     938        1566 :   __ imull(rdx, rdx, Immediate(Abs(divisor)));
     939        1566 :   __ movl(rax, dividend);
     940        1566 :   __ subl(rax, rdx);
     941             : 
     942             :   // Check for negative zero.
     943             :   HMod* hmod = instr->hydrogen();
     944        3132 :   if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
     945             :     Label remainder_not_zero;
     946          94 :     __ j(not_zero, &remainder_not_zero, Label::kNear);
     947          94 :     __ cmpl(dividend, Immediate(0));
     948             :     DeoptimizeIf(less, instr, DeoptimizeReason::kMinusZero);
     949          94 :     __ bind(&remainder_not_zero);
     950             :   }
     951             : }
     952             : 
     953             : 
     954         402 : void LCodeGen::DoModI(LModI* instr) {
     955             :   HMod* hmod = instr->hydrogen();
     956             : 
     957             :   Register left_reg = ToRegister(instr->left());
     958             :   DCHECK(left_reg.is(rax));
     959             :   Register right_reg = ToRegister(instr->right());
     960             :   DCHECK(!right_reg.is(rax));
     961             :   DCHECK(!right_reg.is(rdx));
     962         402 :   Register result_reg = ToRegister(instr->result());
     963             :   DCHECK(result_reg.is(rdx));
     964             : 
     965             :   Label done;
     966             :   // Check for x % 0, idiv would signal a divide error. We have to
     967             :   // deopt in this case because we can't return a NaN.
     968        1913 :   if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
     969        4293 :     __ testl(right_reg, right_reg);
     970             :     DeoptimizeIf(zero, instr, DeoptimizeReason::kDivisionByZero);
     971             :   }
     972             : 
     973             :   // Check for kMinInt % -1, idiv would signal a divide error. We
     974             :   // have to deopt if we care about -0, because we can't return that.
     975         402 :   if (hmod->CheckFlag(HValue::kCanOverflow)) {
     976             :     Label no_overflow_possible;
     977         305 :     __ cmpl(left_reg, Immediate(kMinInt));
     978         305 :     __ j(not_zero, &no_overflow_possible, Label::kNear);
     979         305 :     __ cmpl(right_reg, Immediate(-1));
     980         305 :     if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
     981             :       DeoptimizeIf(equal, instr, DeoptimizeReason::kMinusZero);
     982             :     } else {
     983         161 :       __ j(not_equal, &no_overflow_possible, Label::kNear);
     984         161 :       __ Set(result_reg, 0);
     985         161 :       __ jmp(&done, Label::kNear);
     986             :     }
     987         305 :     __ bind(&no_overflow_possible);
     988             :   }
     989             : 
     990             :   // Sign extend dividend in eax into edx:eax, since we are using only the low
     991             :   // 32 bits of the values.
     992         402 :   __ cdq();
     993             : 
     994             :   // If we care about -0, test if the dividend is <0 and the result is 0.
     995         402 :   if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
     996             :     Label positive_left;
     997         165 :     __ testl(left_reg, left_reg);
     998         165 :     __ j(not_sign, &positive_left, Label::kNear);
     999         165 :     __ idivl(right_reg);
    1000         165 :     __ testl(result_reg, result_reg);
    1001             :     DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
    1002         165 :     __ jmp(&done, Label::kNear);
    1003         165 :     __ bind(&positive_left);
    1004             :   }
    1005         402 :   __ idivl(right_reg);
    1006         402 :   __ bind(&done);
    1007         402 : }
    1008             : 
    1009             : 
    1010        1006 : void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
    1011             :   Register dividend = ToRegister(instr->dividend());
    1012             :   int32_t divisor = instr->divisor();
    1013             :   DCHECK(dividend.is(ToRegister(instr->result())));
    1014             : 
    1015             :   // If the divisor is positive, things are easy: There can be no deopts and we
    1016             :   // can simply do an arithmetic right shift.
    1017         768 :   if (divisor == 1) return;
    1018             :   int32_t shift = WhichPowerOf2Abs(divisor);
    1019         503 :   if (divisor > 1) {
    1020        1931 :     __ sarl(dividend, Immediate(shift));
    1021         232 :     return;
    1022             :   }
    1023             : 
    1024             :   // If the divisor is negative, we have to negate and handle edge cases.
    1025         271 :   __ negl(dividend);
    1026         542 :   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
    1027             :     DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
    1028             :   }
    1029             : 
    1030             :   // Dividing by -1 is basically negation, unless we overflow.
    1031         271 :   if (divisor == -1) {
    1032          66 :     if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
    1033             :       DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
    1034             :     }
    1035             :     return;
    1036             :   }
    1037             : 
    1038             :   // If the negation could not overflow, simply shifting is OK.
    1039         476 :   if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
    1040           0 :     __ sarl(dividend, Immediate(shift));
    1041           0 :     return;
    1042             :   }
    1043             : 
    1044             :   Label not_kmin_int, done;
    1045         238 :   __ j(no_overflow, &not_kmin_int, Label::kNear);
    1046         476 :   __ movl(dividend, Immediate(kMinInt / divisor));
    1047         238 :   __ jmp(&done, Label::kNear);
    1048         238 :   __ bind(&not_kmin_int);
    1049         238 :   __ sarl(dividend, Immediate(shift));
    1050         238 :   __ bind(&done);
    1051             : }
    1052             : 
    1053             : 
    1054        3888 : void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
    1055             :   Register dividend = ToRegister(instr->dividend());
    1056             :   int32_t divisor = instr->divisor();
    1057             :   DCHECK(ToRegister(instr->result()).is(rdx));
    1058             : 
    1059        1944 :   if (divisor == 0) {
    1060             :     DeoptimizeIf(no_condition, instr, DeoptimizeReason::kDivisionByZero);
    1061           7 :     return;
    1062             :   }
    1063             : 
    1064             :   // Check for (0 / -x) that will produce negative zero.
    1065             :   HMathFloorOfDiv* hdiv = instr->hydrogen();
    1066        5811 :   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
    1067       20289 :     __ testl(dividend, dividend);
    1068             :     DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
    1069             :   }
    1070             : 
    1071             :   // Easy case: We need no dynamic check for the dividend and the flooring
    1072             :   // division is the same as the truncating division.
    1073        4859 :   if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
    1074         952 :       (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
    1075           0 :     __ TruncatingDiv(dividend, Abs(divisor));
    1076           0 :     if (divisor < 0) __ negl(rdx);
    1077             :     return;
    1078             :   }
    1079             : 
    1080             :   // In the general case we may need to adjust before and after the truncating
    1081             :   // division to get a flooring division.
    1082             :   Register temp = ToRegister(instr->temp3());
    1083             :   DCHECK(!temp.is(dividend) && !temp.is(rax) && !temp.is(rdx));
    1084             :   Label needs_adjustment, done;
    1085        1937 :   __ cmpl(dividend, Immediate(0));
    1086        3874 :   __ j(divisor > 0 ? less : greater, &needs_adjustment, Label::kNear);
    1087        1937 :   __ TruncatingDiv(dividend, Abs(divisor));
    1088        2889 :   if (divisor < 0) __ negl(rdx);
    1089        1937 :   __ jmp(&done, Label::kNear);
    1090        1937 :   __ bind(&needs_adjustment);
    1091        5811 :   __ leal(temp, Operand(dividend, divisor > 0 ? 1 : -1));
    1092        1937 :   __ TruncatingDiv(temp, Abs(divisor));
    1093        2889 :   if (divisor < 0) __ negl(rdx);
    1094        1937 :   __ decl(rdx);
    1095        1937 :   __ bind(&done);
    1096             : }
    1097             : 
    1098             : 
    1099             : // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI.
    1100          71 : void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
    1101             :   HBinaryOperation* hdiv = instr->hydrogen();
    1102             :   Register dividend = ToRegister(instr->dividend());
    1103             :   Register divisor = ToRegister(instr->divisor());
    1104             :   Register remainder = ToRegister(instr->temp());
    1105         142 :   Register result = ToRegister(instr->result());
    1106             :   DCHECK(dividend.is(rax));
    1107             :   DCHECK(remainder.is(rdx));
    1108             :   DCHECK(result.is(rax));
    1109             :   DCHECK(!divisor.is(rax));
    1110             :   DCHECK(!divisor.is(rdx));
    1111             : 
    1112             :   // Check for x / 0.
    1113         284 :   if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
    1114        1153 :     __ testl(divisor, divisor);
    1115             :     DeoptimizeIf(zero, instr, DeoptimizeReason::kDivisionByZero);
    1116             :   }
    1117             : 
    1118             :   // Check for (0 / -x) that will produce negative zero.
    1119          71 :   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
    1120             :     Label dividend_not_zero;
    1121          65 :     __ testl(dividend, dividend);
    1122          65 :     __ j(not_zero, &dividend_not_zero, Label::kNear);
    1123          65 :     __ testl(divisor, divisor);
    1124             :     DeoptimizeIf(sign, instr, DeoptimizeReason::kMinusZero);
    1125          65 :     __ bind(&dividend_not_zero);
    1126             :   }
    1127             : 
    1128             :   // Check for (kMinInt / -1).
    1129          71 :   if (hdiv->CheckFlag(HValue::kCanOverflow)) {
    1130             :     Label dividend_not_min_int;
    1131          65 :     __ cmpl(dividend, Immediate(kMinInt));
    1132          65 :     __ j(not_zero, &dividend_not_min_int, Label::kNear);
    1133          65 :     __ cmpl(divisor, Immediate(-1));
    1134             :     DeoptimizeIf(zero, instr, DeoptimizeReason::kOverflow);
    1135          65 :     __ bind(&dividend_not_min_int);
    1136             :   }
    1137             : 
    1138             :   // Sign extend to rdx (= remainder).
    1139          71 :   __ cdq();
    1140          71 :   __ idivl(divisor);
    1141             : 
    1142             :   Label done;
    1143          71 :   __ testl(remainder, remainder);
    1144          71 :   __ j(zero, &done, Label::kNear);
    1145          71 :   __ xorl(remainder, divisor);
    1146          71 :   __ sarl(remainder, Immediate(31));
    1147          71 :   __ addl(result, remainder);
    1148          71 :   __ bind(&done);
    1149          71 : }
    1150             : 
    1151             : 
    1152        1082 : void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
    1153             :   Register dividend = ToRegister(instr->dividend());
    1154             :   int32_t divisor = instr->divisor();
    1155         541 :   Register result = ToRegister(instr->result());
    1156             :   DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
    1157             :   DCHECK(!result.is(dividend));
    1158             : 
    1159             :   // Check for (0 / -x) that will produce negative zero.
    1160             :   HDiv* hdiv = instr->hydrogen();
    1161        2164 :   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
    1162        2883 :     __ testl(dividend, dividend);
    1163             :     DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
    1164             :   }
    1165             :   // Check for (kMinInt / -1).
    1166         541 :   if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
    1167          30 :     __ cmpl(dividend, Immediate(kMinInt));
    1168             :     DeoptimizeIf(zero, instr, DeoptimizeReason::kOverflow);
    1169             :   }
    1170             :   // Deoptimize if remainder will not be 0.
    1171         541 :   if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
    1172         541 :       divisor != 1 && divisor != -1) {
    1173         129 :     int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
    1174         129 :     __ testl(dividend, Immediate(mask));
    1175             :     DeoptimizeIf(not_zero, instr, DeoptimizeReason::kLostPrecision);
    1176             :   }
    1177         541 :   __ Move(result, dividend);
    1178             :   int32_t shift = WhichPowerOf2Abs(divisor);
    1179         541 :   if (shift > 0) {
    1180             :     // The arithmetic shift is always OK, the 'if' is an optimization only.
    1181         924 :     if (shift > 1) __ sarl(result, Immediate(31));
    1182        1020 :     __ shrl(result, Immediate(32 - shift));
    1183         510 :     __ addl(result, dividend);
    1184         510 :     __ sarl(result, Immediate(shift));
    1185             :   }
    1186         768 :   if (divisor < 0) __ negl(result);
    1187         541 : }
    1188             : 
    1189             : 
    1190        2834 : void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
    1191             :   Register dividend = ToRegister(instr->dividend());
    1192             :   int32_t divisor = instr->divisor();
    1193             :   DCHECK(ToRegister(instr->result()).is(rdx));
    1194             : 
    1195        1417 :   if (divisor == 0) {
    1196             :     DeoptimizeIf(no_condition, instr, DeoptimizeReason::kDivisionByZero);
    1197        1417 :     return;
    1198             :   }
    1199             : 
    1200             :   // Check for (0 / -x) that will produce negative zero.
    1201             :   HDiv* hdiv = instr->hydrogen();
    1202        4251 :   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
    1203        2162 :     __ testl(dividend, dividend);
    1204             :     DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
    1205             :   }
    1206             : 
    1207        1417 :   __ TruncatingDiv(dividend, Abs(divisor));
    1208        2096 :   if (divisor < 0) __ negl(rdx);
    1209             : 
    1210        1417 :   if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
    1211          22 :     __ movl(rax, rdx);
    1212          22 :     __ imull(rax, rax, Immediate(divisor));
    1213          22 :     __ subl(rax, dividend);
    1214             :     DeoptimizeIf(not_equal, instr, DeoptimizeReason::kLostPrecision);
    1215             :   }
    1216             : }
    1217             : 
    1218             : 
    1219             : // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
    1220         450 : void LCodeGen::DoDivI(LDivI* instr) {
    1221             :   HBinaryOperation* hdiv = instr->hydrogen();
    1222             :   Register dividend = ToRegister(instr->dividend());
    1223             :   Register divisor = ToRegister(instr->divisor());
    1224             :   Register remainder = ToRegister(instr->temp());
    1225             :   DCHECK(dividend.is(rax));
    1226             :   DCHECK(remainder.is(rdx));
    1227             :   DCHECK(ToRegister(instr->result()).is(rax));
    1228             :   DCHECK(!divisor.is(rax));
    1229             :   DCHECK(!divisor.is(rdx));
    1230             : 
    1231             :   // Check for x / 0.
    1232        2250 :   if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
    1233        4062 :     __ testl(divisor, divisor);
    1234             :     DeoptimizeIf(zero, instr, DeoptimizeReason::kDivisionByZero);
    1235             :   }
    1236             : 
    1237             :   // Check for (0 / -x) that will produce negative zero.
    1238         450 :   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
    1239             :     Label dividend_not_zero;
    1240         239 :     __ testl(dividend, dividend);
    1241         239 :     __ j(not_zero, &dividend_not_zero, Label::kNear);
    1242         239 :     __ testl(divisor, divisor);
    1243             :     DeoptimizeIf(sign, instr, DeoptimizeReason::kMinusZero);
    1244         239 :     __ bind(&dividend_not_zero);
    1245             :   }
    1246             : 
    1247             :   // Check for (kMinInt / -1).
    1248         450 :   if (hdiv->CheckFlag(HValue::kCanOverflow)) {
    1249             :     Label dividend_not_min_int;
    1250         372 :     __ cmpl(dividend, Immediate(kMinInt));
    1251         372 :     __ j(not_zero, &dividend_not_min_int, Label::kNear);
    1252         372 :     __ cmpl(divisor, Immediate(-1));
    1253             :     DeoptimizeIf(zero, instr, DeoptimizeReason::kOverflow);
    1254         372 :     __ bind(&dividend_not_min_int);
    1255             :   }
    1256             : 
    1257             :   // Sign extend to rdx (= remainder).
    1258         450 :   __ cdq();
    1259         450 :   __ idivl(divisor);
    1260             : 
    1261         450 :   if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
    1262             :     // Deoptimize if remainder is not 0.
    1263         272 :     __ testl(remainder, remainder);
    1264             :     DeoptimizeIf(not_zero, instr, DeoptimizeReason::kLostPrecision);
    1265             :   }
    1266         450 : }
    1267             : 
    1268             : 
    1269        7291 : void LCodeGen::DoMulI(LMulI* instr) {
    1270             :   Register left = ToRegister(instr->left());
    1271             :   LOperand* right = instr->right();
    1272             : 
    1273       14582 :   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
    1274        4812 :     if (instr->hydrogen_value()->representation().IsSmi()) {
    1275       23843 :       __ movp(kScratchRegister, left);
    1276             :     } else {
    1277        3563 :       __ movl(kScratchRegister, left);
    1278             :     }
    1279             :   }
    1280             : 
    1281             :   bool can_overflow =
    1282        7291 :       instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
    1283        7291 :   if (right->IsConstantOperand()) {
    1284             :     int32_t right_value = ToInteger32(LConstantOperand::cast(right));
    1285        6110 :     if (right_value == -1) {
    1286        2846 :       __ negl(left);
    1287        3264 :     } else if (right_value == 0) {
    1288          48 :       __ xorl(left, left);
    1289        3216 :     } else if (right_value == 2) {
    1290         178 :       __ addl(left, left);
    1291        3038 :     } else if (!can_overflow) {
    1292             :       // If the multiplication is known to not overflow, we
    1293             :       // can use operations that don't set the overflow flag
    1294             :       // correctly.
    1295         609 :       switch (right_value) {
    1296             :         case 1:
    1297             :           // Do nothing.
    1298             :           break;
    1299             :         case 3:
    1300          36 :           __ leal(left, Operand(left, left, times_2, 0));
    1301          12 :           break;
    1302             :         case 4:
    1303          36 :           __ shll(left, Immediate(2));
    1304          36 :           break;
    1305             :         case 5:
    1306          45 :           __ leal(left, Operand(left, left, times_4, 0));
    1307          15 :           break;
    1308             :         case 8:
    1309         480 :           __ shll(left, Immediate(3));
    1310         480 :           break;
    1311             :         case 9:
    1312           0 :           __ leal(left, Operand(left, left, times_8, 0));
    1313           0 :           break;
    1314             :         case 16:
    1315           1 :           __ shll(left, Immediate(4));
    1316           1 :           break;
    1317             :         default:
    1318          65 :           __ imull(left, left, Immediate(right_value));
    1319          65 :           break;
    1320             :       }
    1321             :     } else {
    1322        2429 :       __ imull(left, left, Immediate(right_value));
    1323             :     }
    1324        1181 :   } else if (right->IsStackSlot()) {
    1325          93 :     if (instr->hydrogen_value()->representation().IsSmi()) {
    1326           0 :       __ SmiToInteger64(left, left);
    1327           0 :       __ imulp(left, ToOperand(right));
    1328             :     } else {
    1329         186 :       __ imull(left, ToOperand(right));
    1330             :     }
    1331             :   } else {
    1332        1088 :     if (instr->hydrogen_value()->representation().IsSmi()) {
    1333         269 :       __ SmiToInteger64(left, left);
    1334         269 :       __ imulp(left, ToRegister(right));
    1335             :     } else {
    1336         819 :       __ imull(left, ToRegister(right));
    1337             :     }
    1338             :   }
    1339             : 
    1340        7291 :   if (can_overflow) {
    1341             :     DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
    1342             :   }
    1343             : 
    1344       14582 :   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
    1345             :     // Bail out if the result is supposed to be negative zero.
    1346             :     Label done;
    1347        3816 :     if (instr->hydrogen_value()->representation().IsSmi()) {
    1348         253 :       __ testp(left, left);
    1349             :     } else {
    1350        3563 :       __ testl(left, left);
    1351             :     }
    1352        3816 :     __ j(not_zero, &done, Label::kNear);
    1353        3816 :     if (right->IsConstantOperand()) {
    1354             :       // Constant can't be represented as 32-bit Smi due to immediate size
    1355             :       // limit.
    1356             :       DCHECK(SmiValuesAre32Bits()
    1357             :           ? !instr->hydrogen_value()->representation().IsSmi()
    1358             :           : SmiValuesAre31Bits());
    1359        2820 :       if (ToInteger32(LConstantOperand::cast(right)) < 0) {
    1360             :         DeoptimizeIf(no_condition, instr, DeoptimizeReason::kMinusZero);
    1361          23 :       } else if (ToInteger32(LConstantOperand::cast(right)) == 0) {
    1362          23 :         __ cmpl(kScratchRegister, Immediate(0));
    1363             :         DeoptimizeIf(less, instr, DeoptimizeReason::kMinusZero);
    1364             :       }
    1365         996 :     } else if (right->IsStackSlot()) {
    1366          71 :       if (instr->hydrogen_value()->representation().IsSmi()) {
    1367           0 :         __ orp(kScratchRegister, ToOperand(right));
    1368             :       } else {
    1369         142 :         __ orl(kScratchRegister, ToOperand(right));
    1370             :       }
    1371             :       DeoptimizeIf(sign, instr, DeoptimizeReason::kMinusZero);
    1372             :     } else {
    1373             :       // Test the non-zero operand for negative sign.
    1374         925 :       if (instr->hydrogen_value()->representation().IsSmi()) {
    1375         253 :         __ orp(kScratchRegister, ToRegister(right));
    1376             :       } else {
    1377         672 :         __ orl(kScratchRegister, ToRegister(right));
    1378             :       }
    1379             :       DeoptimizeIf(sign, instr, DeoptimizeReason::kMinusZero);
    1380             :     }
    1381        3816 :     __ bind(&done);
    1382             :   }
    1383        7291 : }
    1384             : 
    1385             : 
    1386       89648 : void LCodeGen::DoBitI(LBitI* instr) {
    1387             :   LOperand* left = instr->left();
    1388             :   LOperand* right = instr->right();
    1389             :   DCHECK(left->Equals(instr->result()));
    1390             :   DCHECK(left->IsRegister());
    1391             : 
    1392       89648 :   if (right->IsConstantOperand()) {
    1393             :     int32_t right_operand =
    1394             :         ToRepresentation(LConstantOperand::cast(right),
    1395             :                          instr->hydrogen()->right()->representation());
    1396       56960 :     switch (instr->op()) {
    1397             :       case Token::BIT_AND:
    1398       89648 :         __ andl(ToRegister(left), Immediate(right_operand));
    1399       48168 :         break;
    1400             :       case Token::BIT_OR:
    1401         869 :         __ orl(ToRegister(left), Immediate(right_operand));
    1402         869 :         break;
    1403             :       case Token::BIT_XOR:
    1404        7923 :         if (right_operand == int32_t(~0)) {
    1405        1468 :           __ notl(ToRegister(left));
    1406             :         } else {
    1407        6455 :           __ xorl(ToRegister(left), Immediate(right_operand));
    1408             :         }
    1409             :         break;
    1410             :       default:
    1411           0 :         UNREACHABLE();
    1412             :         break;
    1413             :     }
    1414       32688 :   } else if (right->IsStackSlot()) {
    1415        2065 :     switch (instr->op()) {
    1416             :       case Token::BIT_AND:
    1417        1155 :         if (instr->IsInteger32()) {
    1418        2310 :           __ andl(ToRegister(left), ToOperand(right));
    1419             :         } else {
    1420           0 :           __ andp(ToRegister(left), ToOperand(right));
    1421             :         }
    1422             :         break;
    1423             :       case Token::BIT_OR:
    1424         380 :         if (instr->IsInteger32()) {
    1425         760 :           __ orl(ToRegister(left), ToOperand(right));
    1426             :         } else {
    1427           0 :           __ orp(ToRegister(left), ToOperand(right));
    1428             :         }
    1429             :         break;
    1430             :       case Token::BIT_XOR:
    1431         530 :         if (instr->IsInteger32()) {
    1432        1060 :           __ xorl(ToRegister(left), ToOperand(right));
    1433             :         } else {
    1434           0 :           __ xorp(ToRegister(left), ToOperand(right));
    1435             :         }
    1436             :         break;
    1437             :       default:
    1438           0 :         UNREACHABLE();
    1439             :         break;
    1440             :     }
    1441             :   } else {
    1442             :     DCHECK(right->IsRegister());
    1443       30623 :     switch (instr->op()) {
    1444             :       case Token::BIT_AND:
    1445       10817 :         if (instr->IsInteger32()) {
    1446       10505 :           __ andl(ToRegister(left), ToRegister(right));
    1447             :         } else {
    1448         312 :           __ andp(ToRegister(left), ToRegister(right));
    1449             :         }
    1450             :         break;
    1451             :       case Token::BIT_OR:
    1452        7221 :         if (instr->IsInteger32()) {
    1453        6909 :           __ orl(ToRegister(left), ToRegister(right));
    1454             :         } else {
    1455         312 :           __ orp(ToRegister(left), ToRegister(right));
    1456             :         }
    1457             :         break;
    1458             :       case Token::BIT_XOR:
    1459       12585 :         if (instr->IsInteger32()) {
    1460       12317 :           __ xorl(ToRegister(left), ToRegister(right));
    1461             :         } else {
    1462         268 :           __ xorp(ToRegister(left), ToRegister(right));
    1463             :         }
    1464             :         break;
    1465             :       default:
    1466           0 :         UNREACHABLE();
    1467             :         break;
    1468             :     }
    1469             :   }
    1470       89648 : }
    1471             : 
    1472             : 
    1473       77772 : void LCodeGen::DoShiftI(LShiftI* instr) {
    1474             :   LOperand* left = instr->left();
    1475             :   LOperand* right = instr->right();
    1476             :   DCHECK(left->Equals(instr->result()));
    1477             :   DCHECK(left->IsRegister());
    1478       37072 :   if (right->IsRegister()) {
    1479             :     DCHECK(ToRegister(right).is(rcx));
    1480             : 
    1481        5152 :     switch (instr->op()) {
    1482             :       case Token::ROR:
    1483       36293 :         __ rorl_cl(ToRegister(left));
    1484             :         break;
    1485             :       case Token::SAR:
    1486        1407 :         __ sarl_cl(ToRegister(left));
    1487             :         break;
    1488             :       case Token::SHR:
    1489        1825 :         __ shrl_cl(ToRegister(left));
    1490        1825 :         if (instr->can_deopt()) {
    1491         157 :           __ testl(ToRegister(left), ToRegister(left));
    1492             :           DeoptimizeIf(negative, instr, DeoptimizeReason::kNegativeValue);
    1493             :         }
    1494             :         break;
    1495             :       case Token::SHL:
    1496        1420 :         __ shll_cl(ToRegister(left));
    1497             :         break;
    1498             :       default:
    1499           0 :         UNREACHABLE();
    1500             :         break;
    1501             :     }
    1502             :   } else {
    1503             :     int32_t value = ToInteger32(LConstantOperand::cast(right));
    1504       31920 :     uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
    1505       31920 :     switch (instr->op()) {
    1506             :       case Token::ROR:
    1507          48 :         if (shift_count != 0) {
    1508          96 :           __ rorl(ToRegister(left), Immediate(shift_count));
    1509             :         }
    1510             :         break;
    1511             :       case Token::SAR:
    1512       11957 :         if (shift_count != 0) {
    1513       23706 :           __ sarl(ToRegister(left), Immediate(shift_count));
    1514             :         }
    1515             :         break;
    1516             :       case Token::SHR:
    1517        5826 :         if (shift_count != 0) {
    1518        8046 :           __ shrl(ToRegister(left), Immediate(shift_count));
    1519        1803 :         } else if (instr->can_deopt()) {
    1520        1041 :           __ testl(ToRegister(left), ToRegister(left));
    1521             :           DeoptimizeIf(negative, instr, DeoptimizeReason::kNegativeValue);
    1522             :         }
    1523             :         break;
    1524             :       case Token::SHL:
    1525       14089 :         if (shift_count != 0) {
    1526       14019 :           if (instr->hydrogen_value()->representation().IsSmi()) {
    1527             :             if (SmiValuesAre32Bits()) {
    1528           0 :               __ shlp(ToRegister(left), Immediate(shift_count));
    1529             :             } else {
    1530             :               DCHECK(SmiValuesAre31Bits());
    1531             :               if (instr->can_deopt()) {
    1532             :                 if (shift_count != 1) {
    1533             :                   __ shll(ToRegister(left), Immediate(shift_count - 1));
    1534             :                 }
    1535             :                 __ Integer32ToSmi(ToRegister(left), ToRegister(left));
    1536             :                 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
    1537             :               } else {
    1538             :                 __ shll(ToRegister(left), Immediate(shift_count));
    1539             :               }
    1540             :             }
    1541             :           } else {
    1542       28038 :             __ shll(ToRegister(left), Immediate(shift_count));
    1543             :           }
    1544             :         }
    1545             :         break;
    1546             :       default:
    1547           0 :         UNREACHABLE();
    1548             :         break;
    1549             :     }
    1550             :   }
    1551       37072 : }
    1552             : 
    1553             : 
    1554       13284 : void LCodeGen::DoSubI(LSubI* instr) {
    1555             :   LOperand* left = instr->left();
    1556             :   LOperand* right = instr->right();
    1557             :   DCHECK(left->Equals(instr->result()));
    1558             : 
    1559       13284 :   if (right->IsConstantOperand()) {
    1560             :     int32_t right_operand =
    1561             :         ToRepresentation(LConstantOperand::cast(right),
    1562             :                          instr->hydrogen()->right()->representation());
    1563       13284 :     __ subl(ToRegister(left), Immediate(right_operand));
    1564        1748 :   } else if (right->IsRegister()) {
    1565        1748 :     if (instr->hydrogen_value()->representation().IsSmi()) {
    1566         288 :       __ subp(ToRegister(left), ToRegister(right));
    1567             :     } else {
    1568         874 :       __ subl(ToRegister(left), ToRegister(right));
    1569             :     }
    1570             :   } else {
    1571         586 :     if (instr->hydrogen_value()->representation().IsSmi()) {
    1572           0 :       __ subp(ToRegister(left), ToOperand(right));
    1573             :     } else {
    1574        1172 :       __ subl(ToRegister(left), ToOperand(right));
    1575             :     }
    1576             :   }
    1577             : 
    1578       26568 :   if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
    1579             :     DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
    1580             :   }
    1581       13284 : }
    1582             : 
    1583             : 
    1584      507365 : void LCodeGen::DoConstantI(LConstantI* instr) {
    1585      507365 :   Register dst = ToRegister(instr->result());
    1586      507365 :   if (instr->value() == 0) {
    1587      507365 :     __ xorl(dst, dst);
    1588             :   } else {
    1589      451868 :     __ movl(dst, Immediate(instr->value()));
    1590             :   }
    1591      507365 : }
    1592             : 
    1593             : 
    1594      412497 : void LCodeGen::DoConstantS(LConstantS* instr) {
    1595      824994 :   __ Move(ToRegister(instr->result()), instr->value());
    1596      412497 : }
    1597             : 
    1598             : 
    1599       42968 : void LCodeGen::DoConstantD(LConstantD* instr) {
    1600       85936 :   __ Move(ToDoubleRegister(instr->result()), instr->bits());
    1601       42968 : }
    1602             : 
    1603             : 
    1604        7578 : void LCodeGen::DoConstantE(LConstantE* instr) {
    1605       15156 :   __ LoadAddress(ToRegister(instr->result()), instr->value());
    1606        7578 : }
    1607             : 
    1608             : 
    1609     2595880 : void LCodeGen::DoConstantT(LConstantT* instr) {
    1610     7787642 :   Handle<Object> object = instr->value(isolate());
    1611             :   AllowDeferredHandleDereference smi_check;
    1612     5191762 :   __ Move(ToRegister(instr->result()), object);
    1613     2595881 : }
    1614             : 
    1615             : 
    1616       28544 : Operand LCodeGen::BuildSeqStringOperand(Register string,
    1617             :                                         LOperand* index,
    1618             :                                         String::Encoding encoding) {
    1619       28544 :   if (index->IsConstantOperand()) {
    1620             :     int offset = ToInteger32(LConstantOperand::cast(index));
    1621           0 :     if (encoding == String::TWO_BYTE_ENCODING) {
    1622           0 :       offset *= kUC16Size;
    1623             :     }
    1624             :     STATIC_ASSERT(kCharSize == 1);
    1625             :     return FieldOperand(string, SeqString::kHeaderSize + offset);
    1626             :   }
    1627             :   return FieldOperand(
    1628             :       string, ToRegister(index),
    1629             :       encoding == String::ONE_BYTE_ENCODING ? times_1 : times_2,
    1630       28544 :       SeqString::kHeaderSize);
    1631             : }
    1632             : 
    1633             : 
    1634       14272 : void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) {
    1635       14272 :   String::Encoding encoding = instr->hydrogen()->encoding();
    1636       14272 :   Register result = ToRegister(instr->result());
    1637             :   Register string = ToRegister(instr->string());
    1638             : 
    1639       14272 :   if (FLAG_debug_code) {
    1640       14272 :     __ Push(string);
    1641           0 :     __ movp(string, FieldOperand(string, HeapObject::kMapOffset));
    1642           0 :     __ movzxbp(string, FieldOperand(string, Map::kInstanceTypeOffset));
    1643             : 
    1644           0 :     __ andb(string, Immediate(kStringRepresentationMask | kStringEncodingMask));
    1645             :     static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
    1646             :     static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
    1647             :     __ cmpp(string, Immediate(encoding == String::ONE_BYTE_ENCODING
    1648           0 :                               ? one_byte_seq_type : two_byte_seq_type));
    1649           0 :     __ Check(equal, kUnexpectedStringType);
    1650           0 :     __ Pop(string);
    1651             :   }
    1652             : 
    1653       14272 :   Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
    1654       14272 :   if (encoding == String::ONE_BYTE_ENCODING) {
    1655        7136 :     __ movzxbl(result, operand);
    1656             :   } else {
    1657        7136 :     __ movzxwl(result, operand);
    1658             :   }
    1659       14272 : }
    1660             : 
    1661             : 
    1662       14272 : void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
    1663       14272 :   String::Encoding encoding = instr->hydrogen()->encoding();
    1664       14272 :   Register string = ToRegister(instr->string());
    1665             : 
    1666       14272 :   if (FLAG_debug_code) {
    1667           0 :     Register value = ToRegister(instr->value());
    1668           0 :     Register index = ToRegister(instr->index());
    1669             :     static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
    1670             :     static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
    1671             :     int encoding_mask =
    1672             :         instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING
    1673           0 :         ? one_byte_seq_type : two_byte_seq_type;
    1674       14272 :     __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask);
    1675             :   }
    1676             : 
    1677       14272 :   Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
    1678       14272 :   if (instr->value()->IsConstantOperand()) {
    1679             :     int value = ToInteger32(LConstantOperand::cast(instr->value()));
    1680             :     DCHECK_LE(0, value);
    1681           0 :     if (encoding == String::ONE_BYTE_ENCODING) {
    1682             :       DCHECK_LE(value, String::kMaxOneByteCharCode);
    1683           0 :       __ movb(operand, Immediate(value));
    1684             :     } else {
    1685             :       DCHECK_LE(value, String::kMaxUtf16CodeUnit);
    1686           0 :       __ movw(operand, Immediate(value));
    1687             :     }
    1688             :   } else {
    1689       14272 :     Register value = ToRegister(instr->value());
    1690       14272 :     if (encoding == String::ONE_BYTE_ENCODING) {
    1691        7136 :       __ movb(operand, value);
    1692             :     } else {
    1693        7136 :       __ movw(operand, value);
    1694             :     }
    1695             :   }
    1696       14272 : }
    1697             : 
    1698             : 
    1699      148123 : void LCodeGen::DoAddI(LAddI* instr) {
    1700             :   LOperand* left = instr->left();
    1701             :   LOperand* right = instr->right();
    1702             : 
    1703             :   Representation target_rep = instr->hydrogen()->representation();
    1704      148123 :   bool is_p = target_rep.IsSmi() || target_rep.IsExternal();
    1705             : 
    1706      207263 :   if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) {
    1707       34562 :     if (right->IsConstantOperand()) {
    1708             :       // No support for smi-immediates for 32-bit SMI.
    1709             :       DCHECK(SmiValuesAre32Bits() ? !target_rep.IsSmi() : SmiValuesAre31Bits());
    1710             :       int32_t offset =
    1711             :           ToRepresentation(LConstantOperand::cast(right),
    1712             :                            instr->hydrogen()->right()->representation());
    1713       23770 :       if (is_p) {
    1714      148123 :         __ leap(ToRegister(instr->result()),
    1715           0 :                 MemOperand(ToRegister(left), offset));
    1716             :       } else {
    1717       23770 :         __ leal(ToRegister(instr->result()),
    1718       95080 :                 MemOperand(ToRegister(left), offset));
    1719             :       }
    1720             :     } else {
    1721       10792 :       Operand address(ToRegister(left), ToRegister(right), times_1, 0);
    1722       10792 :       if (is_p) {
    1723          72 :         __ leap(ToRegister(instr->result()), address);
    1724             :       } else {
    1725       21512 :         __ leal(ToRegister(instr->result()), address);
    1726             :       }
    1727             :     }
    1728             :   } else {
    1729      113561 :     if (right->IsConstantOperand()) {
    1730             :       // No support for smi-immediates for 32-bit SMI.
    1731             :       DCHECK(SmiValuesAre32Bits() ? !target_rep.IsSmi() : SmiValuesAre31Bits());
    1732             :       int32_t right_operand =
    1733             :           ToRepresentation(LConstantOperand::cast(right),
    1734             :                            instr->hydrogen()->right()->representation());
    1735       96539 :       if (is_p) {
    1736           0 :         __ addp(ToRegister(left), Immediate(right_operand));
    1737             :       } else {
    1738       96539 :         __ addl(ToRegister(left), Immediate(right_operand));
    1739             :       }
    1740       17022 :     } else if (right->IsRegister()) {
    1741       15412 :       if (is_p) {
    1742        2945 :         __ addp(ToRegister(left), ToRegister(right));
    1743             :       } else {
    1744       12467 :         __ addl(ToRegister(left), ToRegister(right));
    1745             :       }
    1746             :     } else {
    1747        1610 :       if (is_p) {
    1748           0 :         __ addp(ToRegister(left), ToOperand(right));
    1749             :       } else {
    1750        3220 :         __ addl(ToRegister(left), ToOperand(right));
    1751             :       }
    1752             :     }
    1753      227122 :     if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
    1754             :       DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
    1755             :     }
    1756             :   }
    1757      148123 : }
    1758             : 
    1759             : 
    1760        1580 : void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
    1761             :   LOperand* left = instr->left();
    1762             :   LOperand* right = instr->right();
    1763             :   DCHECK(left->Equals(instr->result()));
    1764        1580 :   HMathMinMax::Operation operation = instr->hydrogen()->operation();
    1765        1580 :   if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
    1766             :     Label return_left;
    1767             :     Condition condition = (operation == HMathMinMax::kMathMin)
    1768             :         ? less_equal
    1769         212 :         : greater_equal;
    1770             :     Register left_reg = ToRegister(left);
    1771         212 :     if (right->IsConstantOperand()) {
    1772             :       Immediate right_imm = Immediate(
    1773             :           ToRepresentation(LConstantOperand::cast(right),
    1774             :                            instr->hydrogen()->right()->representation()));
    1775             :       DCHECK(SmiValuesAre32Bits()
    1776             :           ? !instr->hydrogen()->representation().IsSmi()
    1777             :           : SmiValuesAre31Bits());
    1778       23958 :       __ cmpl(left_reg, right_imm);
    1779         146 :       __ j(condition, &return_left, Label::kNear);
    1780         146 :       __ movl(left_reg, right_imm);
    1781          66 :     } else if (right->IsRegister()) {
    1782             :       Register right_reg = ToRegister(right);
    1783          66 :       if (instr->hydrogen_value()->representation().IsSmi()) {
    1784           0 :         __ cmpp(left_reg, right_reg);
    1785             :       } else {
    1786          40 :         __ cmpl(left_reg, right_reg);
    1787             :       }
    1788          40 :       __ j(condition, &return_left, Label::kNear);
    1789          40 :       __ movp(left_reg, right_reg);
    1790             :     } else {
    1791          26 :       Operand right_op = ToOperand(right);
    1792          26 :       if (instr->hydrogen_value()->representation().IsSmi()) {
    1793           0 :         __ cmpp(left_reg, right_op);
    1794             :       } else {
    1795          26 :         __ cmpl(left_reg, right_op);
    1796             :       }
    1797          26 :       __ j(condition, &return_left, Label::kNear);
    1798          26 :       __ movp(left_reg, right_op);
    1799             :     }
    1800         212 :     __ bind(&return_left);
    1801             :   } else {
    1802             :     DCHECK(instr->hydrogen()->representation().IsDouble());
    1803             :     Label not_nan, distinct, return_left, return_right;
    1804        1368 :     Condition condition = (operation == HMathMinMax::kMathMin) ? below : above;
    1805        1368 :     XMMRegister left_reg = ToDoubleRegister(left);
    1806        1368 :     XMMRegister right_reg = ToDoubleRegister(right);
    1807        1368 :     __ Ucomisd(left_reg, right_reg);
    1808        1368 :     __ j(parity_odd, &not_nan, Label::kNear);  // Both are not NaN.
    1809             : 
    1810             :     // One of the numbers is NaN. Find which one and return it.
    1811        1368 :     __ Ucomisd(left_reg, left_reg);
    1812        1368 :     __ j(parity_even, &return_left, Label::kNear);  // left is NaN.
    1813        1368 :     __ jmp(&return_right, Label::kNear);            // right is NaN.
    1814             : 
    1815        1368 :     __ bind(&not_nan);
    1816        1368 :     __ j(not_equal, &distinct, Label::kNear);  // left != right.
    1817             : 
    1818             :     // left == right
    1819        1368 :     XMMRegister xmm_scratch = double_scratch0();
    1820        1368 :     __ Xorpd(xmm_scratch, xmm_scratch);
    1821        1368 :     __ Ucomisd(left_reg, xmm_scratch);
    1822        1368 :     __ j(not_equal, &return_left, Label::kNear);  // left == right != 0.
    1823             : 
    1824             :     // At this point, both left and right are either +0 or -0.
    1825        1368 :     if (operation == HMathMinMax::kMathMin) {
    1826         715 :       __ Orpd(left_reg, right_reg);
    1827             :     } else {
    1828         653 :       __ Andpd(left_reg, right_reg);
    1829             :     }
    1830        1368 :     __ jmp(&return_left, Label::kNear);
    1831             : 
    1832        1368 :     __ bind(&distinct);
    1833        1368 :     __ j(condition, &return_left, Label::kNear);
    1834             : 
    1835        1368 :     __ bind(&return_right);
    1836        1368 :     __ Movapd(left_reg, right_reg);
    1837             : 
    1838        1368 :     __ bind(&return_left);
    1839             :   }
    1840        1580 : }
    1841             : 
    1842             : 
    1843      166006 : void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
    1844       83003 :   XMMRegister left = ToDoubleRegister(instr->left());
    1845       83003 :   XMMRegister right = ToDoubleRegister(instr->right());
    1846      166006 :   XMMRegister result = ToDoubleRegister(instr->result());
    1847       83003 :   switch (instr->op()) {
    1848             :     case Token::ADD:
    1849       45970 :       if (CpuFeatures::IsSupported(AVX)) {
    1850      104138 :         CpuFeatureScope scope(masm(), AVX);
    1851       45963 :         __ vaddsd(result, left, right);
    1852             :       } else {
    1853             :         DCHECK(result.is(left));
    1854           7 :         __ addsd(left, right);
    1855             :       }
    1856             :       break;
    1857             :     case Token::SUB:
    1858        3089 :       if (CpuFeatures::IsSupported(AVX)) {
    1859             :         CpuFeatureScope scope(masm(), AVX);
    1860        3084 :         __ vsubsd(result, left, right);
    1861             :       } else {
    1862             :         DCHECK(result.is(left));
    1863           5 :         __ subsd(left, right);
    1864             :       }
    1865             :        break;
    1866             :     case Token::MUL:
    1867       12809 :       if (CpuFeatures::IsSupported(AVX)) {
    1868             :         CpuFeatureScope scope(masm(), AVX);
    1869       12800 :         __ vmulsd(result, left, right);
    1870             :       } else {
    1871             :         DCHECK(result.is(left));
    1872           9 :         __ mulsd(left, right);
    1873             :       }
    1874             :       break;
    1875             :     case Token::DIV:
    1876       18911 :       if (CpuFeatures::IsSupported(AVX)) {
    1877             :         CpuFeatureScope scope(masm(), AVX);
    1878       18902 :         __ vdivsd(result, left, right);
    1879             :       } else {
    1880             :         DCHECK(result.is(left));
    1881           9 :         __ divsd(left, right);
    1882             :       }
    1883             :       // Don't delete this mov. It may improve performance on some CPUs,
    1884             :       // when there is a (v)mulsd depending on the result
    1885       18911 :       __ Movapd(result, result);
    1886       18911 :       break;
    1887             :     case Token::MOD: {
    1888             :       DCHECK(left.is(xmm0));
    1889             :       DCHECK(right.is(xmm1));
    1890             :       DCHECK(result.is(xmm0));
    1891        2224 :       __ PrepareCallCFunction(2);
    1892             :       __ CallCFunction(
    1893        4448 :           ExternalReference::mod_two_doubles_operation(isolate()), 2);
    1894        2224 :       break;
    1895             :     }
    1896             :     default:
    1897           0 :       UNREACHABLE();
    1898             :       break;
    1899             :   }
    1900       83003 : }
    1901             : 
    1902             : 
    1903       47387 : void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
    1904             :   DCHECK(ToRegister(instr->context()).is(rsi));
    1905             :   DCHECK(ToRegister(instr->left()).is(rdx));
    1906             :   DCHECK(ToRegister(instr->right()).is(rax));
    1907             :   DCHECK(ToRegister(instr->result()).is(rax));
    1908             : 
    1909       94774 :   Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), instr->op()).code();
    1910             :   CallCode(code, RelocInfo::CODE_TARGET, instr);
    1911       47387 : }
    1912             : 
    1913             : 
    1914             : template<class InstrType>
    1915      489131 : void LCodeGen::EmitBranch(InstrType instr, Condition cc) {
    1916      489131 :   int left_block = instr->TrueDestination(chunk_);
    1917      489131 :   int right_block = instr->FalseDestination(chunk_);
    1918             : 
    1919      983707 :   int next_block = GetNextEmittedBlock();
    1920             : 
    1921      489131 :   if (right_block == left_block || cc == no_condition) {
    1922         599 :     EmitGoto(left_block);
    1923      488532 :   } else if (left_block == next_block) {
    1924      312788 :     __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block));
    1925      332138 :   } else if (right_block == next_block) {
    1926      652188 :     __ j(cc, chunk_->GetAssemblyLabel(left_block));
    1927             :   } else {
    1928       12088 :     __ j(cc, chunk_->GetAssemblyLabel(left_block));
    1929        6044 :     if (cc != always) {
    1930       12088 :       __ jmp(chunk_->GetAssemblyLabel(right_block));
    1931             :     }
    1932             :   }
    1933      489131 : }
    1934             : 
    1935             : 
    1936             : template <class InstrType>
    1937         319 : void LCodeGen::EmitTrueBranch(InstrType instr, Condition cc) {
    1938         319 :   int true_block = instr->TrueDestination(chunk_);
    1939         319 :   __ j(cc, chunk_->GetAssemblyLabel(true_block));
    1940         319 : }
    1941             : 
    1942             : 
    1943             : template <class InstrType>
    1944         622 : void LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) {
    1945         622 :   int false_block = instr->FalseDestination(chunk_);
    1946         622 :   __ j(cc, chunk_->GetAssemblyLabel(false_block));
    1947         622 : }
    1948             : 
    1949             : 
    1950           0 : void LCodeGen::DoDebugBreak(LDebugBreak* instr) {
    1951           0 :   __ int3();
    1952           0 : }
    1953             : 
    1954             : 
    1955      325227 : void LCodeGen::DoBranch(LBranch* instr) {
    1956             :   Representation r = instr->hydrogen()->value()->representation();
    1957      325227 :   if (r.IsInteger32()) {
    1958             :     DCHECK(!info()->IsStub());
    1959             :     Register reg = ToRegister(instr->value());
    1960     2592045 :     __ testl(reg, reg);
    1961         570 :     EmitBranch(instr, not_zero);
    1962      324657 :   } else if (r.IsSmi()) {
    1963             :     DCHECK(!info()->IsStub());
    1964             :     Register reg = ToRegister(instr->value());
    1965           0 :     __ testp(reg, reg);
    1966           0 :     EmitBranch(instr, not_zero);
    1967      324657 :   } else if (r.IsDouble()) {
    1968             :     DCHECK(!info()->IsStub());
    1969          21 :     XMMRegister reg = ToDoubleRegister(instr->value());
    1970          21 :     XMMRegister xmm_scratch = double_scratch0();
    1971          21 :     __ Xorpd(xmm_scratch, xmm_scratch);
    1972          21 :     __ Ucomisd(reg, xmm_scratch);
    1973          21 :     EmitBranch(instr, not_equal);
    1974             :   } else {
    1975             :     DCHECK(r.IsTagged());
    1976             :     Register reg = ToRegister(instr->value());
    1977             :     HType type = instr->hydrogen()->value()->type();
    1978      324636 :     if (type.IsBoolean()) {
    1979             :       DCHECK(!info()->IsStub());
    1980      204280 :       __ CompareRoot(reg, Heap::kTrueValueRootIndex);
    1981      204280 :       EmitBranch(instr, equal);
    1982      120356 :     } else if (type.IsSmi()) {
    1983             :       DCHECK(!info()->IsStub());
    1984           0 :       __ SmiCompare(reg, Smi::kZero);
    1985           0 :       EmitBranch(instr, not_equal);
    1986      120356 :     } else if (type.IsJSArray()) {
    1987             :       DCHECK(!info()->IsStub());
    1988           0 :       EmitBranch(instr, no_condition);
    1989      120356 :     } else if (type.IsHeapNumber()) {
    1990             :       DCHECK(!info()->IsStub());
    1991           0 :       XMMRegister xmm_scratch = double_scratch0();
    1992           0 :       __ Xorpd(xmm_scratch, xmm_scratch);
    1993           0 :       __ Ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset));
    1994           0 :       EmitBranch(instr, not_equal);
    1995      120356 :     } else if (type.IsString()) {
    1996             :       DCHECK(!info()->IsStub());
    1997          81 :       __ cmpp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
    1998          81 :       EmitBranch(instr, not_equal);
    1999             :     } else {
    2000             :       ToBooleanHints expected = instr->hydrogen()->expected_input_types();
    2001             :       // Avoid deopts in the case where we've never executed this path before.
    2002      120275 :       if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny;
    2003             : 
    2004      120275 :       if (expected & ToBooleanHint::kUndefined) {
    2005             :         // undefined -> false.
    2006       75465 :         __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
    2007      150930 :         __ j(equal, instr->FalseLabel(chunk_));
    2008             :       }
    2009      120275 :       if (expected & ToBooleanHint::kBoolean) {
    2010             :         // true -> true.
    2011      107301 :         __ CompareRoot(reg, Heap::kTrueValueRootIndex);
    2012      214602 :         __ j(equal, instr->TrueLabel(chunk_));
    2013             :         // false -> false.
    2014      107301 :         __ CompareRoot(reg, Heap::kFalseValueRootIndex);
    2015      214602 :         __ j(equal, instr->FalseLabel(chunk_));
    2016             :       }
    2017      120275 :       if (expected & ToBooleanHint::kNull) {
    2018             :         // 'null' -> false.
    2019       71577 :         __ CompareRoot(reg, Heap::kNullValueRootIndex);
    2020      143154 :         __ j(equal, instr->FalseLabel(chunk_));
    2021             :       }
    2022             : 
    2023      120275 :       if (expected & ToBooleanHint::kSmallInteger) {
    2024             :         // Smis: 0 -> false, all other -> true.
    2025       71325 :         __ Cmp(reg, Smi::kZero);
    2026      142650 :         __ j(equal, instr->FalseLabel(chunk_));
    2027      142650 :         __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
    2028       48950 :       } else if (expected & ToBooleanHint::kNeedsMap) {
    2029             :         // If we need a map later and have a Smi -> deopt.
    2030        8436 :         __ testb(reg, Immediate(kSmiTagMask));
    2031             :         DeoptimizeIf(zero, instr, DeoptimizeReason::kSmi);
    2032             :       }
    2033             : 
    2034             :       const Register map = kScratchRegister;
    2035      120275 :       if (expected & ToBooleanHint::kNeedsMap) {
    2036       78209 :         __ movp(map, FieldOperand(reg, HeapObject::kMapOffset));
    2037             : 
    2038       78209 :         if (expected & ToBooleanHint::kCanBeUndetectable) {
    2039             :           // Undetectable -> false.
    2040             :           __ testb(FieldOperand(map, Map::kBitFieldOffset),
    2041      151010 :                    Immediate(1 << Map::kIsUndetectable));
    2042      151010 :           __ j(not_zero, instr->FalseLabel(chunk_));
    2043             :         }
    2044             :       }
    2045             : 
    2046      120275 :       if (expected & ToBooleanHint::kReceiver) {
    2047             :         // spec object -> true.
    2048       75505 :         __ CmpInstanceType(map, FIRST_JS_RECEIVER_TYPE);
    2049      151010 :         __ j(above_equal, instr->TrueLabel(chunk_));
    2050             :       }
    2051             : 
    2052      120275 :       if (expected & ToBooleanHint::kString) {
    2053             :         // String value -> false iff empty.
    2054             :         Label not_string;
    2055       72289 :         __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
    2056       72289 :         __ j(above_equal, &not_string, Label::kNear);
    2057       72289 :         __ cmpp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
    2058      144578 :         __ j(not_zero, instr->TrueLabel(chunk_));
    2059      144578 :         __ jmp(instr->FalseLabel(chunk_));
    2060       72289 :         __ bind(&not_string);
    2061             :       }
    2062             : 
    2063      120275 :       if (expected & ToBooleanHint::kSymbol) {
    2064             :         // Symbol value -> true.
    2065       69685 :         __ CmpInstanceType(map, SYMBOL_TYPE);
    2066      139370 :         __ j(equal, instr->TrueLabel(chunk_));
    2067             :       }
    2068             : 
    2069      120275 :       if (expected & ToBooleanHint::kHeapNumber) {
    2070             :         // heap number -> false iff +0, -0, or NaN.
    2071             :         Label not_heap_number;
    2072       69720 :         __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
    2073       69720 :         __ j(not_equal, &not_heap_number, Label::kNear);
    2074       69720 :         XMMRegister xmm_scratch = double_scratch0();
    2075       69720 :         __ Xorpd(xmm_scratch, xmm_scratch);
    2076      139440 :         __ Ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset));
    2077      139440 :         __ j(zero, instr->FalseLabel(chunk_));
    2078      139440 :         __ jmp(instr->TrueLabel(chunk_));
    2079       69720 :         __ bind(&not_heap_number);
    2080             :       }
    2081             : 
    2082      120275 :       if (expected != ToBooleanHint::kAny) {
    2083             :         // We've seen something for the first time -> deopt.
    2084             :         // This can only happen if we are not generic already.
    2085             :         DeoptimizeIf(no_condition, instr, DeoptimizeReason::kUnexpectedObject);
    2086             :       }
    2087             :     }
    2088             :   }
    2089      325227 : }
    2090             : 
    2091             : 
    2092     1014038 : void LCodeGen::EmitGoto(int block) {
    2093     1014038 :   if (!IsNextEmittedBlock(block)) {
    2094      220588 :     __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block)));
    2095             :   }
    2096     1014039 : }
    2097             : 
    2098             : 
    2099     1004320 : void LCodeGen::DoGoto(LGoto* instr) {
    2100     1004320 :   EmitGoto(instr->block_id());
    2101     1004321 : }
    2102             : 
    2103             : 
    2104      360093 : inline Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
    2105             :   Condition cond = no_condition;
    2106      360093 :   switch (op) {
    2107             :     case Token::EQ:
    2108             :     case Token::EQ_STRICT:
    2109             :       cond = equal;
    2110             :       break;
    2111             :     case Token::NE:
    2112             :     case Token::NE_STRICT:
    2113             :       cond = not_equal;
    2114       13056 :       break;
    2115             :     case Token::LT:
    2116       52181 :       cond = is_unsigned ? below : less;
    2117       52181 :       break;
    2118             :     case Token::GT:
    2119       34880 :       cond = is_unsigned ? above : greater;
    2120       34880 :       break;
    2121             :     case Token::LTE:
    2122        5698 :       cond = is_unsigned ? below_equal : less_equal;
    2123        5698 :       break;
    2124             :     case Token::GTE:
    2125        7778 :       cond = is_unsigned ? above_equal : greater_equal;
    2126        7778 :       break;
    2127             :     case Token::IN:
    2128             :     case Token::INSTANCEOF:
    2129             :     default:
    2130           0 :       UNREACHABLE();
    2131             :   }
    2132      360093 :   return cond;
    2133             : }
    2134             : 
    2135             : 
    2136      160446 : void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
    2137             :   LOperand* left = instr->left();
    2138             :   LOperand* right = instr->right();
    2139             :   bool is_unsigned =
    2140      143837 :       instr->is_double() ||
    2141      448087 :       instr->hydrogen()->left()->CheckFlag(HInstruction::kUint32) ||
    2142      143804 :       instr->hydrogen()->right()->CheckFlag(HInstruction::kUint32);
    2143      320892 :   Condition cc = TokenToCondition(instr->op(), is_unsigned);
    2144             : 
    2145      169958 :   if (left->IsConstantOperand() && right->IsConstantOperand()) {
    2146             :     // We can statically evaluate the comparison.
    2147             :     double left_val = ToDouble(LConstantOperand::cast(left));
    2148             :     double right_val = ToDouble(LConstantOperand::cast(right));
    2149        9119 :     int next_block = Token::EvalComparison(instr->op(), left_val, right_val)
    2150         893 :                          ? instr->TrueDestination(chunk_)
    2151       10012 :                          : instr->FalseDestination(chunk_);
    2152        9119 :     EmitGoto(next_block);
    2153             :   } else {
    2154      151327 :     if (instr->is_double()) {
    2155             :       // Don't base result on EFLAGS when a NaN is involved. Instead
    2156             :       // jump to the false block.
    2157      166205 :       __ Ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
    2158       29756 :       __ j(parity_even, instr->FalseLabel(chunk_));
    2159             :     } else {
    2160             :       int32_t value;
    2161      136449 :       if (right->IsConstantOperand()) {
    2162             :         value = ToInteger32(LConstantOperand::cast(right));
    2163       82132 :         if (instr->hydrogen_value()->representation().IsSmi()) {
    2164           0 :           __ Cmp(ToRegister(left), Smi::FromInt(value));
    2165             :         } else {
    2166       81739 :           __ cmpl(ToRegister(left), Immediate(value));
    2167             :         }
    2168       54710 :       } else if (left->IsConstantOperand()) {
    2169             :         value = ToInteger32(LConstantOperand::cast(left));
    2170         393 :         if (instr->hydrogen_value()->representation().IsSmi()) {
    2171           0 :           if (right->IsRegister()) {
    2172           0 :             __ Cmp(ToRegister(right), Smi::FromInt(value));
    2173             :           } else {
    2174           0 :             __ Cmp(ToOperand(right), Smi::FromInt(value));
    2175             :           }
    2176         393 :         } else if (right->IsRegister()) {
    2177         361 :           __ cmpl(ToRegister(right), Immediate(value));
    2178             :         } else {
    2179          64 :           __ cmpl(ToOperand(right), Immediate(value));
    2180             :         }
    2181             :         // We commuted the operands, so commute the condition.
    2182         393 :         cc = CommuteCondition(cc);
    2183       54317 :       } else if (instr->hydrogen_value()->representation().IsSmi()) {
    2184        3746 :         if (right->IsRegister()) {
    2185        3663 :           __ cmpp(ToRegister(left), ToRegister(right));
    2186             :         } else {
    2187         166 :           __ cmpp(ToRegister(left), ToOperand(right));
    2188             :         }
    2189             :       } else {
    2190       50571 :         if (right->IsRegister()) {
    2191       38770 :           __ cmpl(ToRegister(left), ToRegister(right));
    2192             :         } else {
    2193       23602 :           __ cmpl(ToRegister(left), ToOperand(right));
    2194             :         }
    2195             :       }
    2196             :     }
    2197      151327 :     EmitBranch(instr, cc);
    2198             :   }
    2199      160446 : }
    2200             : 
    2201             : 
    2202       41421 : void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
    2203       41421 :   Register left = ToRegister(instr->left());
    2204             : 
    2205       41421 :   if (instr->right()->IsConstantOperand()) {
    2206       30577 :     Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right()));
    2207       41421 :     __ Cmp(left, right);
    2208             :   } else {
    2209       10844 :     Register right = ToRegister(instr->right());
    2210       10844 :     __ cmpp(left, right);
    2211             :   }
    2212       41421 :   EmitBranch(instr, equal);
    2213       41421 : }
    2214             : 
    2215             : 
    2216          33 : void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
    2217          33 :   if (instr->hydrogen()->representation().IsTagged()) {
    2218          24 :     Register input_reg = ToRegister(instr->object());
    2219          93 :     __ Cmp(input_reg, factory()->the_hole_value());
    2220          24 :     EmitBranch(instr, equal);
    2221          33 :     return;
    2222             :   }
    2223             : 
    2224           9 :   XMMRegister input_reg = ToDoubleRegister(instr->object());
    2225           9 :   __ Ucomisd(input_reg, input_reg);
    2226           9 :   EmitFalseBranch(instr, parity_odd);
    2227             : 
    2228           9 :   __ subp(rsp, Immediate(kDoubleSize));
    2229          18 :   __ Movsd(MemOperand(rsp, 0), input_reg);
    2230           9 :   __ addp(rsp, Immediate(kDoubleSize));
    2231             : 
    2232             :   int offset = sizeof(kHoleNanUpper32);
    2233          27 :   __ cmpl(MemOperand(rsp, -offset), Immediate(kHoleNanUpper32));
    2234           9 :   EmitBranch(instr, equal);
    2235             : }
    2236             : 
    2237             : 
    2238         426 : Condition LCodeGen::EmitIsString(Register input,
    2239             :                                  Register temp1,
    2240             :                                  Label* is_not_string,
    2241             :                                  SmiCheck check_needed = INLINE_SMI_CHECK) {
    2242         426 :   if (check_needed == INLINE_SMI_CHECK) {
    2243         425 :     __ JumpIfSmi(input, is_not_string);
    2244             :   }
    2245             : 
    2246         426 :   Condition cond =  masm_->IsObjectStringType(input, temp1, temp1);
    2247             : 
    2248         426 :   return cond;
    2249             : }
    2250             : 
    2251             : 
    2252         426 : void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
    2253         426 :   Register reg = ToRegister(instr->value());
    2254         426 :   Register temp = ToRegister(instr->temp());
    2255             : 
    2256             :   SmiCheck check_needed =
    2257             :       instr->hydrogen()->value()->type().IsHeapObject()
    2258         426 :           ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
    2259             : 
    2260             :   Condition true_cond = EmitIsString(
    2261         426 :       reg, temp, instr->FalseLabel(chunk_), check_needed);
    2262             : 
    2263         426 :   EmitBranch(instr, true_cond);
    2264         426 : }
    2265             : 
    2266             : 
    2267        8819 : void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
    2268             :   Condition is_smi;
    2269        8819 :   if (instr->value()->IsRegister()) {
    2270        6860 :     Register input = ToRegister(instr->value());
    2271        8819 :     is_smi = masm()->CheckSmi(input);
    2272             :   } else {
    2273        1959 :     Operand input = ToOperand(instr->value());
    2274        1959 :     is_smi = masm()->CheckSmi(input);
    2275             :   }
    2276        8819 :   EmitBranch(instr, is_smi);
    2277        8819 : }
    2278             : 
    2279             : 
    2280        1176 : void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
    2281             :   Register input = ToRegister(instr->value());
    2282             :   Register temp = ToRegister(instr->temp());
    2283             : 
    2284        1176 :   if (!instr->hydrogen()->value()->type().IsHeapObject()) {
    2285        3461 :     __ JumpIfSmi(input, instr->FalseLabel(chunk_));
    2286             :   }
    2287        1176 :   __ movp(temp, FieldOperand(input, HeapObject::kMapOffset));
    2288             :   __ testb(FieldOperand(temp, Map::kBitFieldOffset),
    2289        2352 :            Immediate(1 << Map::kIsUndetectable));
    2290        1176 :   EmitBranch(instr, not_zero);
    2291        1176 : }
    2292             : 
    2293             : 
    2294       13270 : void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
    2295             :   DCHECK(ToRegister(instr->context()).is(rsi));
    2296             :   DCHECK(ToRegister(instr->left()).is(rdx));
    2297             :   DCHECK(ToRegister(instr->right()).is(rax));
    2298             : 
    2299       39810 :   Handle<Code> code = CodeFactory::StringCompare(isolate(), instr->op()).code();
    2300             :   CallCode(code, RelocInfo::CODE_TARGET, instr);
    2301       13270 :   __ CompareRoot(rax, Heap::kTrueValueRootIndex);
    2302       13270 :   EmitBranch(instr, equal);
    2303       13270 : }
    2304             : 
    2305             : 
    2306        1889 : static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
    2307             :   InstanceType from = instr->from();
    2308             :   InstanceType to = instr->to();
    2309        1889 :   if (from == FIRST_TYPE) return to;
    2310             :   DCHECK(from == to || to == LAST_TYPE);
    2311             :   return from;
    2312             : }
    2313             : 
    2314             : 
    2315        1889 : static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
    2316             :   InstanceType from = instr->from();
    2317             :   InstanceType to = instr->to();
    2318        1889 :   if (from == to) return equal;
    2319        1031 :   if (to == LAST_TYPE) return above_equal;
    2320           0 :   if (from == FIRST_TYPE) return below_equal;
    2321           0 :   UNREACHABLE();
    2322             :   return equal;
    2323             : }
    2324             : 
    2325             : 
    2326        1889 : void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
    2327        1889 :   Register input = ToRegister(instr->value());
    2328             : 
    2329        1889 :   if (!instr->hydrogen()->value()->type().IsHeapObject()) {
    2330        3548 :     __ JumpIfSmi(input, instr->FalseLabel(chunk_));
    2331             :   }
    2332             : 
    2333        1889 :   __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister);
    2334        1889 :   EmitBranch(instr, BranchCondition(instr->hydrogen()));
    2335        1889 : }
    2336             : 
    2337             : // Branches to a label or falls through with the answer in the z flag.
    2338             : // Trashes the temp register.
    2339        7314 : void LCodeGen::EmitClassOfTest(Label* is_true, Label* is_false,
    2340             :                                Handle<String> class_name, Register input,
    2341             :                                Register temp, Register temp2) {
    2342             :   DCHECK(!input.is(temp));
    2343             :   DCHECK(!input.is(temp2));
    2344             :   DCHECK(!temp.is(temp2));
    2345             : 
    2346       58512 :   __ JumpIfSmi(input, is_false);
    2347             : 
    2348        7314 :   __ CmpObjectType(input, FIRST_FUNCTION_TYPE, temp);
    2349             :   STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
    2350       14628 :   if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
    2351           6 :     __ j(above_equal, is_true);
    2352             :   } else {
    2353        7308 :     __ j(above_equal, is_false);
    2354             :   }
    2355             : 
    2356             :   // Check if the constructor in the map is a function.
    2357        7314 :   __ GetMapConstructor(temp, temp, kScratchRegister);
    2358             : 
    2359             :   // Objects with a non-function constructor have class 'Object'.
    2360        7314 :   __ CmpInstanceType(kScratchRegister, JS_FUNCTION_TYPE);
    2361       14628 :   if (String::Equals(class_name, isolate()->factory()->Object_string())) {
    2362           0 :     __ j(not_equal, is_true);
    2363             :   } else {
    2364        7314 :     __ j(not_equal, is_false);
    2365             :   }
    2366             : 
    2367             :   // temp now contains the constructor function. Grab the
    2368             :   // instance class name from there.
    2369        7314 :   __ movp(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset));
    2370             :   __ movp(temp,
    2371        7314 :           FieldOperand(temp, SharedFunctionInfo::kInstanceClassNameOffset));
    2372             :   // The class name we are testing against is internalized since it's a literal.
    2373             :   // The name in the constructor is internalized because of the way the context
    2374             :   // is booted.  This routine isn't expected to work for random API-created
    2375             :   // classes and it doesn't have to because you can't access it with natives
    2376             :   // syntax.  Since both sides are internalized it is sufficient to use an
    2377             :   // identity comparison.
    2378             :   DCHECK(class_name->IsInternalizedString());
    2379        7314 :   __ Cmp(temp, class_name);
    2380             :   // End with the answer in the z flag.
    2381        7314 : }
    2382             : 
    2383        7314 : void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
    2384        7314 :   Register input = ToRegister(instr->value());
    2385        7314 :   Register temp = ToRegister(instr->temp());
    2386        7314 :   Register temp2 = ToRegister(instr->temp2());
    2387        7314 :   Handle<String> class_name = instr->hydrogen()->class_name();
    2388             : 
    2389             :   EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
    2390        7314 :                   class_name, input, temp, temp2);
    2391             : 
    2392        7314 :   EmitBranch(instr, equal);
    2393        7314 : }
    2394             : 
    2395       16351 : void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
    2396             :   Register reg = ToRegister(instr->value());
    2397             : 
    2398       16351 :   __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map());
    2399       16351 :   EmitBranch(instr, equal);
    2400       16351 : }
    2401             : 
    2402             : 
    2403         319 : void LCodeGen::DoHasInPrototypeChainAndBranch(
    2404             :     LHasInPrototypeChainAndBranch* instr) {
    2405             :   Register const object = ToRegister(instr->object());
    2406             :   Register const object_map = kScratchRegister;
    2407             :   Register const object_prototype = object_map;
    2408         319 :   Register const prototype = ToRegister(instr->prototype());
    2409             : 
    2410             :   // The {object} must be a spec object.  It's sufficient to know that {object}
    2411             :   // is not a smi, since all other non-spec objects have {null} prototypes and
    2412             :   // will be ruled out below.
    2413         319 :   if (instr->hydrogen()->ObjectNeedsSmiCheck()) {
    2414        3165 :     Condition is_smi = __ CheckSmi(object);
    2415         294 :     EmitFalseBranch(instr, is_smi);
    2416             :   }
    2417             : 
    2418             :   // Loop through the {object}s prototype chain looking for the {prototype}.
    2419         319 :   __ movp(object_map, FieldOperand(object, HeapObject::kMapOffset));
    2420             :   Label loop;
    2421         319 :   __ bind(&loop);
    2422             : 
    2423             :   // Deoptimize if the object needs to be access checked.
    2424             :   __ testb(FieldOperand(object_map, Map::kBitFieldOffset),
    2425         638 :            Immediate(1 << Map::kIsAccessCheckNeeded));
    2426             :   DeoptimizeIf(not_zero, instr, DeoptimizeReason::kAccessCheck);
    2427             :   // Deoptimize for proxies.
    2428         319 :   __ CmpInstanceType(object_map, JS_PROXY_TYPE);
    2429             :   DeoptimizeIf(equal, instr, DeoptimizeReason::kProxy);
    2430             : 
    2431         319 :   __ movp(object_prototype, FieldOperand(object_map, Map::kPrototypeOffset));
    2432         319 :   __ CompareRoot(object_prototype, Heap::kNullValueRootIndex);
    2433         319 :   EmitFalseBranch(instr, equal);
    2434         319 :   __ cmpp(object_prototype, prototype);
    2435         319 :   EmitTrueBranch(instr, equal);
    2436         319 :   __ movp(object_map, FieldOperand(object_prototype, HeapObject::kMapOffset));
    2437         319 :   __ jmp(&loop);
    2438         319 : }
    2439             : 
    2440             : 
    2441      199647 : void LCodeGen::DoCmpT(LCmpT* instr) {
    2442             :   DCHECK(ToRegister(instr->context()).is(rsi));
    2443             :   Token::Value op = instr->op();
    2444             : 
    2445     1796823 :   Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
    2446             :   CallCode(ic, RelocInfo::CODE_TARGET, instr);
    2447             : 
    2448      199647 :   Condition condition = TokenToCondition(op, false);
    2449             :   Label true_value, done;
    2450      199647 :   __ testp(rax, rax);
    2451      199647 :   __ j(condition, &true_value, Label::kNear);
    2452      399294 :   __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
    2453      199647 :   __ jmp(&done, Label::kNear);
    2454      199647 :   __ bind(&true_value);
    2455      399294 :   __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
    2456      199647 :   __ bind(&done);
    2457      199647 : }
    2458             : 
    2459             : 
    2460      353362 : void LCodeGen::DoReturn(LReturn* instr) {
    2461     1702240 :   if (FLAG_trace && info()->IsOptimizing()) {
    2462             :     // Preserve the return value on the stack and rely on the runtime call
    2463             :     // to return the value in the same register.  We're leaving the code
    2464             :     // managed by the register allocator and tearing down the frame, it's
    2465             :     // safe to write to the context register.
    2466           0 :     __ Push(rax);
    2467           0 :     __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
    2468           0 :     __ CallRuntime(Runtime::kTraceExit);
    2469             :   }
    2470      353363 :   if (info()->saves_caller_doubles()) {
    2471          55 :     RestoreCallerDoubles();
    2472             :   }
    2473      353363 :   if (NeedsEagerFrame()) {
    2474      321076 :     __ movp(rsp, rbp);
    2475      321076 :     __ popq(rbp);
    2476             :   }
    2477      353362 :   if (instr->has_constant_parameter_count()) {
    2478      353363 :     __ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize,
    2479      706726 :            rcx);
    2480             :   } else {
    2481             :     DCHECK(info()->IsStub());  // Functions would need to drop one more value.
    2482             :     Register reg = ToRegister(instr->parameter_count());
    2483             :     // The argument count parameter is a smi
    2484           0 :     __ SmiToInteger32(reg, reg);
    2485           0 :     Register return_addr_reg = reg.is(rcx) ? rbx : rcx;
    2486             :     __ PopReturnAddressTo(return_addr_reg);
    2487           0 :     __ shlp(reg, Immediate(kPointerSizeLog2));
    2488           0 :     __ addp(rsp, reg);
    2489           0 :     __ jmp(return_addr_reg);
    2490             :   }
    2491      353363 : }
    2492             : 
    2493             : 
    2494      298906 : void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
    2495      298906 :   Register context = ToRegister(instr->context());
    2496      298906 :   Register result = ToRegister(instr->result());
    2497      311634 :   __ movp(result, ContextOperand(context, instr->slot_index()));
    2498      298906 :   if (instr->hydrogen()->RequiresHoleCheck()) {
    2499       12728 :     __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
    2500       12728 :     if (instr->hydrogen()->DeoptimizesOnHole()) {
    2501             :       DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
    2502             :     } else {
    2503             :       Label is_not_hole;
    2504           0 :       __ j(not_equal, &is_not_hole, Label::kNear);
    2505           0 :       __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
    2506           0 :       __ bind(&is_not_hole);
    2507             :     }
    2508             :   }
    2509      298906 : }
    2510             : 
    2511             : 
    2512       69884 : void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
    2513             :   Register context = ToRegister(instr->context());
    2514             :   Register value = ToRegister(instr->value());
    2515             : 
    2516       69884 :   Operand target = ContextOperand(context, instr->slot_index());
    2517             : 
    2518             :   Label skip_assignment;
    2519       69884 :   if (instr->hydrogen()->RequiresHoleCheck()) {
    2520      178733 :     __ CompareRoot(target, Heap::kTheHoleValueRootIndex);
    2521         612 :     if (instr->hydrogen()->DeoptimizesOnHole()) {
    2522             :       DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
    2523             :     } else {
    2524           0 :       __ j(not_equal, &skip_assignment);
    2525             :     }
    2526             :   }
    2527       69884 :   __ movp(target, value);
    2528             : 
    2529       69884 :   if (instr->hydrogen()->NeedsWriteBarrier()) {
    2530             :     SmiCheck check_needed =
    2531             :       instr->hydrogen()->value()->type().IsHeapObject()
    2532       38353 :           ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
    2533             :     int offset = Context::SlotOffset(instr->slot_index());
    2534             :     Register scratch = ToRegister(instr->temp());
    2535             :     __ RecordWriteContextSlot(context,
    2536             :                               offset,
    2537             :                               value,
    2538             :                               scratch,
    2539             :                               kSaveFPRegs,
    2540             :                               EMIT_REMEMBERED_SET,
    2541             :                               check_needed);
    2542             :   }
    2543             : 
    2544       69884 :   __ bind(&skip_assignment);
    2545       69884 : }
    2546             : 
    2547             : 
    2548      239435 : void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
    2549             :   HObjectAccess access = instr->hydrogen()->access();
    2550             :   int offset = access.offset();
    2551             : 
    2552      239435 :   if (access.IsExternalMemory()) {
    2553           0 :     Register result = ToRegister(instr->result());
    2554           0 :     if (instr->object()->IsConstantOperand()) {
    2555             :       DCHECK(result.is(rax));
    2556      242057 :       __ load_rax(ToExternalReference(LConstantOperand::cast(instr->object())));
    2557             :     } else {
    2558           0 :       Register object = ToRegister(instr->object());
    2559           0 :       __ Load(result, MemOperand(object, offset), access.representation());
    2560             :     }
    2561             :     return;
    2562             :   }
    2563             : 
    2564             :   Register object = ToRegister(instr->object());
    2565      239435 :   if (instr->hydrogen()->representation().IsDouble()) {
    2566             :     DCHECK(access.IsInobject());
    2567        2884 :     XMMRegister result = ToDoubleRegister(instr->result());
    2568        2884 :     __ Movsd(result, FieldOperand(object, offset));
    2569             :     return;
    2570             :   }
    2571             : 
    2572      237993 :   Register result = ToRegister(instr->result());
    2573      237993 :   if (!access.IsInobject()) {
    2574        2598 :     __ movp(result, FieldOperand(object, JSObject::kPropertiesOffset));
    2575             :     object = result;
    2576             :   }
    2577             : 
    2578             :   Representation representation = access.representation();
    2579      317462 :   if (representation.IsSmi() && SmiValuesAre32Bits() &&
    2580             :       instr->hydrogen()->representation().IsInteger32()) {
    2581       79469 :     if (FLAG_debug_code) {
    2582          12 :       Register scratch = kScratchRegister;
    2583          24 :       __ Load(scratch, FieldOperand(object, offset), representation);
    2584          12 :       __ AssertSmi(scratch);
    2585             :     }
    2586             : 
    2587             :     // Read int value directly from upper half of the smi.
    2588             :     STATIC_ASSERT(kSmiTag == 0);
    2589             :     DCHECK(kSmiTagSize + kSmiShiftSize == 32);
    2590       79469 :     offset += kPointerSize / 2;
    2591             :     representation = Representation::Integer32();
    2592             :   }
    2593      475986 :   __ Load(result, FieldOperand(object, offset), representation);
    2594             : }
    2595             : 
    2596             : 
    2597        5770 : void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
    2598             :   Register function = ToRegister(instr->function());
    2599        5770 :   Register result = ToRegister(instr->result());
    2600             : 
    2601             :   // Get the prototype or initial map from the function.
    2602       34620 :   __ movp(result,
    2603        5770 :          FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
    2604             : 
    2605             :   // Check that the function has a prototype or an initial map.
    2606        5770 :   __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
    2607             :   DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
    2608             : 
    2609             :   // If the function does not have an initial map, we're done.
    2610             :   Label done;
    2611        5770 :   __ CmpObjectType(result, MAP_TYPE, kScratchRegister);
    2612        5770 :   __ j(not_equal, &done, Label::kNear);
    2613             : 
    2614             :   // Get the prototype from the initial map.
    2615        5770 :   __ movp(result, FieldOperand(result, Map::kPrototypeOffset));
    2616             : 
    2617             :   // All done.
    2618        5770 :   __ bind(&done);
    2619        5770 : }
    2620             : 
    2621             : 
    2622        5183 : void LCodeGen::DoLoadRoot(LLoadRoot* instr) {
    2623       10366 :   Register result = ToRegister(instr->result());
    2624        5183 :   __ LoadRoot(result, instr->index());
    2625        5183 : }
    2626             : 
    2627             : 
    2628         595 : void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
    2629             :   Register arguments = ToRegister(instr->arguments());
    2630         595 :   Register result = ToRegister(instr->result());
    2631             : 
    2632         779 :   if (instr->length()->IsConstantOperand() &&
    2633             :       instr->index()->IsConstantOperand()) {
    2634             :     int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index()));
    2635             :     int32_t const_length = ToInteger32(LConstantOperand::cast(instr->length()));
    2636         184 :     if (const_index >= 0 && const_index < const_length) {
    2637             :       StackArgumentsAccessor args(arguments, const_length,
    2638             :                                   ARGUMENTS_DONT_CONTAIN_RECEIVER);
    2639        1006 :       __ movp(result, args.GetArgumentOperand(const_index));
    2640           0 :     } else if (FLAG_debug_code) {
    2641           0 :       __ int3();
    2642             :     }
    2643             :   } else {
    2644             :     Register length = ToRegister(instr->length());
    2645             :     // There are two words between the frame pointer and the last argument.
    2646             :     // Subtracting from length accounts for one of them add one more.
    2647         411 :     if (instr->index()->IsRegister()) {
    2648         411 :       __ subl(length, ToRegister(instr->index()));
    2649             :     } else {
    2650           0 :       __ subl(length, ToOperand(instr->index()));
    2651             :     }
    2652             :     StackArgumentsAccessor args(arguments, length,
    2653             :                                 ARGUMENTS_DONT_CONTAIN_RECEIVER);
    2654         822 :     __ movp(result, args.GetArgumentOperand(0));
    2655             :   }
    2656         595 : }
    2657             : 
    2658             : 
    2659        2027 : void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
    2660             :   ElementsKind elements_kind = instr->elements_kind();
    2661             :   LOperand* key = instr->key();
    2662             :   if (kPointerSize == kInt32Size && !key->IsConstantOperand()) {
    2663             :     Register key_reg = ToRegister(key);
    2664             :     Representation key_representation =
    2665             :         instr->hydrogen()->key()->representation();
    2666             :     if (ExternalArrayOpRequiresTemp(key_representation, elements_kind)) {
    2667        2108 :       __ SmiToInteger64(key_reg, key_reg);
    2668             :     } else if (instr->hydrogen()->IsDehoisted()) {
    2669             :       // Sign extend key because it could be a 32 bit negative value
    2670             :       // and the dehoisted address computation happens in 64 bits
    2671             :       __ movsxlq(key_reg, key_reg);
    2672             :     }
    2673             :   }
    2674             :   Operand operand(BuildFastArrayOperand(
    2675             :       instr->elements(),
    2676             :       key,
    2677             :       instr->hydrogen()->key()->representation(),
    2678             :       elements_kind,
    2679        2027 :       instr->base_offset()));
    2680             : 
    2681        2027 :   if (elements_kind == FLOAT32_ELEMENTS) {
    2682        1394 :     XMMRegister result(ToDoubleRegister(instr->result()));
    2683         697 :     __ Cvtss2sd(result, operand);
    2684        1330 :   } else if (elements_kind == FLOAT64_ELEMENTS) {
    2685         458 :     __ Movsd(ToDoubleRegister(instr->result()), operand);
    2686             :   } else {
    2687        1101 :     Register result(ToRegister(instr->result()));
    2688        1101 :     switch (elements_kind) {
    2689             :       case INT8_ELEMENTS:
    2690         165 :         __ movsxbl(result, operand);
    2691         165 :         break;
    2692             :       case UINT8_ELEMENTS:
    2693             :       case UINT8_CLAMPED_ELEMENTS:
    2694         369 :         __ movzxbl(result, operand);
    2695             :         break;
    2696             :       case INT16_ELEMENTS:
    2697         100 :         __ movsxwl(result, operand);
    2698         100 :         break;
    2699             :       case UINT16_ELEMENTS:
    2700         112 :         __ movzxwl(result, operand);
    2701             :         break;
    2702             :       case INT32_ELEMENTS:
    2703         151 :         __ movl(result, operand);
    2704             :         break;
    2705             :       case UINT32_ELEMENTS:
    2706         204 :         __ movl(result, operand);
    2707         408 :         if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
    2708          81 :           __ testl(result, result);
    2709             :           DeoptimizeIf(negative, instr, DeoptimizeReason::kNegativeValue);
    2710             :         }
    2711             :         break;
    2712             :       case FLOAT32_ELEMENTS:
    2713             :       case FLOAT64_ELEMENTS:
    2714             :       case FAST_ELEMENTS:
    2715             :       case FAST_SMI_ELEMENTS:
    2716             :       case FAST_DOUBLE_ELEMENTS:
    2717             :       case FAST_HOLEY_ELEMENTS:
    2718             :       case FAST_HOLEY_SMI_ELEMENTS:
    2719             :       case FAST_HOLEY_DOUBLE_ELEMENTS:
    2720             :       case DICTIONARY_ELEMENTS:
    2721             :       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
    2722             :       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
    2723             :       case FAST_STRING_WRAPPER_ELEMENTS:
    2724             :       case SLOW_STRING_WRAPPER_ELEMENTS:
    2725             :       case NO_ELEMENTS:
    2726           0 :         UNREACHABLE();
    2727             :         break;
    2728             :     }
    2729             :   }
    2730        2027 : }
    2731             : 
    2732             : 
    2733        6505 : void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
    2734       13010 :   XMMRegister result(ToDoubleRegister(instr->result()));
    2735             :   LOperand* key = instr->key();
    2736             :   if (kPointerSize == kInt32Size && !key->IsConstantOperand() &&
    2737             :       instr->hydrogen()->IsDehoisted()) {
    2738             :     // Sign extend key because it could be a 32 bit negative value
    2739             :     // and the dehoisted address computation happens in 64 bits
    2740        6944 :     __ movsxlq(ToRegister(key), ToRegister(key));
    2741             :   }
    2742        6505 :   if (instr->hydrogen()->RequiresHoleCheck()) {
    2743             :     Operand hole_check_operand = BuildFastArrayOperand(
    2744             :         instr->elements(),
    2745             :         key,
    2746             :         instr->hydrogen()->key()->representation(),
    2747             :         FAST_DOUBLE_ELEMENTS,
    2748         878 :         instr->base_offset() + sizeof(kHoleNanLower32));
    2749         439 :     __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32));
    2750             :     DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
    2751             :   }
    2752             : 
    2753             :   Operand double_load_operand = BuildFastArrayOperand(
    2754             :       instr->elements(),
    2755             :       key,
    2756             :       instr->hydrogen()->key()->representation(),
    2757             :       FAST_DOUBLE_ELEMENTS,
    2758        6505 :       instr->base_offset());
    2759        6505 :   __ Movsd(result, double_load_operand);
    2760        6505 : }
    2761             : 
    2762             : 
    2763       41344 : void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
    2764       39638 :   HLoadKeyed* hinstr = instr->hydrogen();
    2765       41344 :   Register result = ToRegister(instr->result());
    2766             :   LOperand* key = instr->key();
    2767       41344 :   bool requires_hole_check = hinstr->RequiresHoleCheck();
    2768             :   Representation representation = hinstr->representation();
    2769       41344 :   int offset = instr->base_offset();
    2770             : 
    2771             :   if (kPointerSize == kInt32Size && !key->IsConstantOperand() &&
    2772             :       instr->hydrogen()->IsDehoisted()) {
    2773             :     // Sign extend key because it could be a 32 bit negative value
    2774             :     // and the dehoisted address computation happens in 64 bits
    2775       54960 :     __ movsxlq(ToRegister(key), ToRegister(key));
    2776             :   }
    2777       48491 :   if (representation.IsInteger32() && SmiValuesAre32Bits() &&
    2778             :       hinstr->elements_kind() == FAST_SMI_ELEMENTS) {
    2779             :     DCHECK(!requires_hole_check);
    2780        7147 :     if (FLAG_debug_code) {
    2781           0 :       Register scratch = kScratchRegister;
    2782             :       __ Load(scratch,
    2783             :               BuildFastArrayOperand(instr->elements(),
    2784             :                                     key,
    2785             :                                     instr->hydrogen()->key()->representation(),
    2786             :                                     FAST_ELEMENTS,
    2787             :                                     offset),
    2788           0 :               Representation::Smi());
    2789           0 :       __ AssertSmi(scratch);
    2790             :     }
    2791             :     // Read int value directly from upper half of the smi.
    2792             :     STATIC_ASSERT(kSmiTag == 0);
    2793             :     DCHECK(kSmiTagSize + kSmiShiftSize == 32);
    2794        7147 :     offset += kPointerSize / 2;
    2795             :   }
    2796             : 
    2797             :   __ Load(result,
    2798             :           BuildFastArrayOperand(instr->elements(), key,
    2799             :                                 instr->hydrogen()->key()->representation(),
    2800       41344 :                                 FAST_ELEMENTS, offset),
    2801       82688 :           representation);
    2802             : 
    2803             :   // Check for the hole value.
    2804       41344 :   if (requires_hole_check) {
    2805        1706 :     if (IsFastSmiElementsKind(hinstr->elements_kind())) {
    2806         493 :       Condition smi = __ CheckSmi(result);
    2807             :       DeoptimizeIf(NegateCondition(smi), instr, DeoptimizeReason::kNotASmi);
    2808             :     } else {
    2809        1213 :       __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
    2810             :       DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
    2811             :     }
    2812       39638 :   } else if (hinstr->hole_mode() == CONVERT_HOLE_TO_UNDEFINED) {
    2813             :     DCHECK(hinstr->elements_kind() == FAST_HOLEY_ELEMENTS);
    2814             :     Label done;
    2815        2382 :     __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
    2816        2382 :     __ j(not_equal, &done);
    2817        2382 :     if (info()->IsStub()) {
    2818             :       // A stub can safely convert the hole to undefined only if the array
    2819             :       // protector cell contains (Smi) Isolate::kProtectorValid. Otherwise
    2820             :       // it needs to bail out.
    2821           0 :       __ LoadRoot(result, Heap::kArrayProtectorRootIndex);
    2822             :       __ Cmp(FieldOperand(result, PropertyCell::kValueOffset),
    2823           0 :              Smi::FromInt(Isolate::kProtectorValid));
    2824             :       DeoptimizeIf(not_equal, instr, DeoptimizeReason::kHole);
    2825             :     }
    2826        4764 :     __ Move(result, isolate()->factory()->undefined_value());
    2827        2382 :     __ bind(&done);
    2828             :   }
    2829       41344 : }
    2830             : 
    2831             : 
    2832       49876 : void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
    2833       49876 :   if (instr->is_fixed_typed_array()) {
    2834        2027 :     DoLoadKeyedExternalArray(instr);
    2835       47849 :   } else if (instr->hydrogen()->representation().IsDouble()) {
    2836        6505 :     DoLoadKeyedFixedDoubleArray(instr);
    2837             :   } else {
    2838       41344 :     DoLoadKeyedFixedArray(instr);
    2839             :   }
    2840       49876 : }
    2841             : 
    2842             : 
    2843       78872 : Operand LCodeGen::BuildFastArrayOperand(
    2844             :     LOperand* elements_pointer,
    2845             :     LOperand* key,
    2846             :     Representation key_representation,
    2847             :     ElementsKind elements_kind,
    2848             :     uint32_t offset) {
    2849       78872 :   Register elements_pointer_reg = ToRegister(elements_pointer);
    2850       78872 :   int shift_size = ElementsKindToShiftSize(elements_kind);
    2851       78872 :   if (key->IsConstantOperand()) {
    2852             :     int32_t constant_value = ToInteger32(LConstantOperand::cast(key));
    2853       36010 :     if (constant_value & 0xF0000000) {
    2854           5 :       Abort(kArrayIndexConstantValueTooBig);
    2855             :     }
    2856             :     return Operand(elements_pointer_reg,
    2857       36010 :                    (constant_value << shift_size) + offset);
    2858             :   } else {
    2859             :     // Guaranteed by ArrayInstructionInterface::KeyedAccessIndexRequirement().
    2860             :     DCHECK(key_representation.IsInteger32());
    2861             : 
    2862       42862 :     ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
    2863             :     return Operand(elements_pointer_reg,
    2864             :                    ToRegister(key),
    2865             :                    scale_factor,
    2866       85724 :                    offset);
    2867             :   }
    2868             : }
    2869             : 
    2870             : 
    2871         719 : void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
    2872         719 :   Register result = ToRegister(instr->result());
    2873             : 
    2874         719 :   if (instr->hydrogen()->from_inlined()) {
    2875        4642 :     __ leap(result, Operand(rsp, -kFPOnStackSize + -kPCOnStackSize));
    2876         534 :   } else if (instr->hydrogen()->arguments_adaptor()) {
    2877             :     // Check for arguments adapter frame.
    2878             :     Label done, adapted;
    2879        1602 :     __ movp(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
    2880             :     __ cmpp(Operand(result, CommonFrameConstants::kContextOrFrameTypeOffset),
    2881        1602 :             Immediate(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR)));
    2882         534 :     __ j(equal, &adapted, Label::kNear);
    2883             : 
    2884             :     // No arguments adaptor frame.
    2885         534 :     __ movp(result, rbp);
    2886         534 :     __ jmp(&done, Label::kNear);
    2887             : 
    2888             :     // Arguments adaptor frame present.
    2889         534 :     __ bind(&adapted);
    2890        1602 :     __ movp(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
    2891             : 
    2892             :     // Result is the frame pointer for the frame if not adapted and for the real
    2893             :     // frame below the adaptor frame if adapted.
    2894         534 :     __ bind(&done);
    2895             :   } else {
    2896           0 :     __ movp(result, rbp);
    2897             :   }
    2898         719 : }
    2899             : 
    2900             : 
    2901        1068 : void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
    2902         534 :   Register result = ToRegister(instr->result());
    2903             : 
    2904             :   Label done;
    2905             : 
    2906             :   // If no arguments adaptor frame the number of arguments is fixed.
    2907         534 :   if (instr->elements()->IsRegister()) {
    2908        3204 :     __ cmpp(rbp, ToRegister(instr->elements()));
    2909             :   } else {
    2910           0 :     __ cmpp(rbp, ToOperand(instr->elements()));
    2911             :   }
    2912        1068 :   __ movl(result, Immediate(scope()->num_parameters()));
    2913         534 :   __ j(equal, &done, Label::kNear);
    2914             : 
    2915             :   // Arguments adaptor frame present. Get argument length from there.
    2916        1602 :   __ movp(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
    2917             :   __ SmiToInteger32(result,
    2918             :                     Operand(result,
    2919        1068 :                             ArgumentsAdaptorFrameConstants::kLengthOffset));
    2920             : 
    2921             :   // Argument length is in result register.
    2922         534 :   __ bind(&done);
    2923         534 : }
    2924             : 
    2925             : 
    2926        4451 : void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
    2927             :   Register receiver = ToRegister(instr->receiver());
    2928             :   Register function = ToRegister(instr->function());
    2929             : 
    2930             :   // If the receiver is null or undefined, we have to pass the global
    2931             :   // object as a receiver to normal functions. Values have to be
    2932             :   // passed unchanged to builtins and strict-mode functions.
    2933             :   Label global_object, receiver_ok;
    2934        4451 :   Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
    2935             : 
    2936        4451 :   if (!instr->hydrogen()->known_function()) {
    2937             :     // Do not transform the receiver to object for strict mode
    2938             :     // functions.
    2939       75667 :     __ movp(kScratchRegister,
    2940        4451 :             FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
    2941             :     __ testb(FieldOperand(kScratchRegister,
    2942             :                           SharedFunctionInfo::kStrictModeByteOffset),
    2943        8902 :              Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
    2944        4451 :     __ j(not_equal, &receiver_ok, dist);
    2945             : 
    2946             :     // Do not transform the receiver to object for builtins.
    2947             :     __ testb(FieldOperand(kScratchRegister,
    2948             :                           SharedFunctionInfo::kNativeByteOffset),
    2949        8902 :              Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
    2950        4451 :     __ j(not_equal, &receiver_ok, dist);
    2951             :   }
    2952             : 
    2953             :   // Normal function. Replace undefined or null with global receiver.
    2954        4451 :   __ CompareRoot(receiver, Heap::kNullValueRootIndex);
    2955        4451 :   __ j(equal, &global_object, dist);
    2956        4451 :   __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex);
    2957        4451 :   __ j(equal, &global_object, dist);
    2958             : 
    2959             :   // The receiver should be a JS object.
    2960        4451 :   Condition is_smi = __ CheckSmi(receiver);
    2961             :   DeoptimizeIf(is_smi, instr, DeoptimizeReason::kSmi);
    2962        4451 :   __ CmpObjectType(receiver, FIRST_JS_RECEIVER_TYPE, kScratchRegister);
    2963             :   DeoptimizeIf(below, instr, DeoptimizeReason::kNotAJavaScriptObject);
    2964             : 
    2965        4451 :   __ jmp(&receiver_ok, dist);
    2966        4451 :   __ bind(&global_object);
    2967        4451 :   __ movp(receiver, FieldOperand(function, JSFunction::kContextOffset));
    2968        8902 :   __ movp(receiver, ContextOperand(receiver, Context::NATIVE_CONTEXT_INDEX));
    2969        8902 :   __ movp(receiver, ContextOperand(receiver, Context::GLOBAL_PROXY_INDEX));
    2970             : 
    2971        4451 :   __ bind(&receiver_ok);
    2972        4451 : }
    2973             : 
    2974             : 
    2975         136 : void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
    2976             :   Register receiver = ToRegister(instr->receiver());
    2977         136 :   Register function = ToRegister(instr->function());
    2978             :   Register length = ToRegister(instr->length());
    2979             :   Register elements = ToRegister(instr->elements());
    2980             :   DCHECK(receiver.is(rax));  // Used for parameter count.
    2981             :   DCHECK(function.is(rdi));  // Required by InvokeFunction.
    2982             :   DCHECK(ToRegister(instr->result()).is(rax));
    2983             : 
    2984             :   // Copy the arguments to this function possibly from the
    2985             :   // adaptor frame below it.
    2986             :   const uint32_t kArgumentsLimit = 1 * KB;
    2987        1496 :   __ cmpp(length, Immediate(kArgumentsLimit));
    2988             :   DeoptimizeIf(above, instr, DeoptimizeReason::kTooManyArguments);
    2989             : 
    2990         136 :   __ Push(receiver);
    2991         136 :   __ movp(receiver, length);
    2992             : 
    2993             :   // Loop through the arguments pushing them onto the execution
    2994             :   // stack.
    2995             :   Label invoke, loop;
    2996             :   // length is a small non-negative integer, due to the test above.
    2997         136 :   __ testl(length, length);
    2998         136 :   __ j(zero, &invoke, Label::kNear);
    2999         136 :   __ bind(&loop);
    3000             :   StackArgumentsAccessor args(elements, length,
    3001             :                               ARGUMENTS_DONT_CONTAIN_RECEIVER);
    3002         272 :   __ Push(args.GetArgumentOperand(0));
    3003         136 :   __ decl(length);
    3004         136 :   __ j(not_zero, &loop);
    3005             : 
    3006             :   // Invoke the function.
    3007         136 :   __ bind(&invoke);
    3008             : 
    3009             :   InvokeFlag flag = CALL_FUNCTION;
    3010         272 :   if (instr->hydrogen()->tail_call_mode() == TailCallMode::kAllow) {
    3011             :     DCHECK(!info()->saves_caller_doubles());
    3012             :     // TODO(ishell): drop current frame before pushing arguments to the stack.
    3013             :     flag = JUMP_FUNCTION;
    3014             :     ParameterCount actual(rax);
    3015             :     // It is safe to use rbx, rcx and r8 as scratch registers here given that
    3016             :     // 1) we are not going to return to caller function anyway,
    3017             :     // 2) rbx (expected number of arguments) will be initialized below.
    3018           0 :     PrepareForTailCall(actual, rbx, rcx, r8);
    3019             :   }
    3020             : 
    3021             :   DCHECK(instr->HasPointerMap());
    3022             :   LPointerMap* pointers = instr->pointer_map();
    3023             :   SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt);
    3024             :   ParameterCount actual(rax);
    3025         136 :   __ InvokeFunction(function, no_reg, actual, flag, safepoint_generator);
    3026         136 : }
    3027             : 
    3028             : 
    3029     1344576 : void LCodeGen::DoPushArgument(LPushArgument* instr) {
    3030             :   LOperand* argument = instr->value();
    3031     1344576 :   EmitPushTaggedOperand(argument);
    3032     1344576 : }
    3033             : 
    3034             : 
    3035         201 : void LCodeGen::DoDrop(LDrop* instr) {
    3036         201 :   __ Drop(instr->count());
    3037         201 : }
    3038             : 
    3039             : 
    3040       21913 : void LCodeGen::DoThisFunction(LThisFunction* instr) {
    3041       21913 :   Register result = ToRegister(instr->result());
    3042       43826 :   __ movp(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
    3043       21913 : }
    3044             : 
    3045             : 
    3046      281179 : void LCodeGen::DoContext(LContext* instr) {
    3047      281179 :   Register result = ToRegister(instr->result());
    3048      538878 :   if (info()->IsOptimizing()) {
    3049      773091 :     __ movp(result, Operand(rbp, StandardFrameConstants::kContextOffset));
    3050             :   } else {
    3051             :     // If there is no frame, the context must be in rsi.
    3052             :     DCHECK(result.is(rsi));
    3053             :   }
    3054      281181 : }
    3055             : 
    3056             : 
    3057       12327 : void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
    3058             :   DCHECK(ToRegister(instr->context()).is(rsi));
    3059       36981 :   __ Push(instr->hydrogen()->declarations());
    3060       24654 :   __ Push(Smi::FromInt(instr->hydrogen()->flags()));
    3061       12327 :   __ Push(instr->hydrogen()->feedback_vector());
    3062       12327 :   CallRuntime(Runtime::kDeclareGlobals, instr);
    3063       12327 : }
    3064             : 
    3065      121555 : void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
    3066             :                                  int formal_parameter_count, int arity,
    3067             :                                  bool is_tail_call, LInstruction* instr) {
    3068             :   bool dont_adapt_arguments =
    3069      121555 :       formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
    3070             :   bool can_invoke_directly =
    3071      121555 :       dont_adapt_arguments || formal_parameter_count == arity;
    3072             : 
    3073             :   Register function_reg = rdi;
    3074             :   LPointerMap* pointers = instr->pointer_map();
    3075             : 
    3076      121555 :   if (can_invoke_directly) {
    3077             :     // Change context.
    3078      554609 :     __ movp(rsi, FieldOperand(function_reg, JSFunction::kContextOffset));
    3079             : 
    3080             :     // Always initialize new target and number of actual arguments.
    3081      108263 :     __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
    3082      216528 :     __ Set(rax, arity);
    3083             : 
    3084             :     bool is_self_call = function.is_identical_to(info()->closure());
    3085             : 
    3086             :     // Invoke function.
    3087      108263 :     if (is_self_call) {
    3088             :       Handle<Code> self(reinterpret_cast<Code**>(__ CodeObject().location()));
    3089         413 :       if (is_tail_call) {
    3090          14 :         __ Jump(self, RelocInfo::CODE_TARGET);
    3091             :       } else {
    3092         399 :         __ Call(self, RelocInfo::CODE_TARGET);
    3093             :       }
    3094             :     } else {
    3095      107850 :       Operand target = FieldOperand(function_reg, JSFunction::kCodeEntryOffset);
    3096      107850 :       if (is_tail_call) {
    3097           9 :         __ Jump(target);
    3098             :       } else {
    3099      107841 :         __ Call(target);
    3100             :       }
    3101             :     }
    3102             : 
    3103      108263 :     if (!is_tail_call) {
    3104             :       // Set up deoptimization.
    3105      108241 :       RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0);
    3106             :     }
    3107             :   } else {
    3108             :     // We need to adapt arguments.
    3109             :     SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
    3110             :     ParameterCount actual(arity);
    3111             :     ParameterCount expected(formal_parameter_count);
    3112       13292 :     InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION;
    3113       13292 :     __ InvokeFunction(function_reg, no_reg, expected, actual, flag, generator);
    3114             :   }
    3115      121555 : }
    3116             : 
    3117             : 
    3118      847423 : void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
    3119             :   DCHECK(ToRegister(instr->result()).is(rax));
    3120             : 
    3121      847423 :   if (instr->hydrogen()->IsTailCall()) {
    3122      847423 :     if (NeedsEagerFrame()) __ leave();
    3123             : 
    3124           0 :     if (instr->target()->IsConstantOperand()) {
    3125             :       LConstantOperand* target = LConstantOperand::cast(instr->target());
    3126           0 :       Handle<Code> code = Handle<Code>::cast(ToHandle(target));
    3127           0 :       __ jmp(code, RelocInfo::CODE_TARGET);
    3128             :     } else {
    3129             :       DCHECK(instr->target()->IsRegister());
    3130           0 :       Register target = ToRegister(instr->target());
    3131           0 :       __ addp(target, Immediate(Code::kHeaderSize - kHeapObjectTag));
    3132           0 :       __ jmp(target);
    3133             :     }
    3134             :   } else {
    3135             :     LPointerMap* pointers = instr->pointer_map();
    3136             :     SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
    3137             : 
    3138      847423 :     if (instr->target()->IsConstantOperand()) {
    3139             :       LConstantOperand* target = LConstantOperand::cast(instr->target());
    3140      847423 :       Handle<Code> code = Handle<Code>::cast(ToHandle(target));
    3141             :       generator.BeforeCall(__ CallSize(code));
    3142      847423 :       __ call(code, RelocInfo::CODE_TARGET);
    3143             :     } else {
    3144             :       DCHECK(instr->target()->IsRegister());
    3145             :       Register target = ToRegister(instr->target());
    3146             :       generator.BeforeCall(__ CallSize(target));
    3147           0 :       __ addp(target, Immediate(Code::kHeaderSize - kHeapObjectTag));
    3148           0 :       __ call(target);
    3149             :     }
    3150      847423 :     generator.AfterCall();
    3151             :   }
    3152      847425 : }
    3153             : 
    3154             : 
    3155          79 : void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
    3156             :   Register input_reg = ToRegister(instr->value());
    3157             :   __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
    3158        1207 :                  Heap::kHeapNumberMapRootIndex);
    3159             :   DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumber);
    3160             : 
    3161             :   Label slow, allocated, done;
    3162             :   uint32_t available_regs = rax.bit() | rcx.bit() | rdx.bit() | rbx.bit();
    3163          79 :   available_regs &= ~input_reg.bit();
    3164          79 :   if (instr->context()->IsRegister()) {
    3165             :     // Make sure that the context isn't overwritten in the AllocateHeapNumber
    3166             :     // macro below.
    3167          10 :     available_regs &= ~ToRegister(instr->context()).bit();
    3168             :   }
    3169             : 
    3170             :   Register tmp =
    3171          79 :       Register::from_code(base::bits::CountTrailingZeros32(available_regs));
    3172          79 :   available_regs &= ~tmp.bit();
    3173             :   Register tmp2 =
    3174          79 :       Register::from_code(base::bits::CountTrailingZeros32(available_regs));
    3175             : 
    3176             :   // Preserve the value of all registers.
    3177             :   PushSafepointRegistersScope scope(this);
    3178             : 
    3179          79 :   __ movl(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
    3180             :   // Check the sign of the argument. If the argument is positive, just
    3181             :   // return it. We do not need to patch the stack since |input| and
    3182             :   // |result| are the same register and |input| will be restored
    3183             :   // unchanged by popping safepoint registers.
    3184          79 :   __ testl(tmp, Immediate(HeapNumber::kSignMask));
    3185          79 :   __ j(zero, &done);
    3186             : 
    3187          79 :   __ AllocateHeapNumber(tmp, tmp2, &slow);
    3188          79 :   __ jmp(&allocated, Label::kNear);
    3189             : 
    3190             :   // Slow case: Call the runtime system to do the number allocation.
    3191          79 :   __ bind(&slow);
    3192             :   CallRuntimeFromDeferred(
    3193          79 :       Runtime::kAllocateHeapNumber, 0, instr, instr->context());
    3194             :   // Set the pointer to the new heap number in tmp.
    3195         101 :   if (!tmp.is(rax)) __ movp(tmp, rax);
    3196             :   // Restore input_reg after call to runtime.
    3197          79 :   __ LoadFromSafepointRegisterSlot(input_reg, input_reg);
    3198             : 
    3199          79 :   __ bind(&allocated);
    3200          79 :   __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset));
    3201          79 :   __ shlq(tmp2, Immediate(1));
    3202          79 :   __ shrq(tmp2, Immediate(1));
    3203          79 :   __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2);
    3204          79 :   __ StoreToSafepointRegisterSlot(input_reg, tmp);
    3205             : 
    3206          79 :   __ bind(&done);
    3207          79 : }
    3208             : 
    3209             : 
    3210          52 : void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
    3211             :   Register input_reg = ToRegister(instr->value());
    3212         208 :   __ testl(input_reg, input_reg);
    3213             :   Label is_positive;
    3214          52 :   __ j(not_sign, &is_positive, Label::kNear);
    3215          52 :   __ negl(input_reg);  // Sets flags.
    3216             :   DeoptimizeIf(negative, instr, DeoptimizeReason::kOverflow);
    3217          52 :   __ bind(&is_positive);
    3218          52 : }
    3219             : 
    3220             : 
    3221          79 : void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) {
    3222             :   Register input_reg = ToRegister(instr->value());
    3223         316 :   __ testp(input_reg, input_reg);
    3224             :   Label is_positive;
    3225          79 :   __ j(not_sign, &is_positive, Label::kNear);
    3226          79 :   __ negp(input_reg);  // Sets flags.
    3227             :   DeoptimizeIf(negative, instr, DeoptimizeReason::kOverflow);
    3228          79 :   __ bind(&is_positive);
    3229          79 : }
    3230             : 
    3231             : 
    3232         304 : void LCodeGen::DoMathAbs(LMathAbs* instr) {
    3233             :   // Class for deferred case.
    3234           0 :   class DeferredMathAbsTaggedHeapNumber final : public LDeferredCode {
    3235             :    public:
    3236             :     DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr)
    3237          79 :         : LDeferredCode(codegen), instr_(instr) { }
    3238          79 :     void Generate() override {
    3239          79 :       codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
    3240          79 :     }
    3241         158 :     LInstruction* instr() override { return instr_; }
    3242             : 
    3243             :    private:
    3244             :     LMathAbs* instr_;
    3245             :   };
    3246             : 
    3247             :   DCHECK(instr->value()->Equals(instr->result()));
    3248             :   Representation r = instr->hydrogen()->value()->representation();
    3249             : 
    3250         304 :   if (r.IsDouble()) {
    3251         173 :     XMMRegister scratch = double_scratch0();
    3252         173 :     XMMRegister input_reg = ToDoubleRegister(instr->value());
    3253         583 :     __ Xorpd(scratch, scratch);
    3254         173 :     __ Subsd(scratch, input_reg);
    3255         173 :     __ Andpd(input_reg, scratch);
    3256         131 :   } else if (r.IsInteger32()) {
    3257          52 :     EmitIntegerMathAbs(instr);
    3258          79 :   } else if (r.IsSmi()) {
    3259           0 :     EmitSmiMathAbs(instr);
    3260             :   } else {  // Tagged case.
    3261             :     DeferredMathAbsTaggedHeapNumber* deferred =
    3262             :         new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr);
    3263          79 :     Register input_reg = ToRegister(instr->value());
    3264             :     // Smi check.
    3265         158 :     __ JumpIfNotSmi(input_reg, deferred->entry());
    3266          79 :     EmitSmiMathAbs(instr);
    3267          79 :     __ bind(deferred->exit());
    3268             :   }
    3269         304 : }
    3270             : 
    3271        4495 : void LCodeGen::DoMathFloorD(LMathFloorD* instr) {
    3272        8990 :   XMMRegister output_reg = ToDoubleRegister(instr->result());
    3273        4495 :   XMMRegister input_reg = ToDoubleRegister(instr->value());
    3274        4495 :   CpuFeatureScope scope(masm(), SSE4_1);
    3275        4495 :   __ Roundsd(output_reg, input_reg, kRoundDown);
    3276        4495 : }
    3277             : 
    3278       18256 : void LCodeGen::DoMathFloorI(LMathFloorI* instr) {
    3279       18256 :   XMMRegister xmm_scratch = double_scratch0();
    3280       18256 :   Register output_reg = ToRegister(instr->result());
    3281       18256 :   XMMRegister input_reg = ToDoubleRegister(instr->value());
    3282             : 
    3283       18256 :   if (CpuFeatures::IsSupported(SSE4_1)) {
    3284       91496 :     CpuFeatureScope scope(masm(), SSE4_1);
    3285       36472 :     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
    3286             :       // Deoptimize if minus zero.
    3287       18204 :       __ Movq(output_reg, input_reg);
    3288       18204 :       __ subq(output_reg, Immediate(1));
    3289             :       DeoptimizeIf(overflow, instr, DeoptimizeReason::kMinusZero);
    3290             :     }
    3291       18236 :     __ Roundsd(xmm_scratch, input_reg, kRoundDown);
    3292       18236 :     __ Cvttsd2si(output_reg, xmm_scratch);
    3293       18236 :     __ cmpl(output_reg, Immediate(0x1));
    3294             :     DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
    3295             :   } else {
    3296             :     Label negative_sign, done;
    3297             :     // Deoptimize on unordered.
    3298          20 :     __ Xorpd(xmm_scratch, xmm_scratch);  // Zero the register.
    3299          20 :     __ Ucomisd(input_reg, xmm_scratch);
    3300             :     DeoptimizeIf(parity_even, instr, DeoptimizeReason::kNaN);
    3301          20 :     __ j(below, &negative_sign, Label::kNear);
    3302             : 
    3303          40 :     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
    3304             :       // Check for negative zero.
    3305             :       Label positive_sign;
    3306          20 :       __ j(above, &positive_sign, Label::kNear);
    3307          20 :       __ Movmskpd(output_reg, input_reg);
    3308          20 :       __ testl(output_reg, Immediate(1));
    3309             :       DeoptimizeIf(not_zero, instr, DeoptimizeReason::kMinusZero);
    3310          20 :       __ Set(output_reg, 0);
    3311          20 :       __ jmp(&done);
    3312          20 :       __ bind(&positive_sign);
    3313             :     }
    3314             : 
    3315             :     // Use truncating instruction (OK because input is positive).
    3316          20 :     __ Cvttsd2si(output_reg, input_reg);
    3317             :     // Overflow is signalled with minint.
    3318          20 :     __ cmpl(output_reg, Immediate(0x1));
    3319             :     DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
    3320          20 :     __ jmp(&done, Label::kNear);
    3321             : 
    3322             :     // Non-zero negative reaches here.
    3323          20 :     __ bind(&negative_sign);
    3324             :     // Truncate, then compare and compensate.
    3325          20 :     __ Cvttsd2si(output_reg, input_reg);
    3326          20 :     __ Cvtlsi2sd(xmm_scratch, output_reg);
    3327          20 :     __ Ucomisd(input_reg, xmm_scratch);
    3328          20 :     __ j(equal, &done, Label::kNear);
    3329          20 :     __ subl(output_reg, Immediate(1));
    3330             :     DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
    3331             : 
    3332          20 :     __ bind(&done);
    3333             :   }
    3334       18256 : }
    3335             : 
    3336         627 : void LCodeGen::DoMathRoundD(LMathRoundD* instr) {
    3337             :   XMMRegister xmm_scratch = double_scratch0();
    3338        1254 :   XMMRegister output_reg = ToDoubleRegister(instr->result());
    3339         627 :   XMMRegister input_reg = ToDoubleRegister(instr->value());
    3340        5016 :   CpuFeatureScope scope(masm(), SSE4_1);
    3341             :   Label done;
    3342         627 :   __ Roundsd(output_reg, input_reg, kRoundUp);
    3343             :   __ Move(xmm_scratch, -0.5);
    3344         627 :   __ Addsd(xmm_scratch, output_reg);
    3345         627 :   __ Ucomisd(xmm_scratch, input_reg);
    3346         627 :   __ j(below_equal, &done, Label::kNear);
    3347             :   __ Move(xmm_scratch, 1.0);
    3348         627 :   __ Subsd(output_reg, xmm_scratch);
    3349         627 :   __ bind(&done);
    3350         627 : }
    3351             : 
    3352         700 : void LCodeGen::DoMathRoundI(LMathRoundI* instr) {
    3353         700 :   const XMMRegister xmm_scratch = double_scratch0();
    3354         700 :   Register output_reg = ToRegister(instr->result());
    3355         700 :   XMMRegister input_reg = ToDoubleRegister(instr->value());
    3356         700 :   XMMRegister input_temp = ToDoubleRegister(instr->temp());
    3357             :   static int64_t one_half = V8_INT64_C(0x3FE0000000000000);  // 0.5
    3358             :   static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000);  // -0.5
    3359             : 
    3360             :   Label done, round_to_zero, below_one_half;
    3361         700 :   Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
    3362       18174 :   __ movq(kScratchRegister, one_half);
    3363         700 :   __ Movq(xmm_scratch, kScratchRegister);
    3364         700 :   __ Ucomisd(xmm_scratch, input_reg);
    3365         700 :   __ j(above, &below_one_half, Label::kNear);
    3366             : 
    3367             :   // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
    3368         700 :   __ Addsd(xmm_scratch, input_reg);
    3369         700 :   __ Cvttsd2si(output_reg, xmm_scratch);
    3370             :   // Overflow is signalled with minint.
    3371         700 :   __ cmpl(output_reg, Immediate(0x1));
    3372             :   DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
    3373         700 :   __ jmp(&done, dist);
    3374             : 
    3375         700 :   __ bind(&below_one_half);
    3376        1400 :   __ movq(kScratchRegister, minus_one_half);
    3377         700 :   __ Movq(xmm_scratch, kScratchRegister);
    3378         700 :   __ Ucomisd(xmm_scratch, input_reg);
    3379         700 :   __ j(below_equal, &round_to_zero, Label::kNear);
    3380             : 
    3381             :   // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
    3382             :   // compare and compensate.
    3383         700 :   __ Movapd(input_temp, input_reg);  // Do not alter input_reg.
    3384         700 :   __ Subsd(input_temp, xmm_scratch);
    3385         700 :   __ Cvttsd2si(output_reg, input_temp);
    3386             :   // Catch minint due to overflow, and to prevent overflow when compensating.
    3387         700 :   __ cmpl(output_reg, Immediate(0x1));
    3388             :   DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
    3389             : 
    3390         700 :   __ Cvtlsi2sd(xmm_scratch, output_reg);
    3391         700 :   __ Ucomisd(xmm_scratch, input_temp);
    3392         700 :   __ j(equal, &done, dist);
    3393         700 :   __ subl(output_reg, Immediate(1));
    3394             :   // No overflow because we already ruled out minint.
    3395         700 :   __ jmp(&done, dist);
    3396             : 
    3397         700 :   __ bind(&round_to_zero);
    3398             :   // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
    3399             :   // we can ignore the difference between a result of -0 and +0.
    3400        1400 :   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
    3401         687 :     __ Movq(output_reg, input_reg);
    3402         687 :     __ testq(output_reg, output_reg);
    3403             :     DeoptimizeIf(negative, instr, DeoptimizeReason::kMinusZero);
    3404             :   }
    3405         700 :   __ Set(output_reg, 0);
    3406         700 :   __ bind(&done);
    3407         700 : }
    3408             : 
    3409             : 
    3410         630 : void LCodeGen::DoMathFround(LMathFround* instr) {
    3411         630 :   XMMRegister input_reg = ToDoubleRegister(instr->value());
    3412        1260 :   XMMRegister output_reg = ToDoubleRegister(instr->result());
    3413         630 :   __ Cvtsd2ss(output_reg, input_reg);
    3414         630 :   __ Cvtss2sd(output_reg, output_reg);
    3415         630 : }
    3416             : 
    3417             : 
    3418          62 : void LCodeGen::DoMathSqrt(LMathSqrt* instr) {
    3419         124 :   XMMRegister output = ToDoubleRegister(instr->result());
    3420          62 :   if (instr->value()->IsDoubleRegister()) {
    3421          59 :     XMMRegister input = ToDoubleRegister(instr->value());
    3422          62 :     __ Sqrtsd(output, input);
    3423             :   } else {
    3424           3 :     Operand input = ToOperand(instr->value());
    3425           3 :     __ Sqrtsd(output, input);
    3426             :   }
    3427          62 : }
    3428             : 
    3429             : 
    3430          41 : void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
    3431          41 :   XMMRegister xmm_scratch = double_scratch0();
    3432          41 :   XMMRegister input_reg = ToDoubleRegister(instr->value());
    3433             :   DCHECK(ToDoubleRegister(instr->result()).is(input_reg));
    3434             : 
    3435             :   // Note that according to ECMA-262 15.8.2.13:
    3436             :   // Math.pow(-Infinity, 0.5) == Infinity
    3437             :   // Math.sqrt(-Infinity) == NaN
    3438             :   Label done, sqrt;
    3439             :   // Check base for -Infinity.  According to IEEE-754, double-precision
    3440             :   // -Infinity has the highest 12 bits set and the lowest 52 bits cleared.
    3441         492 :   __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000));
    3442          41 :   __ Movq(xmm_scratch, kScratchRegister);
    3443          41 :   __ Ucomisd(xmm_scratch, input_reg);
    3444             :   // Comparing -Infinity with NaN results in "unordered", which sets the
    3445             :   // zero flag as if both were equal.  However, it also sets the carry flag.
    3446          41 :   __ j(not_equal, &sqrt, Label::kNear);
    3447          41 :   __ j(carry, &sqrt, Label::kNear);
    3448             :   // If input is -Infinity, return Infinity.
    3449          41 :   __ Xorpd(input_reg, input_reg);
    3450          41 :   __ Subsd(input_reg, xmm_scratch);
    3451          41 :   __ jmp(&done, Label::kNear);
    3452             : 
    3453             :   // Square root.
    3454          41 :   __ bind(&sqrt);
    3455          41 :   __ Xorpd(xmm_scratch, xmm_scratch);
    3456          41 :   __ Addsd(input_reg, xmm_scratch);  // Convert -0 to +0.
    3457          41 :   __ Sqrtsd(input_reg, input_reg);
    3458          41 :   __ bind(&done);
    3459          41 : }
    3460             : 
    3461             : 
    3462         829 : void LCodeGen::DoPower(LPower* instr) {
    3463             :   Representation exponent_type = instr->hydrogen()->right()->representation();
    3464             :   // Having marked this as a call, we can use any registers.
    3465             :   // Just make sure that the input/output registers are the expected ones.
    3466             : 
    3467         829 :   Register tagged_exponent = MathPowTaggedDescriptor::exponent();
    3468             :   DCHECK(!instr->right()->IsRegister() ||
    3469             :          ToRegister(instr->right()).is(tagged_exponent));
    3470             :   DCHECK(!instr->right()->IsDoubleRegister() ||
    3471             :          ToDoubleRegister(instr->right()).is(xmm1));
    3472             :   DCHECK(ToDoubleRegister(instr->left()).is(xmm2));
    3473             :   DCHECK(ToDoubleRegister(instr->result()).is(xmm3));
    3474             : 
    3475         829 :   if (exponent_type.IsSmi()) {
    3476        1066 :     MathPowStub stub(isolate(), MathPowStub::TAGGED);
    3477           0 :     __ CallStub(&stub);
    3478         829 :   } else if (exponent_type.IsTagged()) {
    3479             :     Label no_deopt;
    3480          79 :     __ JumpIfSmi(tagged_exponent, &no_deopt, Label::kNear);
    3481          79 :     __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, rcx);
    3482             :     DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumber);
    3483          79 :     __ bind(&no_deopt);
    3484          79 :     MathPowStub stub(isolate(), MathPowStub::TAGGED);
    3485          79 :     __ CallStub(&stub);
    3486         750 :   } else if (exponent_type.IsInteger32()) {
    3487         362 :     MathPowStub stub(isolate(), MathPowStub::INTEGER);
    3488         362 :     __ CallStub(&stub);
    3489             :   } else {
    3490             :     DCHECK(exponent_type.IsDouble());
    3491         388 :     MathPowStub stub(isolate(), MathPowStub::DOUBLE);
    3492         388 :     __ CallStub(&stub);
    3493             :   }
    3494         829 : }
    3495             : 
    3496          60 : void LCodeGen::DoMathCos(LMathCos* instr) {
    3497             :   DCHECK(ToDoubleRegister(instr->value()).is(xmm0));
    3498             :   DCHECK(ToDoubleRegister(instr->result()).is(xmm0));
    3499         120 :   __ PrepareCallCFunction(1);
    3500         120 :   __ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 1);
    3501          60 : }
    3502             : 
    3503          58 : void LCodeGen::DoMathExp(LMathExp* instr) {
    3504             :   DCHECK(ToDoubleRegister(instr->value()).is(xmm0));
    3505             :   DCHECK(ToDoubleRegister(instr->result()).is(xmm0));
    3506         116 :   __ PrepareCallCFunction(1);
    3507         116 :   __ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 1);
    3508          58 : }
    3509             : 
    3510          90 : void LCodeGen::DoMathSin(LMathSin* instr) {
    3511             :   DCHECK(ToDoubleRegister(instr->value()).is(xmm0));
    3512             :   DCHECK(ToDoubleRegister(instr->result()).is(xmm0));
    3513         180 :   __ PrepareCallCFunction(1);
    3514         180 :   __ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 1);
    3515          90 : }
    3516             : 
    3517         291 : void LCodeGen::DoMathLog(LMathLog* instr) {
    3518             :   DCHECK(ToDoubleRegister(instr->value()).is(xmm0));
    3519             :   DCHECK(ToDoubleRegister(instr->result()).is(xmm0));
    3520         582 :   __ PrepareCallCFunction(1);
    3521         582 :   __ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 1);
    3522         291 : }
    3523             : 
    3524             : 
    3525          42 : void LCodeGen::DoMathClz32(LMathClz32* instr) {
    3526          42 :   Register input = ToRegister(instr->value());
    3527          84 :   Register result = ToRegister(instr->result());
    3528             : 
    3529          42 :   __ Lzcntl(result, input);
    3530          42 : }
    3531             : 
    3532          37 : void LCodeGen::PrepareForTailCall(const ParameterCount& actual,
    3533             :                                   Register scratch1, Register scratch2,
    3534             :                                   Register scratch3) {
    3535             : #if DEBUG
    3536             :   if (actual.is_reg()) {
    3537             :     DCHECK(!AreAliased(actual.reg(), scratch1, scratch2, scratch3));
    3538             :   } else {
    3539             :     DCHECK(!AreAliased(scratch1, scratch2, scratch3));
    3540             :   }
    3541             : #endif
    3542          37 :   if (FLAG_code_comments) {
    3543           0 :     if (actual.is_reg()) {
    3544             :       Comment(";;; PrepareForTailCall, actual: %s {",
    3545             :               RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
    3546         407 :                   actual.reg().code()));
    3547             :     } else {
    3548           0 :       Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
    3549             :     }
    3550             :   }
    3551             : 
    3552             :   // Check if next frame is an arguments adaptor frame.
    3553          37 :   Register caller_args_count_reg = scratch1;
    3554             :   Label no_arguments_adaptor, formal_parameter_count_loaded;
    3555         111 :   __ movp(scratch2, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
    3556             :   __ cmpp(Operand(scratch2, CommonFrameConstants::kContextOrFrameTypeOffset),
    3557         111 :           Immediate(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR)));
    3558          37 :   __ j(not_equal, &no_arguments_adaptor, Label::kNear);
    3559             : 
    3560             :   // Drop current frame and load arguments count from arguments adaptor frame.
    3561          37 :   __ movp(rbp, scratch2);
    3562             :   __ SmiToInteger32(
    3563             :       caller_args_count_reg,
    3564          74 :       Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset));
    3565          37 :   __ jmp(&formal_parameter_count_loaded, Label::kNear);
    3566             : 
    3567          37 :   __ bind(&no_arguments_adaptor);
    3568             :   // Load caller's formal parameter count.
    3569             :   __ movp(caller_args_count_reg,
    3570          74 :           Immediate(info()->literal()->parameter_count()));
    3571             : 
    3572          37 :   __ bind(&formal_parameter_count_loaded);
    3573             :   __ PrepareForTailCall(actual, caller_args_count_reg, scratch2, scratch3,
    3574          37 :                         ReturnAddressState::kNotOnStack);
    3575          37 :   Comment(";;; }");
    3576          37 : }
    3577             : 
    3578      126042 : void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
    3579      247598 :   HInvokeFunction* hinstr = instr->hydrogen();
    3580             :   DCHECK(ToRegister(instr->context()).is(rsi));
    3581             :   DCHECK(ToRegister(instr->function()).is(rdi));
    3582             :   DCHECK(instr->HasPointerMap());
    3583             : 
    3584      126042 :   bool is_tail_call = hinstr->tail_call_mode() == TailCallMode::kAllow;
    3585             : 
    3586      126042 :   if (is_tail_call) {
    3587             :     DCHECK(!info()->saves_caller_doubles());
    3588             :     ParameterCount actual(instr->arity());
    3589             :     // It is safe to use rbx, rcx and r8 as scratch registers here given that
    3590             :     // 1) we are not going to return to caller function anyway,
    3591             :     // 2) rbx (expected number of arguments) will be initialized below.
    3592          37 :     PrepareForTailCall(actual, rbx, rcx, r8);
    3593             :   }
    3594             : 
    3595             :   Handle<JSFunction> known_function = hinstr->known_function();
    3596      126042 :   if (known_function.is_null()) {
    3597             :     LPointerMap* pointers = instr->pointer_map();
    3598             :     SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
    3599             :     ParameterCount actual(instr->arity());
    3600        4487 :     InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION;
    3601        4487 :     __ InvokeFunction(rdi, no_reg, actual, flag, generator);
    3602             :   } else {
    3603             :     CallKnownFunction(known_function, hinstr->formal_parameter_count(),
    3604      243111 :                       instr->arity(), is_tail_call, instr);
    3605             :   }
    3606      126043 : }
    3607             : 
    3608             : 
    3609         371 : void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
    3610             :   DCHECK(ToRegister(instr->context()).is(rsi));
    3611             :   DCHECK(ToRegister(instr->constructor()).is(rdi));
    3612             :   DCHECK(ToRegister(instr->result()).is(rax));
    3613             : 
    3614        1112 :   __ Set(rax, instr->arity());
    3615         371 :   __ Move(rbx, instr->hydrogen()->site());
    3616             : 
    3617         371 :   ElementsKind kind = instr->hydrogen()->elements_kind();
    3618             :   AllocationSiteOverrideMode override_mode =
    3619             :       (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
    3620             :           ? DISABLE_ALLOCATION_SITES
    3621         371 :           : DONT_OVERRIDE;
    3622             : 
    3623         371 :   if (instr->arity() == 0) {
    3624           0 :     ArrayNoArgumentConstructorStub stub(isolate(), kind, override_mode);
    3625           0 :     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
    3626         371 :   } else if (instr->arity() == 1) {
    3627             :     Label done;
    3628         315 :     if (IsFastPackedElementsKind(kind)) {
    3629             :       Label packed_case;
    3630             :       // We might need a change here
    3631             :       // look at the first argument
    3632          33 :       __ movp(rcx, Operand(rsp, 0));
    3633          11 :       __ testp(rcx, rcx);
    3634          11 :       __ j(zero, &packed_case, Label::kNear);
    3635             : 
    3636             :       ElementsKind holey_kind = GetHoleyElementsKind(kind);
    3637             :       ArraySingleArgumentConstructorStub stub(isolate(),
    3638             :                                               holey_kind,
    3639          11 :                                               override_mode);
    3640          11 :       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
    3641          11 :       __ jmp(&done, Label::kNear);
    3642          11 :       __ bind(&packed_case);
    3643             :     }
    3644             : 
    3645         315 :     ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode);
    3646         315 :     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
    3647         315 :     __ bind(&done);
    3648             :   } else {
    3649          56 :     ArrayNArgumentsConstructorStub stub(isolate());
    3650          56 :     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
    3651             :   }
    3652         371 : }
    3653             : 
    3654             : 
    3655      102992 : void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
    3656             :   DCHECK(ToRegister(instr->context()).is(rsi));
    3657      102992 :   CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles());
    3658      102992 : }
    3659             : 
    3660             : 
    3661           0 : void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
    3662             :   Register function = ToRegister(instr->function());
    3663             :   Register code_object = ToRegister(instr->code_object());
    3664           0 :   __ leap(code_object, FieldOperand(code_object, Code::kHeaderSize));
    3665           0 :   __ movp(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object);
    3666           0 : }
    3667             : 
    3668             : 
    3669        7136 : void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
    3670        7136 :   Register result = ToRegister(instr->result());
    3671        7136 :   Register base = ToRegister(instr->base_object());
    3672        7136 :   if (instr->offset()->IsConstantOperand()) {
    3673             :     LConstantOperand* offset = LConstantOperand::cast(instr->offset());
    3674       10704 :     __ leap(result, Operand(base, ToInteger32(offset)));
    3675             :   } else {
    3676        3568 :     Register offset = ToRegister(instr->offset());
    3677       10704 :     __ leap(result, Operand(base, offset, times_1, 0));
    3678             :   }
    3679        7136 : }
    3680             : 
    3681             : 
    3682      174793 : void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
    3683      174793 :   HStoreNamedField* hinstr = instr->hydrogen();
    3684             :   Representation representation = instr->representation();
    3685             : 
    3686             :   HObjectAccess access = hinstr->access();
    3687             :   int offset = access.offset();
    3688             : 
    3689      174793 :   if (access.IsExternalMemory()) {
    3690             :     DCHECK(!hinstr->NeedsWriteBarrier());
    3691           0 :     Register value = ToRegister(instr->value());
    3692           0 :     if (instr->object()->IsConstantOperand()) {
    3693             :       DCHECK(value.is(rax));
    3694             :       LConstantOperand* object = LConstantOperand::cast(instr->object());
    3695      389874 :       __ store_rax(ToExternalReference(object));
    3696             :     } else {
    3697           0 :       Register object = ToRegister(instr->object());
    3698           0 :       __ Store(MemOperand(object, offset), value, representation);
    3699             :     }
    3700             :     return;
    3701             :   }
    3702             : 
    3703             :   Register object = ToRegister(instr->object());
    3704      174793 :   __ AssertNotSmi(object);
    3705             : 
    3706             :   DCHECK(!representation.IsSmi() ||
    3707             :          !instr->value()->IsConstantOperand() ||
    3708             :          IsInteger32Constant(LConstantOperand::cast(instr->value())));
    3709             :   if (!FLAG_unbox_double_fields && representation.IsDouble()) {
    3710             :     DCHECK(access.IsInobject());
    3711             :     DCHECK(!hinstr->has_transition());
    3712             :     DCHECK(!hinstr->NeedsWriteBarrier());
    3713             :     XMMRegister value = ToDoubleRegister(instr->value());
    3714             :     __ Movsd(FieldOperand(object, offset), value);
    3715             :     return;
    3716             :   }
    3717             : 
    3718      174793 :   if (hinstr->has_transition()) {
    3719        9257 :     Handle<Map> transition = hinstr->transition_map();
    3720        9257 :     AddDeprecationDependency(transition);
    3721        9257 :     if (!hinstr->NeedsWriteBarrierForMap()) {
    3722        2098 :       __ Move(FieldOperand(object, HeapObject::kMapOffset), transition);
    3723             :     } else {
    3724        8208 :       Register temp = ToRegister(instr->temp());
    3725        8208 :       __ Move(kScratchRegister, transition);
    3726        8208 :       __ movp(FieldOperand(object, HeapObject::kMapOffset), kScratchRegister);
    3727             :       // Update the write barrier for the map field.
    3728             :       __ RecordWriteForMap(object,
    3729             :                            kScratchRegister,
    3730             :                            temp,
    3731        8208 :                            kSaveFPRegs);
    3732             :     }
    3733             :   }
    3734             : 
    3735             :   // Do the store.
    3736             :   Register write_register = object;
    3737      174793 :   if (!access.IsInobject()) {
    3738             :     write_register = ToRegister(instr->temp());
    3739         639 :     __ movp(write_register, FieldOperand(object, JSObject::kPropertiesOffset));
    3740             :   }
    3741             : 
    3742      215823 :   if (representation.IsSmi() && SmiValuesAre32Bits() &&
    3743             :       hinstr->value()->representation().IsInteger32()) {
    3744             :     DCHECK(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY);
    3745        1355 :     if (FLAG_debug_code) {
    3746           0 :       Register scratch = kScratchRegister;
    3747           0 :       __ Load(scratch, FieldOperand(write_register, offset), representation);
    3748           0 :       __ AssertSmi(scratch);
    3749             :     }
    3750             :     // Store int value directly to upper half of the smi.
    3751             :     STATIC_ASSERT(kSmiTag == 0);
    3752             :     DCHECK(kSmiTagSize + kSmiShiftSize == 32);
    3753        1355 :     offset += kPointerSize / 2;
    3754             :     representation = Representation::Integer32();
    3755             :   }
    3756             : 
    3757      174793 :   Operand operand = FieldOperand(write_register, offset);
    3758             : 
    3759      174793 :   if (FLAG_unbox_double_fields && representation.IsDouble()) {
    3760             :     DCHECK(access.IsInobject());
    3761         262 :     XMMRegister value = ToDoubleRegister(instr->value());
    3762         262 :     __ Movsd(operand, value);
    3763             : 
    3764      174531 :   } else if (instr->value()->IsRegister()) {
    3765       74829 :     Register value = ToRegister(instr->value());
    3766       74829 :     __ Store(operand, value, representation);
    3767             :   } else {
    3768             :     LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
    3769       99702 :     if (IsInteger32Constant(operand_value)) {
    3770             :       DCHECK(!hinstr->NeedsWriteBarrier());
    3771             :       int32_t value = ToInteger32(operand_value);
    3772       23549 :       if (representation.IsSmi()) {
    3773       10295 :         __ Move(operand, Smi::FromInt(value));
    3774             : 
    3775             :       } else {
    3776       13254 :         __ movl(operand, Immediate(value));
    3777             :       }
    3778             : 
    3779       76153 :     } else if (IsExternalConstant(operand_value)) {
    3780             :       DCHECK(!hinstr->NeedsWriteBarrier());
    3781             :       ExternalReference ptr = ToExternalReference(operand_value);
    3782             :       __ Move(kScratchRegister, ptr);
    3783           0 :       __ movp(operand, kScratchRegister);
    3784             :     } else {
    3785       76153 :       Handle<Object> handle_value = ToHandle(operand_value);
    3786             :       DCHECK(!hinstr->NeedsWriteBarrier());
    3787       76153 :       __ Move(operand, handle_value);
    3788             :     }
    3789             :   }
    3790             : 
    3791      174793 :   if (hinstr->NeedsWriteBarrier()) {
    3792       13976 :     Register value = ToRegister(instr->value());
    3793       27608 :     Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object;
    3794             :     // Update the write barrier for the object for in-object properties.
    3795             :     __ RecordWriteField(write_register,
    3796             :                         offset,
    3797             :                         value,
    3798             :                         temp,
    3799             :                         kSaveFPRegs,
    3800             :                         EMIT_REMEMBERED_SET,
    3801             :                         hinstr->SmiCheckForWriteBarrier(),
    3802       13976 :                         hinstr->PointersToHereCheckForValue());
    3803             :   }
    3804             : }
    3805             : 
    3806             : 
    3807       30985 : void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
    3808             :   Representation representation = instr->hydrogen()->length()->representation();
    3809             :   DCHECK(representation.Equals(instr->hydrogen()->index()->representation()));
    3810             :   DCHECK(representation.IsSmiOrInteger32());
    3811             : 
    3812       30985 :   Condition cc = instr->hydrogen()->allow_equality() ? below : below_equal;
    3813       30985 :   if (instr->length()->IsConstantOperand()) {
    3814             :     int32_t length = ToInteger32(LConstantOperand::cast(instr->length()));
    3815        6357 :     Register index = ToRegister(instr->index());
    3816        6357 :     if (representation.IsSmi()) {
    3817       30985 :       __ Cmp(index, Smi::FromInt(length));
    3818             :     } else {
    3819        6357 :       __ cmpl(index, Immediate(length));
    3820             :     }
    3821        6357 :     cc = CommuteCondition(cc);
    3822       24628 :   } else if (instr->index()->IsConstantOperand()) {
    3823             :     int32_t index = ToInteger32(LConstantOperand::cast(instr->index()));
    3824        4378 :     if (instr->length()->IsRegister()) {
    3825        4351 :       Register length = ToRegister(instr->length());
    3826        4351 :       if (representation.IsSmi()) {
    3827           0 :         __ Cmp(length, Smi::FromInt(index));
    3828             :       } else {
    3829        4351 :         __ cmpl(length, Immediate(index));
    3830             :       }
    3831             :     } else {
    3832          27 :       Operand length = ToOperand(instr->length());
    3833          27 :       if (representation.IsSmi()) {
    3834           0 :         __ Cmp(length, Smi::FromInt(index));
    3835             :       } else {
    3836          27 :         __ cmpl(length, Immediate(index));
    3837             :       }
    3838             :     }
    3839             :   } else {
    3840             :     Register index = ToRegister(instr->index());
    3841       20250 :     if (instr->length()->IsRegister()) {
    3842       20150 :       Register length = ToRegister(instr->length());
    3843       20150 :       if (representation.IsSmi()) {
    3844           0 :         __ cmpp(length, index);
    3845             :       } else {
    3846       20150 :         __ cmpl(length, index);
    3847             :       }
    3848             :     } else {
    3849         100 :       Operand length = ToOperand(instr->length());
    3850         100 :       if (representation.IsSmi()) {
    3851           0 :         __ cmpp(length, index);
    3852             :       } else {
    3853         100 :         __ cmpl(length, index);
    3854             :       }
    3855             :     }
    3856             :   }
    3857       30996 :   if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
    3858             :     Label done;
    3859           0 :     __ j(NegateCondition(cc), &done, Label::kNear);
    3860           0 :     __ int3();
    3861           0 :     __ bind(&done);
    3862             :   } else {
    3863             :     DeoptimizeIf(cc, instr, DeoptimizeReason::kOutOfBounds);
    3864             :   }
    3865       30985 : }
    3866             : 
    3867             : 
    3868        1792 : void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
    3869             :   ElementsKind elements_kind = instr->elements_kind();
    3870             :   LOperand* key = instr->key();
    3871             :   if (kPointerSize == kInt32Size && !key->IsConstantOperand()) {
    3872             :     Register key_reg = ToRegister(key);
    3873             :     Representation key_representation =
    3874             :         instr->hydrogen()->key()->representation();
    3875             :     if (ExternalArrayOpRequiresTemp(key_representation, elements_kind)) {
    3876        2077 :       __ SmiToInteger64(key_reg, key_reg);
    3877             :     } else if (instr->hydrogen()->IsDehoisted()) {
    3878             :       // Sign extend key because it could be a 32 bit negative value
    3879             :       // and the dehoisted address computation happens in 64 bits
    3880             :       __ movsxlq(key_reg, key_reg);
    3881             :     }
    3882             :   }
    3883             :   Operand operand(BuildFastArrayOperand(
    3884             :       instr->elements(),
    3885             :       key,
    3886             :       instr->hydrogen()->key()->representation(),
    3887             :       elements_kind,
    3888        1792 :       instr->base_offset()));
    3889             : 
    3890        1792 :   if (elements_kind == FLOAT32_ELEMENTS) {
    3891         285 :     XMMRegister value(ToDoubleRegister(instr->value()));
    3892         285 :     __ Cvtsd2ss(value, value);
    3893         285 :     __ Movss(operand, value);
    3894        1507 :   } else if (elements_kind == FLOAT64_ELEMENTS) {
    3895         142 :     __ Movsd(operand, ToDoubleRegister(instr->value()));
    3896             :   } else {
    3897             :     Register value(ToRegister(instr->value()));
    3898        1365 :     switch (elements_kind) {
    3899             :       case INT8_ELEMENTS:
    3900             :       case UINT8_ELEMENTS:
    3901             :       case UINT8_CLAMPED_ELEMENTS:
    3902         715 :         __ movb(operand, value);
    3903         715 :         break;
    3904             :       case INT16_ELEMENTS:
    3905             :       case UINT16_ELEMENTS:
    3906         224 :         __ movw(operand, value);
    3907         224 :         break;
    3908             :       case INT32_ELEMENTS:
    3909             :       case UINT32_ELEMENTS:
    3910         426 :         __ movl(operand, value);
    3911             :         break;
    3912             :       case FLOAT32_ELEMENTS:
    3913             :       case FLOAT64_ELEMENTS:
    3914             :       case FAST_ELEMENTS:
    3915             :       case FAST_SMI_ELEMENTS:
    3916             :       case FAST_DOUBLE_ELEMENTS:
    3917             :       case FAST_HOLEY_ELEMENTS:
    3918             :       case FAST_HOLEY_SMI_ELEMENTS:
    3919             :       case FAST_HOLEY_DOUBLE_ELEMENTS:
    3920             :       case DICTIONARY_ELEMENTS:
    3921             :       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
    3922             :       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
    3923             :       case FAST_STRING_WRAPPER_ELEMENTS:
    3924             :       case SLOW_STRING_WRAPPER_ELEMENTS:
    3925             :       case NO_ELEMENTS:
    3926           0 :         UNREACHABLE();
    3927             :         break;
    3928             :     }
    3929             :   }
    3930        1792 : }
    3931             : 
    3932             : 
    3933        6672 : void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
    3934        6672 :   XMMRegister value = ToDoubleRegister(instr->value());
    3935             :   LOperand* key = instr->key();
    3936             :   if (kPointerSize == kInt32Size && !key->IsConstantOperand() &&
    3937             :       instr->hydrogen()->IsDehoisted()) {
    3938             :     // Sign extend key because it could be a 32 bit negative value
    3939             :     // and the dehoisted address computation happens in 64 bits
    3940        7070 :     __ movsxlq(ToRegister(key), ToRegister(key));
    3941             :   }
    3942        6672 :   if (instr->NeedsCanonicalization()) {
    3943         199 :     XMMRegister xmm_scratch = double_scratch0();
    3944             :     // Turn potential sNaN value into qNaN.
    3945         199 :     __ Xorpd(xmm_scratch, xmm_scratch);
    3946         199 :     __ Subsd(value, xmm_scratch);
    3947             :   }
    3948             : 
    3949             :   Operand double_store_operand = BuildFastArrayOperand(
    3950             :       instr->elements(),
    3951             :       key,
    3952             :       instr->hydrogen()->key()->representation(),
    3953             :       FAST_DOUBLE_ELEMENTS,
    3954        6672 :       instr->base_offset());
    3955             : 
    3956        6672 :   __ Movsd(double_store_operand, value);
    3957        6672 : }
    3958             : 
    3959             : 
    3960       20093 : void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
    3961             :   HStoreKeyed* hinstr = instr->hydrogen();
    3962             :   LOperand* key = instr->key();
    3963       20093 :   int offset = instr->base_offset();
    3964             :   Representation representation = hinstr->value()->representation();
    3965             : 
    3966             :   if (kPointerSize == kInt32Size && !key->IsConstantOperand() &&
    3967             :       instr->hydrogen()->IsDehoisted()) {
    3968             :     // Sign extend key because it could be a 32 bit negative value
    3969             :     // and the dehoisted address computation happens in 64 bits
    3970       33177 :     __ movsxlq(ToRegister(key), ToRegister(key));
    3971             :   }
    3972       20093 :   if (representation.IsInteger32() && SmiValuesAre32Bits()) {
    3973             :     DCHECK(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY);
    3974             :     DCHECK(hinstr->elements_kind() == FAST_SMI_ELEMENTS);
    3975        1496 :     if (FLAG_debug_code) {
    3976           0 :       Register scratch = kScratchRegister;
    3977             :       __ Load(scratch,
    3978             :               BuildFastArrayOperand(instr->elements(),
    3979             :                                     key,
    3980             :                                     instr->hydrogen()->key()->representation(),
    3981             :                                     FAST_ELEMENTS,
    3982             :                                     offset),
    3983           0 :               Representation::Smi());
    3984           0 :       __ AssertSmi(scratch);
    3985             :     }
    3986             :     // Store int value directly to upper half of the smi.
    3987             :     STATIC_ASSERT(kSmiTag == 0);
    3988             :     DCHECK(kSmiTagSize + kSmiShiftSize == 32);
    3989        1496 :     offset += kPointerSize / 2;
    3990             :   }
    3991             : 
    3992             :   Operand operand =
    3993             :       BuildFastArrayOperand(instr->elements(),
    3994             :                             key,
    3995             :                             instr->hydrogen()->key()->representation(),
    3996             :                             FAST_ELEMENTS,
    3997       40186 :                             offset);
    3998       20093 :   if (instr->value()->IsRegister()) {
    3999       17573 :     __ Store(operand, ToRegister(instr->value()), representation);
    4000             :   } else {
    4001             :     LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
    4002        2520 :     if (IsInteger32Constant(operand_value)) {
    4003             :       int32_t value = ToInteger32(operand_value);
    4004        1277 :       if (representation.IsSmi()) {
    4005         660 :         __ Move(operand, Smi::FromInt(value));
    4006             : 
    4007             :       } else {
    4008         617 :         __ movl(operand, Immediate(value));
    4009             :       }
    4010             :     } else {
    4011        1243 :       Handle<Object> handle_value = ToHandle(operand_value);
    4012        1243 :       __ Move(operand, handle_value);
    4013             :     }
    4014             :   }
    4015             : 
    4016       20093 :   if (hinstr->NeedsWriteBarrier()) {
    4017        6542 :     Register elements = ToRegister(instr->elements());
    4018             :     DCHECK(instr->value()->IsRegister());
    4019        6542 :     Register value = ToRegister(instr->value());
    4020             :     DCHECK(!key->IsConstantOperand());
    4021             :     SmiCheck check_needed = hinstr->value()->type().IsHeapObject()
    4022        6542 :             ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
    4023             :     // Compute address of modified element and store it into key register.
    4024             :     Register key_reg(ToRegister(key));
    4025        6542 :     __ leap(key_reg, operand);
    4026             :     __ RecordWrite(elements,
    4027             :                    key_reg,
    4028             :                    value,
    4029             :                    kSaveFPRegs,
    4030             :                    EMIT_REMEMBERED_SET,
    4031             :                    check_needed,
    4032        6542 :                    hinstr->PointersToHereCheckForValue());
    4033             :   }
    4034       20093 : }
    4035             : 
    4036             : 
    4037       28557 : void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
    4038       28557 :   if (instr->is_fixed_typed_array()) {
    4039        1792 :     DoStoreKeyedExternalArray(instr);
    4040       26765 :   } else if (instr->hydrogen()->value()->representation().IsDouble()) {
    4041        6672 :     DoStoreKeyedFixedDoubleArray(instr);
    4042             :   } else {
    4043       20093 :     DoStoreKeyedFixedArray(instr);
    4044             :   }
    4045       28557 : }
    4046             : 
    4047             : 
    4048        2532 : void LCodeGen::DoMaybeGrowElements(LMaybeGrowElements* instr) {
    4049           0 :   class DeferredMaybeGrowElements final : public LDeferredCode {
    4050             :    public:
    4051             :     DeferredMaybeGrowElements(LCodeGen* codegen, LMaybeGrowElements* instr)
    4052        2532 :         : LDeferredCode(codegen), instr_(instr) {}
    4053        2528 :     void Generate() override { codegen()->DoDeferredMaybeGrowElements(instr_); }
    4054        5056 :     LInstruction* instr() override { return instr_; }
    4055             : 
    4056             :    private:
    4057             :     LMaybeGrowElements* instr_;
    4058             :   };
    4059             : 
    4060             :   Register result = rax;
    4061             :   DeferredMaybeGrowElements* deferred =
    4062       12660 :       new (zone()) DeferredMaybeGrowElements(this, instr);
    4063             :   LOperand* key = instr->key();
    4064             :   LOperand* current_capacity = instr->current_capacity();
    4065             : 
    4066             :   DCHECK(instr->hydrogen()->key()->representation().IsInteger32());
    4067             :   DCHECK(instr->hydrogen()->current_capacity()->representation().IsInteger32());
    4068             :   DCHECK(key->IsConstantOperand() || key->IsRegister());
    4069             :   DCHECK(current_capacity->IsConstantOperand() ||
    4070             :          current_capacity->IsRegister());
    4071             : 
    4072        2626 :   if (key->IsConstantOperand() && current_capacity->IsConstantOperand()) {
    4073             :     int32_t constant_key = ToInteger32(LConstantOperand::cast(key));
    4074             :     int32_t constant_capacity =
    4075             :         ToInteger32(LConstantOperand::cast(current_capacity));
    4076           0 :     if (constant_key >= constant_capacity) {
    4077             :       // Deferred case.
    4078           0 :       __ jmp(deferred->entry());
    4079             :     }
    4080        2532 :   } else if (key->IsConstantOperand()) {
    4081             :     int32_t constant_key = ToInteger32(LConstantOperand::cast(key));
    4082          94 :     __ cmpl(ToRegister(current_capacity), Immediate(constant_key));
    4083         188 :     __ j(less_equal, deferred->entry());
    4084        2438 :   } else if (current_capacity->IsConstantOperand()) {
    4085             :     int32_t constant_capacity =
    4086             :         ToInteger32(LConstantOperand::cast(current_capacity));
    4087           0 :     __ cmpl(ToRegister(key), Immediate(constant_capacity));
    4088           0 :     __ j(greater_equal, deferred->entry());
    4089             :   } else {
    4090        2438 :     __ cmpl(ToRegister(key), ToRegister(current_capacity));
    4091        4876 :     __ j(greater_equal, deferred->entry());
    4092             :   }
    4093             : 
    4094        2532 :   if (instr->elements()->IsRegister()) {
    4095        2527 :     __ movp(result, ToRegister(instr->elements()));
    4096             :   } else {
    4097          10 :     __ movp(result, ToOperand(instr->elements()));
    4098             :   }
    4099             : 
    4100        2532 :   __ bind(deferred->exit());
    4101        2532 : }
    4102             : 
    4103             : 
    4104        2528 : void LCodeGen::DoDeferredMaybeGrowElements(LMaybeGrowElements* instr) {
    4105             :   // TODO(3095996): Get rid of this. For now, we need to make the
    4106             :   // result register contain a valid pointer because it is already
    4107             :   // contained in the register pointer map.
    4108             :   Register result = rax;
    4109       17606 :   __ Move(result, Smi::kZero);
    4110             : 
    4111             :   // We have to call a stub.
    4112             :   {
    4113             :     PushSafepointRegistersScope scope(this);
    4114        2528 :     if (instr->object()->IsConstantOperand()) {
    4115             :       LConstantOperand* constant_object =
    4116             :           LConstantOperand::cast(instr->object());
    4117           0 :       if (IsSmiConstant(constant_object)) {
    4118             :         Smi* immediate = ToSmi(constant_object);
    4119             :         __ Move(result, immediate);
    4120             :       } else {
    4121           0 :         Handle<Object> handle_value = ToHandle(constant_object);
    4122           0 :         __ Move(result, handle_value);
    4123             :       }
    4124        2528 :     } else if (instr->object()->IsRegister()) {
    4125        2528 :       __ Move(result, ToRegister(instr->object()));
    4126             :     } else {
    4127           0 :       __ movp(result, ToOperand(instr->object()));
    4128             :     }
    4129             : 
    4130             :     LOperand* key = instr->key();
    4131        2528 :     if (key->IsConstantOperand()) {
    4132             :       __ Move(rbx, ToSmi(LConstantOperand::cast(key)));
    4133             :     } else {
    4134        2438 :       __ Move(rbx, ToRegister(key));
    4135        2438 :       __ Integer32ToSmi(rbx, rbx);
    4136             :     }
    4137             : 
    4138        2528 :     GrowArrayElementsStub stub(isolate(), instr->hydrogen()->kind());
    4139        2528 :     __ CallStub(&stub);
    4140        2528 :     RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0);
    4141        2528 :     __ StoreToSafepointRegisterSlot(result, result);
    4142             :   }
    4143             : 
    4144             :   // Deopt on smi, which means the elements array changed to dictionary mode.
    4145        2528 :   Condition is_smi = __ CheckSmi(result);
    4146             :   DeoptimizeIf(is_smi, instr, DeoptimizeReason::kSmi);
    4147        2528 : }
    4148             : 
    4149             : 
    4150         755 : void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
    4151             :   Register object_reg = ToRegister(instr->object());
    4152             : 
    4153             :   Handle<Map> from_map = instr->original_map();
    4154             :   Handle<Map> to_map = instr->transitioned_map();
    4155             :   ElementsKind from_kind = instr->from_kind();
    4156             :   ElementsKind to_kind = instr->to_kind();
    4157             : 
    4158             :   Label not_applicable;
    4159        3370 :   __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
    4160         755 :   __ j(not_equal, &not_applicable);
    4161         755 :   if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
    4162             :     Register new_map_reg = ToRegister(instr->new_map_temp());
    4163             :     __ Move(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT);
    4164         350 :     __ movp(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg);
    4165             :     // Write barrier.
    4166             :     __ RecordWriteForMap(object_reg, new_map_reg, ToRegister(instr->temp()),
    4167         350 :                          kDontSaveFPRegs);
    4168             :   } else {
    4169             :     DCHECK(object_reg.is(rax));
    4170             :     DCHECK(ToRegister(instr->context()).is(rsi));
    4171             :     PushSafepointRegistersScope scope(this);
    4172         405 :     __ Move(rbx, to_map);
    4173         405 :     TransitionElementsKindStub stub(isolate(), from_kind, to_kind);
    4174         405 :     __ CallStub(&stub);
    4175         405 :     RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0);
    4176             :   }
    4177         755 :   __ bind(&not_applicable);
    4178         755 : }
    4179             : 
    4180             : 
    4181          38 : void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
    4182          38 :   Register object = ToRegister(instr->object());
    4183          38 :   Register temp = ToRegister(instr->temp());
    4184             :   Label no_memento_found;
    4185          76 :   __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
    4186             :   DeoptimizeIf(equal, instr, DeoptimizeReason::kMementoFound);
    4187          38 :   __ bind(&no_memento_found);
    4188          38 : }
    4189             : 
    4190             : 
    4191       21084 : void LCodeGen::DoStringAdd(LStringAdd* instr) {
    4192             :   DCHECK(ToRegister(instr->context()).is(rsi));
    4193             :   DCHECK(ToRegister(instr->left()).is(rdx));
    4194             :   DCHECK(ToRegister(instr->right()).is(rax));
    4195             :   StringAddStub stub(isolate(),
    4196             :                      instr->hydrogen()->flags(),
    4197       21084 :                      instr->hydrogen()->pretenure_flag());
    4198       21084 :   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
    4199       21084 : }
    4200             : 
    4201             : 
    4202         367 : void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
    4203           0 :   class DeferredStringCharCodeAt final : public LDeferredCode {
    4204             :    public:
    4205             :     DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
    4206         367 :         : LDeferredCode(codegen), instr_(instr) { }
    4207         367 :     void Generate() override { codegen()->DoDeferredStringCharCodeAt(instr_); }
    4208         734 :     LInstruction* instr() override { return instr_; }
    4209             : 
    4210             :    private:
    4211             :     LStringCharCodeAt* instr_;
    4212             :   };
    4213             : 
    4214             :   DeferredStringCharCodeAt* deferred =
    4215        1101 :       new(zone()) DeferredStringCharCodeAt(this, instr);
    4216             : 
    4217             :   StringCharLoadGenerator::Generate(masm(),
    4218             :                                     ToRegister(instr->string()),
    4219             :                                     ToRegister(instr->index()),
    4220         367 :                                     ToRegister(instr->result()),
    4221        1101 :                                     deferred->entry());
    4222         367 :   __ bind(deferred->exit());
    4223         367 : }
    4224             : 
    4225             : 
    4226         367 : void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
    4227         367 :   Register string = ToRegister(instr->string());
    4228         734 :   Register result = ToRegister(instr->result());
    4229             : 
    4230             :   // TODO(3095996): Get rid of this. For now, we need to make the
    4231             :   // result register contain a valid pointer because it is already
    4232             :   // contained in the register pointer map.
    4233        2569 :   __ Set(result, 0);
    4234             : 
    4235             :   PushSafepointRegistersScope scope(this);
    4236         367 :   __ Push(string);
    4237             :   // Push the index as a smi. This is safe because of the checks in
    4238             :   // DoStringCharCodeAt above.
    4239             :   STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
    4240         367 :   if (instr->index()->IsConstantOperand()) {
    4241             :     int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index()));
    4242           0 :     __ Push(Smi::FromInt(const_index));
    4243             :   } else {
    4244         367 :     Register index = ToRegister(instr->index());
    4245         367 :     __ Integer32ToSmi(index, index);
    4246         367 :     __ Push(index);
    4247             :   }
    4248             :   CallRuntimeFromDeferred(
    4249         367 :       Runtime::kStringCharCodeAtRT, 2, instr, instr->context());
    4250         367 :   __ AssertSmi(rax);
    4251         367 :   __ SmiToInteger32(rax, rax);
    4252         367 :   __ StoreToSafepointRegisterSlot(result, rax);
    4253         367 : }
    4254             : 
    4255             : 
    4256         458 : void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
    4257           0 :   class DeferredStringCharFromCode final : public LDeferredCode {
    4258             :    public:
    4259             :     DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
    4260         458 :         : LDeferredCode(codegen), instr_(instr) { }
    4261         458 :     void Generate() override {
    4262         458 :       codegen()->DoDeferredStringCharFromCode(instr_);
    4263         458 :     }
    4264         916 :     LInstruction* instr() override { return instr_; }
    4265             : 
    4266             :    private:
    4267             :     LStringCharFromCode* instr_;
    4268             :   };
    4269             : 
    4270             :   DeferredStringCharFromCode* deferred =
    4271        4122 :       new(zone()) DeferredStringCharFromCode(this, instr);
    4272             : 
    4273             :   DCHECK(instr->hydrogen()->value()->representation().IsInteger32());
    4274             :   Register char_code = ToRegister(instr->char_code());
    4275         458 :   Register result = ToRegister(instr->result());
    4276             :   DCHECK(!char_code.is(result));
    4277             : 
    4278         458 :   __ cmpl(char_code, Immediate(String::kMaxOneByteCharCode));
    4279         916 :   __ j(above, deferred->entry());
    4280         458 :   __ movsxlq(char_code, char_code);
    4281         458 :   __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
    4282             :   __ movp(result, FieldOperand(result,
    4283             :                                char_code, times_pointer_size,
    4284         458 :                                FixedArray::kHeaderSize));
    4285         458 :   __ CompareRoot(result, Heap::kUndefinedValueRootIndex);
    4286         458 :   __ j(equal, deferred->entry());
    4287         458 :   __ bind(deferred->exit());
    4288         458 : }
    4289             : 
    4290             : 
    4291         458 : void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
    4292         458 :   Register char_code = ToRegister(instr->char_code());
    4293         916 :   Register result = ToRegister(instr->result());
    4294             : 
    4295             :   // TODO(3095996): Get rid of this. For now, we need to make the
    4296             :   // result register contain a valid pointer because it is already
    4297             :   // contained in the register pointer map.
    4298        1832 :   __ Set(result, 0);
    4299             : 
    4300             :   PushSafepointRegistersScope scope(this);
    4301         458 :   __ Integer32ToSmi(char_code, char_code);
    4302         458 :   __ Push(char_code);
    4303             :   CallRuntimeFromDeferred(Runtime::kStringCharFromCode, 1, instr,
    4304         458 :                           instr->context());
    4305         458 :   __ StoreToSafepointRegisterSlot(result, rax);
    4306         458 : }
    4307             : 
    4308             : 
    4309       22385 : void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
    4310             :   LOperand* input = instr->value();
    4311             :   DCHECK(input->IsRegister() || input->IsStackSlot());
    4312       22385 :   LOperand* output = instr->result();
    4313             :   DCHECK(output->IsDoubleRegister());
    4314       22385 :   if (input->IsRegister()) {
    4315       22385 :     __ Cvtlsi2sd(ToDoubleRegister(output), ToRegister(input));
    4316             :   } else {
    4317        8750 :     __ Cvtlsi2sd(ToDoubleRegister(output), ToOperand(input));
    4318             :   }
    4319       22385 : }
    4320             : 
    4321             : 
    4322         650 : void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
    4323             :   LOperand* input = instr->value();
    4324         650 :   LOperand* output = instr->result();
    4325             : 
    4326         650 :   __ LoadUint32(ToDoubleRegister(output), ToRegister(input));
    4327         650 : }
    4328             : 
    4329             : 
    4330           0 : void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
    4331           0 :   class DeferredNumberTagI final : public LDeferredCode {
    4332             :    public:
    4333             :     DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr)
    4334             :         : LDeferredCode(codegen), instr_(instr) { }
    4335           0 :     void Generate() override {
    4336             :       codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(),
    4337           0 :                                        instr_->temp2(), SIGNED_INT32);
    4338           0 :     }
    4339           0 :     LInstruction* instr() override { return instr_; }
    4340             : 
    4341             :    private:
    4342             :     LNumberTagI* instr_;
    4343             :   };
    4344             : 
    4345             :   LOperand* input = instr->value();
    4346             :   DCHECK(input->IsRegister() && input->Equals(instr->result()));
    4347           0 :   Register reg = ToRegister(input);
    4348             : 
    4349             :   if (SmiValuesAre32Bits()) {
    4350           0 :     __ Integer32ToSmi(reg, reg);
    4351             :   } else {
    4352             :     DCHECK(SmiValuesAre31Bits());
    4353             :     DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr);
    4354             :     __ Integer32ToSmi(reg, reg);
    4355             :     __ j(overflow, deferred->entry());
    4356             :     __ bind(deferred->exit());
    4357             :   }
    4358           0 : }
    4359             : 
    4360             : 
    4361         778 : void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
    4362           0 :   class DeferredNumberTagU final : public LDeferredCode {
    4363             :    public:
    4364             :     DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr)
    4365         778 :         : LDeferredCode(codegen), instr_(instr) { }
    4366         778 :     void Generate() override {
    4367             :       codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(),
    4368        1556 :                                        instr_->temp2(), UNSIGNED_INT32);
    4369         778 :     }
    4370        1556 :     LInstruction* instr() override { return instr_; }
    4371             : 
    4372             :    private:
    4373             :     LNumberTagU* instr_;
    4374             :   };
    4375             : 
    4376             :   LOperand* input = instr->value();
    4377             :   DCHECK(input->IsRegister() && input->Equals(instr->result()));
    4378         778 :   Register reg = ToRegister(input);
    4379             : 
    4380        3890 :   DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr);
    4381         778 :   __ cmpl(reg, Immediate(Smi::kMaxValue));
    4382        1556 :   __ j(above, deferred->entry());
    4383         778 :   __ Integer32ToSmi(reg, reg);
    4384         778 :   __ bind(deferred->exit());
    4385         778 : }
    4386             : 
    4387             : 
    4388         778 : void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
    4389             :                                      LOperand* value,
    4390             :                                      LOperand* temp1,
    4391             :                                      LOperand* temp2,
    4392             :                                      IntegerSignedness signedness) {
    4393             :   Label done, slow;
    4394             :   Register reg = ToRegister(value);
    4395         778 :   Register tmp = ToRegister(temp1);
    4396         778 :   XMMRegister temp_xmm = ToDoubleRegister(temp2);
    4397             : 
    4398             :   // Load value into temp_xmm which will be preserved across potential call to
    4399             :   // runtime (MacroAssembler::EnterExitFrameEpilogue preserves only allocatable
    4400             :   // XMM registers on x64).
    4401         778 :   if (signedness == SIGNED_INT32) {
    4402             :     DCHECK(SmiValuesAre31Bits());
    4403             :     // There was overflow, so bits 30 and 31 of the original integer
    4404             :     // disagree. Try to allocate a heap number in new space and store
    4405             :     // the value in there. If that fails, call the runtime system.
    4406        7774 :     __ SmiToInteger32(reg, reg);
    4407           0 :     __ xorl(reg, Immediate(0x80000000));
    4408           0 :     __ Cvtlsi2sd(temp_xmm, reg);
    4409             :   } else {
    4410             :     DCHECK(signedness == UNSIGNED_INT32);
    4411         778 :     __ LoadUint32(temp_xmm, reg);
    4412             :   }
    4413             : 
    4414         778 :   if (FLAG_inline_new) {
    4415         775 :     __ AllocateHeapNumber(reg, tmp, &slow);
    4416         775 :     __ jmp(&done, kPointerSize == kInt64Size ? Label::kNear : Label::kFar);
    4417             :   }
    4418             : 
    4419             :   // Slow case: Call the runtime system to do the number allocation.
    4420         778 :   __ bind(&slow);
    4421             :   {
    4422             :     // Put a valid pointer value in the stack slot where the result
    4423             :     // register is stored, as this register is in the pointer map, but contains
    4424             :     // an integer value.
    4425         778 :     __ Set(reg, 0);
    4426             : 
    4427             :     // Preserve the value of all registers.
    4428             :     PushSafepointRegistersScope scope(this);
    4429             :     // Reset the context register.
    4430         778 :     if (!reg.is(rsi)) {
    4431         778 :       __ Set(rsi, 0);
    4432             :     }
    4433         778 :     __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
    4434             :     RecordSafepointWithRegisters(
    4435             :         instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
    4436         778 :     __ StoreToSafepointRegisterSlot(reg, rax);
    4437             :   }
    4438             : 
    4439             :   // Done. Put the value in temp_xmm into the value of the allocated heap
    4440             :   // number.
    4441         778 :   __ bind(&done);
    4442        1556 :   __ Movsd(FieldOperand(reg, HeapNumber::kValueOffset), temp_xmm);
    4443         778 : }
    4444             : 
    4445             : 
    4446       26503 : void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
    4447           0 :   class DeferredNumberTagD final : public LDeferredCode {
    4448             :    public:
    4449             :     DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
    4450       26503 :         : LDeferredCode(codegen), instr_(instr) { }
    4451       26503 :     void Generate() override { codegen()->DoDeferredNumberTagD(instr_); }
    4452       53006 :     LInstruction* instr() override { return instr_; }
    4453             : 
    4454             :    private:
    4455             :     LNumberTagD* instr_;
    4456             :   };
    4457             : 
    4458       26503 :   XMMRegister input_reg = ToDoubleRegister(instr->value());
    4459       26503 :   Register reg = ToRegister(instr->result());
    4460       26503 :   Register tmp = ToRegister(instr->temp());
    4461             : 
    4462      106012 :   DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr);
    4463       26503 :   if (FLAG_inline_new) {
    4464       53006 :     __ AllocateHeapNumber(reg, tmp, deferred->entry());
    4465             :   } else {
    4466           0 :     __ jmp(deferred->entry());
    4467             :   }
    4468       26503 :   __ bind(deferred->exit());
    4469       53006 :   __ Movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg);
    4470       26503 : }
    4471             : 
    4472             : 
    4473       26503 : void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
    4474             :   // TODO(3095996): Get rid of this. For now, we need to make the
    4475             :   // result register contain a valid pointer because it is already
    4476             :   // contained in the register pointer map.
    4477       26503 :   Register reg = ToRegister(instr->result());
    4478      132322 :   __ Move(reg, Smi::kZero);
    4479             : 
    4480             :   {
    4481             :     PushSafepointRegistersScope scope(this);
    4482             :     // Reset the context register.
    4483       26503 :     if (!reg.is(rsi)) {
    4484             :       __ Move(rsi, 0);
    4485             :     }
    4486       26503 :     __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
    4487             :     RecordSafepointWithRegisters(
    4488             :         instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
    4489       26503 :     __ movp(kScratchRegister, rax);
    4490             :   }
    4491       26503 :   __ movp(reg, kScratchRegister);
    4492       26503 : }
    4493             : 
    4494             : 
    4495      123018 : void LCodeGen::DoSmiTag(LSmiTag* instr) {
    4496             :   HChange* hchange = instr->hydrogen();
    4497      123018 :   Register input = ToRegister(instr->value());
    4498      246036 :   Register output = ToRegister(instr->result());
    4499      369270 :   if (hchange->CheckFlag(HValue::kCanOverflow) &&
    4500         216 :       hchange->value()->CheckFlag(HValue::kUint32)) {
    4501      123234 :     Condition is_smi = __ CheckUInteger32ValidSmiValue(input);
    4502             :     DeoptimizeIf(NegateCondition(is_smi), instr, DeoptimizeReason::kOverflow);
    4503             :   }
    4504      123018 :   __ Integer32ToSmi(output, input);
    4505      123234 :   if (hchange->CheckFlag(HValue::kCanOverflow) &&
    4506         216 :       !hchange->value()->CheckFlag(HValue::kUint32)) {
    4507             :     DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
    4508             :   }
    4509      123018 : }
    4510             : 
    4511             : 
    4512        8860 : void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
    4513             :   DCHECK(instr->value()->Equals(instr->result()));
    4514        4430 :   Register input = ToRegister(instr->value());
    4515        4430 :   if (instr->needs_check()) {
    4516        8860 :     Condition is_smi = __ CheckSmi(input);
    4517             :     DeoptimizeIf(NegateCondition(is_smi), instr, DeoptimizeReason::kNotASmi);
    4518             :   } else {
    4519        4430 :     __ AssertSmi(input);
    4520             :   }
    4521        4430 :   __ SmiToInteger32(input, input);
    4522        4430 : }
    4523             : 
    4524             : 
    4525       52912 : void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
    4526             :                                 XMMRegister result_reg, NumberUntagDMode mode) {
    4527             :   bool can_convert_undefined_to_nan = instr->truncating();
    4528             :   bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
    4529             : 
    4530             :   Label convert, load_smi, done;
    4531             : 
    4532       52912 :   if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
    4533             :     // Smi check.
    4534      694300 :     __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
    4535             : 
    4536             :     // Heap number map check.
    4537             :     __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
    4538      101550 :                    Heap::kHeapNumberMapRootIndex);
    4539             : 
    4540             :     // On x64 it is safe to load at heap number offset before evaluating the map
    4541             :     // check, since all heap objects are at least two words long.
    4542      101550 :     __ Movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
    4543             : 
    4544       50775 :     if (can_convert_undefined_to_nan) {
    4545       46592 :       __ j(not_equal, &convert, Label::kNear);
    4546             :     } else {
    4547             :       DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumber);
    4548             :     }
    4549             : 
    4550       50775 :     if (deoptimize_on_minus_zero) {
    4551           0 :       XMMRegister xmm_scratch = double_scratch0();
    4552           0 :       __ Xorpd(xmm_scratch, xmm_scratch);
    4553           0 :       __ Ucomisd(xmm_scratch, result_reg);
    4554           0 :       __ j(not_equal, &done, Label::kNear);
    4555           0 :       __ Movmskpd(kScratchRegister, result_reg);
    4556           0 :       __ testl(kScratchRegister, Immediate(1));
    4557             :       DeoptimizeIf(not_zero, instr, DeoptimizeReason::kMinusZero);
    4558             :     }
    4559       50775 :     __ jmp(&done, Label::kNear);
    4560             : 
    4561       50775 :     if (can_convert_undefined_to_nan) {
    4562       46592 :       __ bind(&convert);
    4563             : 
    4564             :       // Convert undefined (and hole) to NaN. Compute NaN as 0/0.
    4565       46592 :       __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
    4566             :       DeoptimizeIf(not_equal, instr,
    4567             :                    DeoptimizeReason::kNotAHeapNumberUndefined);
    4568             : 
    4569       46592 :       __ Xorpd(result_reg, result_reg);
    4570       46592 :       __ Divsd(result_reg, result_reg);
    4571       46592 :       __ jmp(&done, Label::kNear);
    4572             :     }
    4573             :   } else {
    4574             :     DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
    4575             :   }
    4576             : 
    4577             :   // Smi to XMM conversion
    4578       52912 :   __ bind(&load_smi);
    4579       52912 :   __ SmiToInteger32(kScratchRegister, input_reg);
    4580       52912 :   __ Cvtlsi2sd(result_reg, kScratchRegister);
    4581       52912 :   __ bind(&done);
    4582       52912 : }
    4583             : 
    4584             : 
    4585       69650 : void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
    4586             :   Register input_reg = ToRegister(instr->value());
    4587             : 
    4588       69650 :   if (instr->truncating()) {
    4589             :     Register input_map_reg = kScratchRegister;
    4590             :     Label truncate;
    4591             :     Label::Distance truncate_distance =
    4592       16381 :         DeoptEveryNTimes() ? Label::kFar : Label::kNear;
    4593      375494 :     __ movp(input_map_reg, FieldOperand(input_reg, HeapObject::kMapOffset));
    4594             :     __ JumpIfRoot(input_map_reg, Heap::kHeapNumberMapRootIndex, &truncate,
    4595             :                   truncate_distance);
    4596       16381 :     __ CmpInstanceType(input_map_reg, ODDBALL_TYPE);
    4597             :     DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotANumberOrOddball);
    4598       16381 :     __ bind(&truncate);
    4599       16381 :     __ TruncateHeapNumberToI(input_reg, input_reg);
    4600             :   } else {
    4601       53269 :     XMMRegister scratch = ToDoubleRegister(instr->temp());
    4602             :     DCHECK(!scratch.is(double_scratch0()));
    4603             :     __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
    4604      106538 :                    Heap::kHeapNumberMapRootIndex);
    4605             :     DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumber);
    4606             :     __ Movsd(double_scratch0(),
    4607      106538 :              FieldOperand(input_reg, HeapNumber::kValueOffset));
    4608       53269 :     __ Cvttsd2si(input_reg, double_scratch0());
    4609       53269 :     __ Cvtlsi2sd(scratch, input_reg);
    4610       53269 :     __ Ucomisd(double_scratch0(), scratch);
    4611             :     DeoptimizeIf(not_equal, instr, DeoptimizeReason::kLostPrecision);
    4612             :     DeoptimizeIf(parity_even, instr, DeoptimizeReason::kNaN);
    4613       53269 :     if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
    4614        6811 :       __ testl(input_reg, input_reg);
    4615        6811 :       __ j(not_zero, done);
    4616        6811 :       __ Movmskpd(input_reg, double_scratch0());
    4617        6811 :       __ andl(input_reg, Immediate(1));
    4618             :       DeoptimizeIf(not_zero, instr, DeoptimizeReason::kMinusZero);
    4619             :     }
    4620             :   }
    4621       69650 : }
    4622             : 
    4623             : 
    4624       69651 : void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
    4625           0 :   class DeferredTaggedToI final : public LDeferredCode {
    4626             :    public:
    4627             :     DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
    4628       69651 :         : LDeferredCode(codegen), instr_(instr) { }
    4629      139300 :     void Generate() override { codegen()->DoDeferredTaggedToI(instr_, done()); }
    4630      139300 :     LInstruction* instr() override { return instr_; }
    4631             : 
    4632             :    private:
    4633             :     LTaggedToI* instr_;
    4634             :   };
    4635             : 
    4636             :   LOperand* input = instr->value();
    4637             :   DCHECK(input->IsRegister());
    4638             :   DCHECK(input->Equals(instr->result()));
    4639       69651 :   Register input_reg = ToRegister(input);
    4640             : 
    4641       69651 :   if (instr->hydrogen()->value()->representation().IsSmi()) {
    4642      208953 :     __ SmiToInteger32(input_reg, input_reg);
    4643             :   } else {
    4644             :     DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr);
    4645      139302 :     __ JumpIfNotSmi(input_reg, deferred->entry());
    4646       69651 :     __ SmiToInteger32(input_reg, input_reg);
    4647       69651 :     __ bind(deferred->exit());
    4648             :   }
    4649       69651 : }
    4650             : 
    4651             : 
    4652       52912 : void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
    4653             :   LOperand* input = instr->value();
    4654             :   DCHECK(input->IsRegister());
    4655       52912 :   LOperand* result = instr->result();
    4656             :   DCHECK(result->IsDoubleRegister());
    4657             : 
    4658       52912 :   Register input_reg = ToRegister(input);
    4659       52912 :   XMMRegister result_reg = ToDoubleRegister(result);
    4660             : 
    4661             :   HValue* value = instr->hydrogen()->value();
    4662             :   NumberUntagDMode mode = value->representation().IsSmi()
    4663       52912 :       ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
    4664             : 
    4665       52912 :   EmitNumberUntagD(instr, input_reg, result_reg, mode);
    4666       52912 : }
    4667             : 
    4668             : 
    4669        8825 : void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
    4670             :   LOperand* input = instr->value();
    4671             :   DCHECK(input->IsDoubleRegister());
    4672        8825 :   LOperand* result = instr->result();
    4673             :   DCHECK(result->IsRegister());
    4674             : 
    4675        8825 :   XMMRegister input_reg = ToDoubleRegister(input);
    4676        8825 :   Register result_reg = ToRegister(result);
    4677             : 
    4678        8825 :   if (instr->truncating()) {
    4679       18500 :     __ TruncateDoubleToI(result_reg, input_reg);
    4680             :   } else {
    4681             :     Label lost_precision, is_nan, minus_zero, done;
    4682        1935 :     XMMRegister xmm_scratch = double_scratch0();
    4683        1935 :     Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
    4684             :     __ DoubleToI(result_reg, input_reg, xmm_scratch,
    4685             :                  instr->hydrogen()->GetMinusZeroMode(), &lost_precision,
    4686        1935 :                  &is_nan, &minus_zero, dist);
    4687        1935 :     __ jmp(&done, dist);
    4688        1935 :     __ bind(&lost_precision);
    4689             :     DeoptimizeIf(no_condition, instr, DeoptimizeReason::kLostPrecision);
    4690        1935 :     __ bind(&is_nan);
    4691             :     DeoptimizeIf(no_condition, instr, DeoptimizeReason::kNaN);
    4692        1935 :     __ bind(&minus_zero);
    4693             :     DeoptimizeIf(no_condition, instr, DeoptimizeReason::kMinusZero);
    4694        1935 :     __ bind(&done);
    4695             :   }
    4696        8825 : }
    4697             : 
    4698             : 
    4699          81 : void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
    4700             :   LOperand* input = instr->value();
    4701             :   DCHECK(input->IsDoubleRegister());
    4702          81 :   LOperand* result = instr->result();
    4703             :   DCHECK(result->IsRegister());
    4704             : 
    4705          81 :   XMMRegister input_reg = ToDoubleRegister(input);
    4706          81 :   Register result_reg = ToRegister(result);
    4707             : 
    4708             :   Label lost_precision, is_nan, minus_zero, done;
    4709          81 :   XMMRegister xmm_scratch = double_scratch0();
    4710          81 :   Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
    4711             :   __ DoubleToI(result_reg, input_reg, xmm_scratch,
    4712             :                instr->hydrogen()->GetMinusZeroMode(), &lost_precision, &is_nan,
    4713         486 :                &minus_zero, dist);
    4714          81 :   __ jmp(&done, dist);
    4715          81 :   __ bind(&lost_precision);
    4716             :   DeoptimizeIf(no_condition, instr, DeoptimizeReason::kLostPrecision);
    4717          81 :   __ bind(&is_nan);
    4718             :   DeoptimizeIf(no_condition, instr, DeoptimizeReason::kNaN);
    4719          81 :   __ bind(&minus_zero);
    4720             :   DeoptimizeIf(no_condition, instr, DeoptimizeReason::kMinusZero);
    4721          81 :   __ bind(&done);
    4722          81 :   __ Integer32ToSmi(result_reg, result_reg);
    4723             :   DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
    4724          81 : }
    4725             : 
    4726             : 
    4727       21566 : void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
    4728             :   LOperand* input = instr->value();
    4729       21566 :   Condition cc = masm()->CheckSmi(ToRegister(input));
    4730             :   DeoptimizeIf(NegateCondition(cc), instr, DeoptimizeReason::kNotASmi);
    4731       21566 : }
    4732             : 
    4733             : 
    4734       85810 : void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
    4735       85810 :   if (!instr->hydrogen()->value()->type().IsHeapObject()) {
    4736             :     LOperand* input = instr->value();
    4737       85810 :     Condition cc = masm()->CheckSmi(ToRegister(input));
    4738             :     DeoptimizeIf(cc, instr, DeoptimizeReason::kSmi);
    4739             :   }
    4740       85810 : }
    4741             : 
    4742             : 
    4743        2367 : void LCodeGen::DoCheckArrayBufferNotNeutered(
    4744             :     LCheckArrayBufferNotNeutered* instr) {
    4745             :   Register view = ToRegister(instr->view());
    4746             : 
    4747        4734 :   __ movp(kScratchRegister,
    4748        2367 :           FieldOperand(view, JSArrayBufferView::kBufferOffset));
    4749             :   __ testb(FieldOperand(kScratchRegister, JSArrayBuffer::kBitFieldOffset),
    4750        4734 :            Immediate(1 << JSArrayBuffer::WasNeutered::kShift));
    4751             :   DeoptimizeIf(not_zero, instr, DeoptimizeReason::kOutOfBounds);
    4752        2367 : }
    4753             : 
    4754             : 
    4755       42634 : void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
    4756             :   Register input = ToRegister(instr->value());
    4757             : 
    4758      107404 :   __ movp(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset));
    4759             : 
    4760       85268 :   if (instr->hydrogen()->is_interval_check()) {
    4761             :     InstanceType first;
    4762             :     InstanceType last;
    4763        1293 :     instr->hydrogen()->GetCheckInterval(&first, &last);
    4764             : 
    4765             :     __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
    4766        5172 :             Immediate(static_cast<int8_t>(first)));
    4767             : 
    4768             :     // If there is only one type in the interval check for equality.
    4769        1293 :     if (first == last) {
    4770             :       DeoptimizeIf(not_equal, instr, DeoptimizeReason::kWrongInstanceType);
    4771             :     } else {
    4772             :       DeoptimizeIf(below, instr, DeoptimizeReason::kWrongInstanceType);
    4773             :       // Omit check for the last type.
    4774        1293 :       if (last != LAST_TYPE) {
    4775             :         __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
    4776           0 :                 Immediate(static_cast<int8_t>(last)));
    4777             :         DeoptimizeIf(above, instr, DeoptimizeReason::kWrongInstanceType);
    4778             :       }
    4779             :     }
    4780             :   } else {
    4781             :     uint8_t mask;
    4782             :     uint8_t tag;
    4783       41341 :     instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
    4784             : 
    4785       82682 :     if (base::bits::IsPowerOfTwo32(mask)) {
    4786             :       DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
    4787             :       __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
    4788       90819 :                Immediate(mask));
    4789       30273 :       DeoptimizeIf(tag == 0 ? not_zero : zero, instr,
    4790       30273 :                    DeoptimizeReason::kWrongInstanceType);
    4791             :     } else {
    4792             :       __ movzxbl(kScratchRegister,
    4793       11068 :                  FieldOperand(kScratchRegister, Map::kInstanceTypeOffset));
    4794       22136 :       __ andb(kScratchRegister, Immediate(mask));
    4795       22136 :       __ cmpb(kScratchRegister, Immediate(tag));
    4796             :       DeoptimizeIf(not_equal, instr, DeoptimizeReason::kWrongInstanceType);
    4797             :     }
    4798             :   }
    4799       42634 : }
    4800             : 
    4801             : 
    4802       34999 : void LCodeGen::DoCheckValue(LCheckValue* instr) {
    4803       34999 :   Register reg = ToRegister(instr->value());
    4804       34999 :   __ Cmp(reg, instr->hydrogen()->object().handle());
    4805             :   DeoptimizeIf(not_equal, instr, DeoptimizeReason::kValueMismatch);
    4806       34999 : }
    4807             : 
    4808             : 
    4809        1343 : void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
    4810             :   Label deopt, done;
    4811             :   // If the map is not deprecated the migration attempt does not make sense.
    4812       16116 :   __ Push(object);
    4813        1343 :   __ movp(object, FieldOperand(object, HeapObject::kMapOffset));
    4814             :   __ testl(FieldOperand(object, Map::kBitField3Offset),
    4815        1343 :            Immediate(Map::Deprecated::kMask));
    4816        1343 :   __ Pop(object);
    4817        1343 :   __ j(zero, &deopt);
    4818             : 
    4819             :   {
    4820             :     PushSafepointRegistersScope scope(this);
    4821        1343 :     __ Push(object);
    4822             : 
    4823        1343 :     __ Set(rsi, 0);
    4824        1343 :     __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
    4825             :     RecordSafepointWithRegisters(
    4826             :         instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
    4827             : 
    4828        1343 :     __ testp(rax, Immediate(kSmiTagMask));
    4829             :   }
    4830        1343 :   __ j(not_zero, &done);
    4831             : 
    4832        1343 :   __ bind(&deopt);
    4833             :   DeoptimizeIf(always, instr, DeoptimizeReason::kInstanceMigrationFailed);
    4834             : 
    4835        1343 :   __ bind(&done);
    4836        1343 : }
    4837             : 
    4838             : 
    4839      180518 : void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
    4840           0 :   class DeferredCheckMaps final : public LDeferredCode {
    4841             :    public:
    4842             :     DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
    4843        2686 :         : LDeferredCode(codegen), instr_(instr), object_(object) {
    4844        1343 :       SetExit(check_maps());
    4845             :     }
    4846        1343 :     void Generate() override {
    4847        1343 :       codegen()->DoDeferredInstanceMigration(instr_, object_);
    4848        1343 :     }
    4849             :     Label* check_maps() { return &check_maps_; }
    4850        2686 :     LInstruction* instr() override { return instr_; }
    4851             : 
    4852             :    private:
    4853             :     LCheckMaps* instr_;
    4854             :     Label check_maps_;
    4855             :     Register object_;
    4856             :   };
    4857             : 
    4858      361036 :   if (instr->hydrogen()->IsStabilityCheck()) {
    4859      440710 :     const UniqueSet<Map>* maps = instr->hydrogen()->maps();
    4860      440710 :     for (int i = 0; i < maps->size(); ++i) {
    4861      263761 :       AddStabilityDependency(maps->at(i).handle());
    4862             :     }
    4863      109845 :     return;
    4864             :   }
    4865             : 
    4866             :   LOperand* input = instr->value();
    4867             :   DCHECK(input->IsRegister());
    4868             :   Register reg = ToRegister(input);
    4869             : 
    4870             :   DeferredCheckMaps* deferred = NULL;
    4871       70673 :   if (instr->hydrogen()->HasMigrationTarget()) {
    4872             :     deferred = new(zone()) DeferredCheckMaps(this, instr, reg);
    4873        1343 :     __ bind(deferred->check_maps());
    4874             :   }
    4875             : 
    4876      219895 :   const UniqueSet<Map>* maps = instr->hydrogen()->maps();
    4877             :   Label success;
    4878      149222 :   for (int i = 0; i < maps->size() - 1; i++) {
    4879        3938 :     Handle<Map> map = maps->at(i).handle();
    4880        3938 :     __ CompareMap(reg, map);
    4881        3938 :     __ j(equal, &success, Label::kNear);
    4882             :   }
    4883             : 
    4884       70673 :   Handle<Map> map = maps->at(maps->size() - 1).handle();
    4885       70673 :   __ CompareMap(reg, map);
    4886      141346 :   if (instr->hydrogen()->HasMigrationTarget()) {
    4887        2686 :     __ j(not_equal, deferred->entry());
    4888             :   } else {
    4889             :     DeoptimizeIf(not_equal, instr, DeoptimizeReason::kWrongMap);
    4890             :   }
    4891             : 
    4892       70673 :   __ bind(&success);
    4893             : }
    4894             : 
    4895             : 
    4896         223 : void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
    4897         223 :   XMMRegister value_reg = ToDoubleRegister(instr->unclamped());
    4898         223 :   XMMRegister xmm_scratch = double_scratch0();
    4899         446 :   Register result_reg = ToRegister(instr->result());
    4900         223 :   __ ClampDoubleToUint8(value_reg, xmm_scratch, result_reg);
    4901         223 : }
    4902             : 
    4903             : 
    4904          84 : void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
    4905             :   DCHECK(instr->unclamped()->Equals(instr->result()));
    4906         168 :   Register value_reg = ToRegister(instr->result());
    4907          84 :   __ ClampUint8(value_reg);
    4908          84 : }
    4909             : 
    4910             : 
    4911          21 : void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
    4912             :   DCHECK(instr->unclamped()->Equals(instr->result()));
    4913             :   Register input_reg = ToRegister(instr->unclamped());
    4914          21 :   XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp_xmm());
    4915          21 :   XMMRegister xmm_scratch = double_scratch0();
    4916             :   Label is_smi, done, heap_number;
    4917          21 :   Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
    4918         294 :   __ JumpIfSmi(input_reg, &is_smi, dist);
    4919             : 
    4920             :   // Check for heap number
    4921             :   __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
    4922          63 :          factory()->heap_number_map());
    4923          21 :   __ j(equal, &heap_number, Label::kNear);
    4924             : 
    4925             :   // Check for undefined. Undefined is converted to zero for clamping
    4926             :   // conversions.
    4927          21 :   __ Cmp(input_reg, factory()->undefined_value());
    4928             :   DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumberUndefined);
    4929          21 :   __ xorl(input_reg, input_reg);
    4930          21 :   __ jmp(&done, Label::kNear);
    4931             : 
    4932             :   // Heap number
    4933          21 :   __ bind(&heap_number);
    4934          42 :   __ Movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset));
    4935          21 :   __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg);
    4936          21 :   __ jmp(&done, Label::kNear);
    4937             : 
    4938             :   // smi
    4939          21 :   __ bind(&is_smi);
    4940          21 :   __ SmiToInteger32(input_reg, input_reg);
    4941          21 :   __ ClampUint8(input_reg);
    4942             : 
    4943          21 :   __ bind(&done);
    4944          21 : }
    4945             : 
    4946             : 
    4947       20430 : void LCodeGen::DoAllocate(LAllocate* instr) {
    4948           0 :   class DeferredAllocate final : public LDeferredCode {
    4949             :    public:
    4950             :     DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
    4951       20430 :         : LDeferredCode(codegen), instr_(instr) { }
    4952       20430 :     void Generate() override { codegen()->DoDeferredAllocate(instr_); }
    4953       40860 :     LInstruction* instr() override { return instr_; }
    4954             : 
    4955             :    private:
    4956             :     LAllocate* instr_;
    4957             :   };
    4958             : 
    4959             :   DeferredAllocate* deferred =
    4960       61943 :       new(zone()) DeferredAllocate(this, instr);
    4961             : 
    4962       20430 :   Register result = ToRegister(instr->result());
    4963             :   Register temp = ToRegister(instr->temp());
    4964             : 
    4965             :   // Allocate memory for the object.
    4966             :   AllocationFlags flags = NO_ALLOCATION_FLAGS;
    4967       40860 :   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
    4968             :     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
    4969             :   }
    4970       20430 :   if (instr->hydrogen()->IsOldSpaceAllocation()) {
    4971             :     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
    4972           8 :     flags = static_cast<AllocationFlags>(flags | PRETENURE);
    4973             :   }
    4974             : 
    4975       20430 :   if (instr->hydrogen()->IsAllocationFoldingDominator()) {
    4976        2039 :     flags = static_cast<AllocationFlags>(flags | ALLOCATION_FOLDING_DOMINATOR);
    4977             :   }
    4978             :   DCHECK(!instr->hydrogen()->IsAllocationFolded());
    4979             : 
    4980       20430 :   if (instr->size()->IsConstantOperand()) {
    4981             :     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
    4982       12771 :     CHECK(size <= kMaxRegularHeapObjectSize);
    4983       25542 :     __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
    4984             :   } else {
    4985        7659 :     Register size = ToRegister(instr->size());
    4986       15318 :     __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
    4987             :   }
    4988             : 
    4989       20430 :   __ bind(deferred->exit());
    4990             : 
    4991       40860 :   if (instr->hydrogen()->MustPrefillWithFiller()) {
    4992         129 :     if (instr->size()->IsConstantOperand()) {
    4993             :       int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
    4994         242 :       __ movl(temp, Immediate((size / kPointerSize) - 1));
    4995             :     } else {
    4996             :       temp = ToRegister(instr->size());
    4997           8 :       __ sarp(temp, Immediate(kPointerSizeLog2));
    4998           8 :       __ decl(temp);
    4999             :     }
    5000             :     Label loop;
    5001         129 :     __ bind(&loop);
    5002             :     __ Move(FieldOperand(result, temp, times_pointer_size, 0),
    5003         387 :         isolate()->factory()->one_pointer_filler_map());
    5004         129 :     __ decl(temp);
    5005         129 :     __ j(not_zero, &loop);
    5006             :   }
    5007       20430 : }
    5008             : 
    5009        4836 : void LCodeGen::DoFastAllocate(LFastAllocate* instr) {
    5010             :   DCHECK(instr->hydrogen()->IsAllocationFolded());
    5011             :   DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator());
    5012        9672 :   Register result = ToRegister(instr->result());
    5013        4836 :   Register temp = ToRegister(instr->temp());
    5014             : 
    5015             :   AllocationFlags flags = ALLOCATION_FOLDED;
    5016        9672 :   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
    5017             :     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
    5018             :   }
    5019        4836 :   if (instr->hydrogen()->IsOldSpaceAllocation()) {
    5020             :     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
    5021          44 :     flags = static_cast<AllocationFlags>(flags | PRETENURE);
    5022             :   }
    5023        4836 :   if (instr->size()->IsConstantOperand()) {
    5024             :     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
    5025        4836 :     CHECK(size <= kMaxRegularHeapObjectSize);
    5026        4836 :     __ FastAllocate(size, result, temp, flags);
    5027             :   } else {
    5028           0 :     Register size = ToRegister(instr->size());
    5029           0 :     __ FastAllocate(size, result, temp, flags);
    5030             :   }
    5031        4836 : }
    5032             : 
    5033       20430 : void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
    5034       20430 :   Register result = ToRegister(instr->result());
    5035             : 
    5036             :   // TODO(3095996): Get rid of this. For now, we need to make the
    5037             :   // result register contain a valid pointer because it is already
    5038             :   // contained in the register pointer map.
    5039       95496 :   __ Move(result, Smi::kZero);
    5040             : 
    5041             :   PushSafepointRegistersScope scope(this);
    5042       20430 :   if (instr->size()->IsRegister()) {
    5043        7659 :     Register size = ToRegister(instr->size());
    5044             :     DCHECK(!size.is(result));
    5045        7659 :     __ Integer32ToSmi(size, size);
    5046        7659 :     __ Push(size);
    5047             :   } else {
    5048             :     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
    5049       12771 :     __ Push(Smi::FromInt(size));
    5050             :   }
    5051             : 
    5052             :   int flags = 0;
    5053       40860 :   if (instr->hydrogen()->IsOldSpaceAllocation()) {
    5054             :     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
    5055             :     flags = AllocateTargetSpace::update(flags, OLD_SPACE);
    5056             :   } else {
    5057             :     flags = AllocateTargetSpace::update(flags, NEW_SPACE);
    5058             :   }
    5059       20430 :   __ Push(Smi::FromInt(flags));
    5060             : 
    5061             :   CallRuntimeFromDeferred(
    5062       20430 :       Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
    5063       20430 :   __ StoreToSafepointRegisterSlot(result, rax);
    5064             : 
    5065       40860 :   if (instr->hydrogen()->IsAllocationFoldingDominator()) {
    5066             :     AllocationFlags allocation_flags = NO_ALLOCATION_FLAGS;
    5067        2039 :     if (instr->hydrogen()->IsOldSpaceAllocation()) {
    5068             :       DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
    5069           7 :       allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE);
    5070             :     }
    5071             :     // If the allocation folding dominator allocate triggered a GC, allocation
    5072             :     // happend in the runtime. We have to reset the top pointer to virtually
    5073             :     // undo the allocation.
    5074             :     ExternalReference allocation_top =
    5075        2039 :         AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags);
    5076        2039 :     __ subp(rax, Immediate(kHeapObjectTag));
    5077        2039 :     __ Store(allocation_top, rax);
    5078        2039 :     __ addp(rax, Immediate(kHeapObjectTag));
    5079             :   }
    5080       20430 : }
    5081             : 
    5082             : 
    5083       38017 : void LCodeGen::DoTypeof(LTypeof* instr) {
    5084             :   DCHECK(ToRegister(instr->context()).is(rsi));
    5085             :   DCHECK(ToRegister(instr->value()).is(rbx));
    5086             :   Label end, do_call;
    5087       38017 :   Register value_register = ToRegister(instr->value());
    5088      190085 :   __ JumpIfNotSmi(value_register, &do_call);
    5089       76034 :   __ Move(rax, isolate()->factory()->number_string());
    5090       38017 :   __ jmp(&end);
    5091       38017 :   __ bind(&do_call);
    5092       38017 :   Callable callable = CodeFactory::Typeof(isolate());
    5093             :   CallCode(callable.code(), RelocInfo::CODE_TARGET, instr);
    5094       38017 :   __ bind(&end);
    5095       38017 : }
    5096             : 
    5097             : 
    5098     1344576 : void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
    5099             :   DCHECK(!operand->IsDoubleRegister());
    5100     1344576 :   if (operand->IsConstantOperand()) {
    5101     1344576 :     __ Push(ToHandle(LConstantOperand::cast(operand)));
    5102      644827 :   } else if (operand->IsRegister()) {
    5103      335850 :     __ Push(ToRegister(operand));
    5104             :   } else {
    5105      617954 :     __ Push(ToOperand(operand));
    5106             :   }
    5107     1344576 : }
    5108             : 
    5109             : 
    5110       42153 : void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
    5111       42153 :   Register input = ToRegister(instr->value());
    5112       42153 :   Condition final_branch_condition = EmitTypeofIs(instr, input);
    5113       42153 :   if (final_branch_condition != no_condition) {
    5114       42153 :     EmitBranch(instr, final_branch_condition);
    5115             :   }
    5116       42153 : }
    5117             : 
    5118             : 
    5119       42153 : Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
    5120       42153 :   Label* true_label = instr->TrueLabel(chunk_);
    5121       42153 :   Label* false_label = instr->FalseLabel(chunk_);
    5122       42153 :   Handle<String> type_name = instr->type_literal();
    5123       42153 :   int left_block = instr->TrueDestination(chunk_);
    5124       42153 :   int right_block = instr->FalseDestination(chunk_);
    5125      214606 :   int next_block = GetNextEmittedBlock();
    5126             : 
    5127             :   Label::Distance true_distance = left_block == next_block ? Label::kNear
    5128       42153 :                                                            : Label::kFar;
    5129             :   Label::Distance false_distance = right_block == next_block ? Label::kNear
    5130       42153 :                                                              : Label::kFar;
    5131             :   Condition final_branch_condition = no_condition;
    5132       42153 :   Factory* factory = isolate()->factory();
    5133       42153 :   if (String::Equals(type_name, factory->number_string())) {
    5134       14076 :     __ JumpIfSmi(input, true_label, true_distance);
    5135             :     __ CompareRoot(FieldOperand(input, HeapObject::kMapOffset),
    5136       28152 :                    Heap::kHeapNumberMapRootIndex);
    5137             : 
    5138             :     final_branch_condition = equal;
    5139             : 
    5140       28077 :   } else if (String::Equals(type_name, factory->string_string())) {
    5141        1707 :     __ JumpIfSmi(input, false_label, false_distance);
    5142        1707 :     __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
    5143             :     final_branch_condition = below;
    5144             : 
    5145       26370 :   } else if (String::Equals(type_name, factory->symbol_string())) {
    5146         749 :     __ JumpIfSmi(input, false_label, false_distance);
    5147         749 :     __ CmpObjectType(input, SYMBOL_TYPE, input);
    5148             :     final_branch_condition = equal;
    5149             : 
    5150       25621 :   } else if (String::Equals(type_name, factory->boolean_string())) {
    5151         566 :     __ CompareRoot(input, Heap::kTrueValueRootIndex);
    5152         566 :     __ j(equal, true_label, true_distance);
    5153         566 :     __ CompareRoot(input, Heap::kFalseValueRootIndex);
    5154             :     final_branch_condition = equal;
    5155             : 
    5156       25055 :   } else if (String::Equals(type_name, factory->undefined_string())) {
    5157         414 :     __ CompareRoot(input, Heap::kNullValueRootIndex);
    5158         414 :     __ j(equal, false_label, false_distance);
    5159         414 :     __ JumpIfSmi(input, false_label, false_distance);
    5160             :     // Check for undetectable objects => true.
    5161         414 :     __ movp(input, FieldOperand(input, HeapObject::kMapOffset));
    5162             :     __ testb(FieldOperand(input, Map::kBitFieldOffset),
    5163         828 :              Immediate(1 << Map::kIsUndetectable));
    5164             :     final_branch_condition = not_zero;
    5165             : 
    5166       24641 :   } else if (String::Equals(type_name, factory->function_string())) {
    5167       12225 :     __ JumpIfSmi(input, false_label, false_distance);
    5168             :     // Check for callable and not undetectable objects => true.
    5169       12225 :     __ movp(input, FieldOperand(input, HeapObject::kMapOffset));
    5170       12225 :     __ movzxbl(input, FieldOperand(input, Map::kBitFieldOffset));
    5171             :     __ andb(input,
    5172       12225 :             Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
    5173       12225 :     __ cmpb(input, Immediate(1 << Map::kIsCallable));
    5174             :     final_branch_condition = equal;
    5175             : 
    5176       12416 :   } else if (String::Equals(type_name, factory->object_string())) {
    5177       12416 :     __ JumpIfSmi(input, false_label, false_distance);
    5178       12416 :     __ CompareRoot(input, Heap::kNullValueRootIndex);
    5179       12416 :     __ j(equal, true_label, true_distance);
    5180             :     STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
    5181       12416 :     __ CmpObjectType(input, FIRST_JS_RECEIVER_TYPE, input);
    5182       12416 :     __ j(below, false_label, false_distance);
    5183             :     // Check for callable or undetectable objects => false.
    5184             :     __ testb(FieldOperand(input, Map::kBitFieldOffset),
    5185       24832 :              Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
    5186             :     final_branch_condition = zero;
    5187             : 
    5188             :   } else {
    5189           0 :     __ jmp(false_label, false_distance);
    5190             :   }
    5191             : 
    5192       42153 :   return final_branch_condition;
    5193             : }
    5194             : 
    5195             : 
    5196     1985147 : void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
    5197     5955440 :   if (info()->ShouldEnsureSpaceForLazyDeopt()) {
    5198             :     // Ensure that we have enough space after the previous lazy-bailout
    5199             :     // instruction for patching the code here.
    5200     1947585 :     int current_pc = masm()->pc_offset();
    5201     1947585 :     if (current_pc < last_lazy_deopt_pc_ + space_needed) {
    5202      208301 :       int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
    5203      208301 :       __ Nop(padding_size);
    5204             :     }
    5205             :   }
    5206     3970292 :   last_lazy_deopt_pc_ = masm()->pc_offset();
    5207     1985146 : }
    5208             : 
    5209             : 
    5210     1675206 : void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
    5211     3350412 :   last_lazy_deopt_pc_ = masm()->pc_offset();
    5212             :   DCHECK(instr->HasEnvironment());
    5213     3350416 :   LEnvironment* env = instr->environment();
    5214     1675206 :   RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
    5215     1675210 :   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
    5216     1675211 : }
    5217             : 
    5218             : 
    5219       31907 : void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
    5220       31907 :   Deoptimizer::BailoutType type = instr->hydrogen()->type();
    5221             :   // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
    5222             :   // needed return address), even though the implementation of LAZY and EAGER is
    5223             :   // now identical. When LAZY is eventually completely folded into EAGER, remove
    5224             :   // the special case below.
    5225       31907 :   if (info()->IsStub() && type == Deoptimizer::EAGER) {
    5226             :     type = Deoptimizer::LAZY;
    5227             :   }
    5228       31907 :   DeoptimizeIf(no_condition, instr, instr->hydrogen()->reason(), type);
    5229       31907 : }
    5230             : 
    5231             : 
    5232        3030 : void LCodeGen::DoDummy(LDummy* instr) {
    5233             :   // Nothing to see here, move on!
    5234        3030 : }
    5235             : 
    5236             : 
    5237        5582 : void LCodeGen::DoDummyUse(LDummyUse* instr) {
    5238             :   // Nothing to see here, move on!
    5239        5582 : }
    5240             : 
    5241             : 
    5242       31122 : void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
    5243             :   PushSafepointRegistersScope scope(this);
    5244       62244 :   __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
    5245       31122 :   __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
    5246       31122 :   RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0);
    5247             :   DCHECK(instr->HasEnvironment());
    5248       31122 :   LEnvironment* env = instr->environment();
    5249       31122 :   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
    5250       31122 : }
    5251             : 
    5252             : 
    5253      286454 : void LCodeGen::DoStackCheck(LStackCheck* instr) {
    5254           0 :   class DeferredStackCheck final : public LDeferredCode {
    5255             :    public:
    5256             :     DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
    5257       31122 :         : LDeferredCode(codegen), instr_(instr) { }
    5258       31122 :     void Generate() override { codegen()->DoDeferredStackCheck(instr_); }
    5259       62244 :     LInstruction* instr() override { return instr_; }
    5260             : 
    5261             :    private:
    5262             :     LStackCheck* instr_;
    5263             :   };
    5264             : 
    5265             :   DCHECK(instr->HasEnvironment());
    5266      286454 :   LEnvironment* env = instr->environment();
    5267             :   // There is no LLazyBailout instruction for stack-checks. We have to
    5268             :   // prepare for lazy deoptimization explicitly here.
    5269      286454 :   if (instr->hydrogen()->is_function_entry()) {
    5270             :     // Perform stack overflow check.
    5271             :     Label done;
    5272      635152 :     __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
    5273      255333 :     __ j(above_equal, &done, Label::kNear);
    5274             : 
    5275             :     DCHECK(instr->context()->IsRegister());
    5276             :     DCHECK(ToRegister(instr->context()).is(rsi));
    5277             :     CallCode(isolate()->builtins()->StackCheck(),
    5278             :              RelocInfo::CODE_TARGET,
    5279      255333 :              instr);
    5280      255332 :     __ bind(&done);
    5281             :   } else {
    5282             :     DCHECK(instr->hydrogen()->is_backwards_branch());
    5283             :     // Perform stack overflow check if this goto needs it before jumping.
    5284             :     DeferredStackCheck* deferred_stack_check =
    5285             :         new(zone()) DeferredStackCheck(this, instr);
    5286       31122 :     __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
    5287       62244 :     __ j(below, deferred_stack_check->entry());
    5288       31122 :     EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
    5289       62244 :     __ bind(instr->done_label());
    5290             :     deferred_stack_check->SetExit(instr->done_label());
    5291       31122 :     RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
    5292             :     // Don't record a deoptimization index for the safepoint here.
    5293             :     // This will be done explicitly when emitting call and the safepoint in
    5294             :     // the deferred code.
    5295             :   }
    5296      286454 : }
    5297             : 
    5298             : 
    5299        2365 : void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
    5300             :   // This is a pseudo-instruction that ensures that the environment here is
    5301             :   // properly registered for deoptimization and records the assembler's PC
    5302             :   // offset.
    5303        2365 :   LEnvironment* environment = instr->environment();
    5304             : 
    5305             :   // If the environment were already registered, we would have no way of
    5306             :   // backpatching it with the spill slot operands.
    5307             :   DCHECK(!environment->HasBeenRegistered());
    5308        2365 :   RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
    5309             : 
    5310        2365 :   GenerateOsrPrologue();
    5311        2365 : }
    5312             : 
    5313             : 
    5314         751 : void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
    5315             :   DCHECK(ToRegister(instr->context()).is(rsi));
    5316             : 
    5317             :   Label use_cache, call_runtime;
    5318        4506 :   __ CheckEnumCache(&call_runtime);
    5319             : 
    5320         751 :   __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
    5321         751 :   __ jmp(&use_cache, Label::kNear);
    5322             : 
    5323             :   // Get the set of properties to enumerate.
    5324         751 :   __ bind(&call_runtime);
    5325         751 :   __ Push(rax);
    5326         751 :   CallRuntime(Runtime::kForInEnumerate, instr);
    5327         751 :   __ bind(&use_cache);
    5328         751 : }
    5329             : 
    5330             : 
    5331        1732 : void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
    5332        1732 :   Register map = ToRegister(instr->map());
    5333        1732 :   Register result = ToRegister(instr->result());
    5334             :   Label load_cache, done;
    5335       17320 :   __ EnumLength(result, map);
    5336        1732 :   __ Cmp(result, Smi::kZero);
    5337        1732 :   __ j(not_equal, &load_cache, Label::kNear);
    5338        1732 :   __ LoadRoot(result, Heap::kEmptyFixedArrayRootIndex);
    5339        1732 :   __ jmp(&done, Label::kNear);
    5340        1732 :   __ bind(&load_cache);
    5341        1732 :   __ LoadInstanceDescriptors(map, result);
    5342             :   __ movp(result,
    5343        1732 :           FieldOperand(result, DescriptorArray::kEnumCacheOffset));
    5344             :   __ movp(result,
    5345        1732 :           FieldOperand(result, FixedArray::SizeFor(instr->idx())));
    5346        1732 :   __ bind(&done);
    5347        1732 :   Condition cc = masm()->CheckSmi(result);
    5348             :   DeoptimizeIf(cc, instr, DeoptimizeReason::kNoCache);
    5349        1732 : }
    5350             : 
    5351             : 
    5352        1205 : void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
    5353             :   Register object = ToRegister(instr->value());
    5354        1205 :   __ cmpp(ToRegister(instr->map()),
    5355        1205 :           FieldOperand(object, HeapObject::kMapOffset));
    5356             :   DeoptimizeIf(not_equal, instr, DeoptimizeReason::kWrongMap);
    5357        1205 : }
    5358             : 
    5359             : 
    5360         588 : void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
    5361             :                                            Register object,
    5362             :                                            Register index) {
    5363             :   PushSafepointRegistersScope scope(this);
    5364        2352 :   __ Push(object);
    5365         588 :   __ Push(index);
    5366         588 :   __ xorp(rsi, rsi);
    5367         588 :   __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble);
    5368             :   RecordSafepointWithRegisters(
    5369             :       instr->pointer_map(), 2, Safepoint::kNoLazyDeopt);
    5370         588 :   __ StoreToSafepointRegisterSlot(object, rax);
    5371         588 : }
    5372             : 
    5373             : 
    5374         588 : void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
    5375           0 :   class DeferredLoadMutableDouble final : public LDeferredCode {
    5376             :    public:
    5377             :     DeferredLoadMutableDouble(LCodeGen* codegen,
    5378             :                               LLoadFieldByIndex* instr,
    5379             :                               Register object,
    5380             :                               Register index)
    5381             :         : LDeferredCode(codegen),
    5382             :           instr_(instr),
    5383             :           object_(object),
    5384         588 :           index_(index) {
    5385             :     }
    5386         588 :     void Generate() override {
    5387         588 :       codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_);
    5388         588 :     }
    5389        1176 :     LInstruction* instr() override { return instr_; }
    5390             : 
    5391             :    private:
    5392             :     LLoadFieldByIndex* instr_;
    5393             :     Register object_;
    5394             :     Register index_;
    5395             :   };
    5396             : 
    5397             :   Register object = ToRegister(instr->object());
    5398             :   Register index = ToRegister(instr->index());
    5399             : 
    5400             :   DeferredLoadMutableDouble* deferred;
    5401        9408 :   deferred = new(zone()) DeferredLoadMutableDouble(this, instr, object, index);
    5402             : 
    5403             :   Label out_of_object, done;
    5404             :   __ Move(kScratchRegister, Smi::FromInt(1));
    5405         588 :   __ testp(index, kScratchRegister);
    5406        1176 :   __ j(not_zero, deferred->entry());
    5407             : 
    5408         588 :   __ sarp(index, Immediate(1));
    5409             : 
    5410         588 :   __ SmiToInteger32(index, index);
    5411         588 :   __ cmpl(index, Immediate(0));
    5412         588 :   __ j(less, &out_of_object, Label::kNear);
    5413             :   __ movp(object, FieldOperand(object,
    5414             :                                index,
    5415             :                                times_pointer_size,
    5416         588 :                                JSObject::kHeaderSize));
    5417         588 :   __ jmp(&done, Label::kNear);
    5418             : 
    5419         588 :   __ bind(&out_of_object);
    5420         588 :   __ movp(object, FieldOperand(object, JSObject::kPropertiesOffset));
    5421         588 :   __ negl(index);
    5422             :   // Index is now equal to out of object property index plus 1.
    5423             :   __ movp(object, FieldOperand(object,
    5424             :                                index,
    5425             :                                times_pointer_size,
    5426         588 :                                FixedArray::kHeaderSize - kPointerSize));
    5427         588 :   __ bind(deferred->exit());
    5428         588 :   __ bind(&done);
    5429         588 : }
    5430             : 
    5431             : #undef __
    5432             : 
    5433             : }  // namespace internal
    5434             : }  // namespace v8
    5435             : 
    5436             : #endif  // V8_TARGET_ARCH_X64

Generated by: LCOV version 1.10