1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X87
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/x87/lithium-codegen-x87.h"
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
1062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/builtins/builtins-constructor.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/hydrogen-osr.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/deoptimizer.h"
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h"
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/stub-cache.h"
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/x87/frames-x87.h"
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// When invoking builtins, we need to record the safepoint in the middle of
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the invoke instruction sequence generated by the macro assembler.
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass SafepointGenerator final : public CallWrapper {
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SafepointGenerator(LCodeGen* codegen,
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     LPointerMap* pointers,
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     Safepoint::DeoptMode mode)
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : codegen_(codegen),
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        pointers_(pointers),
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        deopt_mode_(mode) {}
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual ~SafepointGenerator() {}
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BeforeCall(int call_size) const override {}
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AfterCall() const override {
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    codegen_->RecordSafepoint(pointers_, deopt_mode_);
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LCodeGen* codegen_;
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LPointerMap* pointers_;
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Safepoint::DeoptMode deopt_mode_;
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ masm()->
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::GenerateCode() {
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LPhase phase("Z_Code generation", chunk());
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_unused());
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  status_ = GENERATING;
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Open a frame scope to indicate that there is a frame on the stack.  The
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // MANUAL indicates that the scope shouldn't actually generate code to set up
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the frame (that is done in GeneratePrologue).
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FrameScope frame_scope(masm_, StackFrame::MANUAL);
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return GeneratePrologue() &&
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      GenerateBody() &&
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      GenerateDeferredCode() &&
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      GenerateJumpTable() &&
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      GenerateSafepointTable();
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::FinishCode(Handle<Code> code) {
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_done());
70109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  code->set_stack_slots(GetTotalFrameSlotCount());
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PopulateDeoptimizationData(code);
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (info()->ShouldEnsureSpaceForLazyDeopt()) {
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef _MSC_VER
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::MakeSureStackPagesMapped(int offset) {
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kPageSize = 4 * KB;
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (offset -= kPageSize; offset > 0; offset -= kPageSize) {
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(Operand(esp, offset), eax);
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::GeneratePrologue() {
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_generating());
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info()->IsOptimizing()) {
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ProfileEntryHookStub::MaybeCallEntryHook(masm_);
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info()->set_prologue_offset(masm_->pc_offset());
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (NeedsEagerFrame()) {
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!frame_is_built_);
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    frame_is_built_ = true;
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (info()->IsStub()) {
1013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      __ StubPrologue(StackFrame::STUB);
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ Prologue(info()->GeneratePreagedPrologue());
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Reserve space for the stack slots needed by the code.
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int slots = GetStackSlotCount();
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(slots != 0 || !info()->IsOptimizing());
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (slots > 0) {
1113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ sub(Operand(esp), Immediate(slots * kPointerSize));
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef _MSC_VER
1133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    MakeSureStackPagesMapped(slots * kPointerSize);
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (FLAG_debug_code) {
1163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      __ push(eax);
1173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      __ mov(Operand(eax), Immediate(slots));
1183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Label loop;
1193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      __ bind(&loop);
1203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      __ mov(MemOperand(esp, eax, times_4, 0), Immediate(kSlotsZapValue));
1213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      __ dec(eax);
1223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      __ j(not_zero, &loop);
1233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      __ pop(eax);
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Initailize FPU state.
128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ fninit();
129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return !is_aborted();
131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LCodeGen::DoPrologue(LPrologue* instr) {
135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Comment(";;; Prologue begin");
136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Possibly allocate a local context.
138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (info_->scope()->NeedsContext()) {
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment(";;; Allocate local context");
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool need_write_barrier = true;
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Argument to NewContext is the function, which is still in edi.
142bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    int slots = info_->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Safepoint::DeoptMode deopt_mode = Safepoint::kNoLazyDeopt;
144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (info()->scope()->is_script_scope()) {
145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ push(edi);
146f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      __ Push(info()->scope()->scope_info());
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ CallRuntime(Runtime::kNewScriptContext);
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      deopt_mode = Safepoint::kLazyDeopt;
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
15062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (slots <=
15162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          ConstructorBuiltinsAssembler::MaximumFunctionContextSlots()) {
15262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Callable callable = CodeFactory::FastNewFunctionContext(
15362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            isolate(), info()->scope()->scope_type());
154f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ mov(FastNewFunctionContextDescriptor::SlotsRegister(),
155f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch               Immediate(slots));
15662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ Call(callable.code(), RelocInfo::CODE_TARGET);
15762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // Result of the FastNewFunctionContext builtin is always in new space.
158f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        need_write_barrier = false;
159f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      } else {
16062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ Push(edi);
16162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ Push(Smi::FromInt(info()->scope()->scope_type()));
162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ CallRuntime(Runtime::kNewFunctionContext);
163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    RecordSafepoint(deopt_mode);
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Context is returned in eax.  It replaces the context passed to us.
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // It's saved in the stack and kept live in esi.
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(esi, eax);
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax);
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Copy parameters into context if necessary.
173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    int num_parameters = info()->scope()->num_parameters();
174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    int first_parameter = info()->scope()->has_this_declaration() ? -1 : 0;
175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (int i = first_parameter; i < num_parameters; i++) {
176f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Variable* var = (i == -1) ? info()->scope()->receiver()
177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                : info()->scope()->parameter(i);
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (var->IsContextSlot()) {
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            (num_parameters - 1 - i) * kPointerSize;
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Load parameter from stack.
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov(eax, Operand(ebp, parameter_offset));
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Store it in the context.
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int context_offset = Context::SlotOffset(var->index());
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov(Operand(esi, context_offset), eax);
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Update the write barrier. This clobbers eax and ebx.
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (need_write_barrier) {
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ RecordWriteContextSlot(esi, context_offset, eax, ebx,
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    kDontSaveFPRegs);
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (FLAG_debug_code) {
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Label done;
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ JumpIfInNewSpace(esi, eax, &done, Label::kNear);
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Abort(kExpectedNewSpaceObject);
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ bind(&done);
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment(";;; End allocate local context");
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Comment(";;; Prologue end");
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::GenerateOsrPrologue() {
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generate the OSR entry prologue at the first unknown OSR value, or if there
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // are none, at the OSR entrypoint instruction.
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (osr_pc_offset_ >= 0) return;
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  osr_pc_offset_ = masm()->pc_offset();
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
212bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Interpreter is the first tier compiler now. It will run the code generated
213bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // by TurboFan compiler which will always put "1" on x87 FPU stack.
214bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // This behavior will affect crankshaft's x87 FPU stack depth check under
215bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // debug mode.
216bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Need to reset the FPU stack here for this scenario.
217bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ fninit();
218bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Adjust the frame size, subsuming the unoptimized frame into the
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // optimized frame.
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots();
2223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(slots >= 0);
2233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ sub(esp, Immediate(slots * kPointerSize));
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->IsCall()) {
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!instr->IsLazyBailout() && !instr->IsGap()) {
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    safepoints_.BumpLastLazySafepointIndex();
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlushX87StackIfNecessary(instr);
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) {
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // When return from function call, FPU should be initialized again.
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->IsCall() && instr->ClobbersDoubleRegisters(isolate())) {
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool double_result = instr->HasDoubleRegisterResult();
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (double_result) {
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lea(esp, Operand(esp, -kDoubleSize));
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fstp_d(Operand(esp, 0));
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fninit();
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (double_result) {
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fld_d(Operand(esp, 0));
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lea(esp, Operand(esp, kDoubleSize));
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->IsGoto()) {
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.LeavingBlock(current_block_, LGoto::cast(instr), this);
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (FLAG_debug_code && FLAG_enable_slow_asserts &&
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             !instr->IsGap() && !instr->IsReturn()) {
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->ClobbersDoubleRegisters(isolate())) {
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (instr->HasDoubleRegisterResult()) {
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK_EQ(1, x87_stack_.depth());
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK_EQ(0, x87_stack_.depth());
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ VerifyX87StackDepth(x87_stack_.depth());
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::GenerateJumpTable() {
269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!jump_table_.length()) return !is_aborted();
270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label needs_frame;
272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Comment(";;; -------------------- Jump table --------------------");
273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < jump_table_.length(); i++) {
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Deoptimizer::JumpTableEntry* table_entry = &jump_table_[i];
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&table_entry->label);
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address entry = table_entry->address;
278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DeoptComment(table_entry->deopt_info);
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (table_entry->needs_frame) {
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!info()->saves_caller_doubles());
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ push(Immediate(ExternalReference::ForDeoptEntry(entry)));
282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ call(&needs_frame);
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ call(entry, RelocInfo::RUNTIME_ENTRY);
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (needs_frame.is_linked()) {
288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&needs_frame);
289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    /* stack layout
2903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       3: entry address
2913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       2: return address  <-- esp
292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       1: garbage
293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       0: garbage
294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    */
2953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ push(MemOperand(esp, 0));                 // Copy return address.
2963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ push(MemOperand(esp, 2 * kPointerSize));  // Copy entry address.
297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    /* stack layout
299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       4: entry address
300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       3: return address
301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       1: return address
302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       0: entry address  <-- esp
303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    */
3043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ mov(MemOperand(esp, 3 * kPointerSize), ebp);  // Save ebp.
305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Fill ebp with the right stack frame address.
3063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ lea(ebp, MemOperand(esp, 3 * kPointerSize));
307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // This variant of deopt can only be used with stubs. Since we don't
309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // have a function pointer to install in the stack frame that we're
310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // building, install a special marker there instead.
311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(info()->IsStub());
312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(MemOperand(esp, 2 * kPointerSize),
313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           Immediate(Smi::FromInt(StackFrame::STUB)));
314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    /* stack layout
3163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch       3: old ebp
317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       2: stub marker
318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       1: return address
319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       0: entry address  <-- esp
320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    */
321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ret(0);  // Call the continuation without clobbering registers.
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return !is_aborted();
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::GenerateDeferredCode() {
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_generating());
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (deferred_.length() > 0) {
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      LDeferredCode* code = deferred_[i];
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      X87Stack copy(code->x87_stack());
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      x87_stack_ = copy;
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      HValue* value =
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          instructions_->at(code->instruction_index())->hydrogen_value();
337c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      RecordAndWritePosition(value->position());
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment(";;; <@%d,#%d> "
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "-------------------- Deferred %s --------------------",
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              code->instruction_index(),
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              code->instr()->hydrogen_value()->id(),
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              code->instr()->Mnemonic());
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(code->entry());
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (NeedsDeferredFrame()) {
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment(";;; Build frame");
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!frame_is_built_);
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(info()->IsStub());
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        frame_is_built_ = true;
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Build the frame in such a way that esi isn't trashed.
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ push(ebp);  // Caller's frame pointer.
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ push(Immediate(Smi::FromInt(StackFrame::STUB)));
3533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        __ lea(ebp, Operand(esp, TypedFrameConstants::kFixedFrameSizeFromFp));
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment(";;; Deferred code");
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      code->Generate();
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (NeedsDeferredFrame()) {
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ bind(code->done());
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment(";;; Destroy frame");
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(frame_is_built_);
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        frame_is_built_ = false;
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov(esp, ebp);
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ pop(ebp);
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(code->exit());
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Deferred code is the last part of the instruction sequence. Mark
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the generated code as done unless we bailed out.
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!is_aborted()) status_ = DONE;
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return !is_aborted();
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::GenerateSafepointTable() {
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_done());
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (info()->ShouldEnsureSpaceForLazyDeopt()) {
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // For lazy deoptimization we need space to patch a call after every call.
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Ensure there is always space for such patching, even if the code ends
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // in a call.
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int target_offset = masm()->pc_offset() + Deoptimizer::patch_size();
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    while (masm()->pc_offset() < target_offset) {
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm()->nop();
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
387109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  safepoints_.Emit(masm(), GetTotalFrameSlotCount());
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return !is_aborted();
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRegister LCodeGen::ToRegister(int code) const {
393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Register::from_code(code);
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochX87Register LCodeGen::ToX87Register(int code) const {
398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return X87Register::from_code(code);
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87LoadForUsage(X87Register reg) {
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(x87_stack_.Contains(reg));
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  x87_stack_.Fxch(reg);
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  x87_stack_.pop();
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87LoadForUsage(X87Register reg1, X87Register reg2) {
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(x87_stack_.Contains(reg1));
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(x87_stack_.Contains(reg2));
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (reg1.is(reg2) && x87_stack_.depth() == 1) {
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fld(x87_stack_.st(reg1));
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.push(reg1);
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.pop();
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.pop();
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.Fxch(reg1, 1);
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.Fxch(reg2);
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.pop();
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.pop();
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint LCodeGen::X87Stack::GetLayout() {
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int layout = stack_depth_;
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < stack_depth_; i++) {
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    layout |= (stack_[stack_depth_ - 1 - i].code() << ((i + 1) * 3));
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return layout;
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) {
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_mutable_);
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Contains(reg) && stack_depth_ > other_slot);
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int i  = ArrayIndex(reg);
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int st = st2idx(i);
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (st != other_slot) {
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int other_i = st2idx(other_slot);
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Register other = stack_[other_i];
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stack_[other_i]   = reg;
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stack_[i]         = other;
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (st == 0) {
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fxch(other_slot);
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (other_slot == 0) {
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fxch(st);
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fxch(st);
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fxch(other_slot);
453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fxch(st);
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint LCodeGen::X87Stack::st2idx(int pos) {
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return stack_depth_ - pos - 1;
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint LCodeGen::X87Stack::ArrayIndex(X87Register reg) {
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < stack_depth_; i++) {
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (stack_[i].is(reg)) return i;
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UNREACHABLE();
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return -1;
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::X87Stack::Contains(X87Register reg) {
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < stack_depth_; i++) {
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (stack_[i].is(reg)) return true;
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return false;
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Stack::Free(X87Register reg) {
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_mutable_);
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Contains(reg));
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int i  = ArrayIndex(reg);
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int st = st2idx(i);
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (st > 0) {
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // keep track of how fstp(i) changes the order of elements
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int tos_i = st2idx(0);
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stack_[i] = stack_[tos_i];
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  pop();
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fstp(st);
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) {
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (x87_stack_.Contains(dst)) {
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.Fxch(dst);
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fstp(0);
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.push(dst);
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Fld(src, opts);
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Mov(X87Register dst, X87Register src, X87OperandType opts) {
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (x87_stack_.Contains(dst)) {
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.Fxch(dst);
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fstp(0);
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.pop();
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push ST(i) onto the FPU register stack
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fld(x87_stack_.st(src));
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.push(dst);
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push ST(i) onto the FPU register stack
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fld(x87_stack_.st(src));
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    x87_stack_.push(dst);
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Fld(Operand src, X87OperandType opts) {
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!src.is_reg_only());
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (opts) {
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX87DoubleOperand:
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fld_d(src);
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX87FloatOperand:
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fld_s(src);
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX87IntOperand:
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fild_s(src);
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Mov(Operand dst, X87Register src, X87OperandType opts) {
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dst.is_reg_only());
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  x87_stack_.Fxch(src);
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (opts) {
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX87DoubleOperand:
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fst_d(dst);
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX87FloatOperand:
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fst_s(dst);
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case kX87IntOperand:
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fist_s(dst);
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Stack::PrepareToWrite(X87Register reg) {
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_mutable_);
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (Contains(reg)) {
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Free(reg);
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark this register as the next register to write to
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  stack_[stack_depth_] = reg;
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Stack::CommitWrite(X87Register reg) {
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_mutable_);
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Assert the reg is prepared to write, but not on the virtual stack yet
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!Contains(reg) && stack_[stack_depth_].is(reg) &&
574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         stack_depth_ < X87Register::kMaxNumAllocatableRegisters);
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  stack_depth_++;
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87PrepareBinaryOp(
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Register left, X87Register right, X87Register result) {
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // You need to use DefineSameAsFirst for x87 instructions
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(result.is(left));
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  x87_stack_.Fxch(right, 1);
584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  x87_stack_.Fxch(left);
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) {
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (stack_depth_ > 0 && instr->ClobbersDoubleRegisters(isolate())) {
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool double_inputs = instr->HasDoubleRegisterInput();
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Flush stack from tos down, since FreeX87() will mess with tos
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = stack_depth_-1; i >= 0; i--) {
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      X87Register reg = stack_[i];
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Skip registers which contain the inputs for the next instruction
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // when flushing the stack
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (double_inputs && instr->IsDoubleInput(reg, cgen)) {
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        continue;
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Free(reg);
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (i < stack_depth_-1) i++;
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->IsReturn()) {
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    while (stack_depth_ > 0) {
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fstp(0);
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stack_depth_--;
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_debug_code && FLAG_enable_slow_asserts) __ VerifyX87StackDepth(0);
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Stack::LeavingBlock(int current_block_id, LGoto* goto_instr,
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      LCodeGen* cgen) {
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For going to a joined block, an explicit LClobberDoubles is inserted before
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // LGoto. Because all used x87 registers are spilled to stack slots. The
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ResolvePhis phase of register allocator could guarantee the two input's x87
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // stacks have the same layout. So don't check stack_depth_ <= 1 here.
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int goto_block_id = goto_instr->block_id();
621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (current_block_id + 1 != goto_block_id) {
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If we have a value on the x87 stack on leaving a block, it must be a
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // phi input. If the next block we compile is not the join block, we have
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // to discard the stack state.
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Before discarding the stack state, we need to save it if the "goto block"
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // has unreachable last predecessor when FLAG_unreachable_code_elimination.
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_unreachable_code_elimination) {
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int length = goto_instr->block()->predecessors()->length();
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      bool has_unreachable_last_predecessor = false;
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (int i = 0; i < length; i++) {
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        HBasicBlock* block = goto_instr->block()->predecessors()->at(i);
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (block->IsUnreachable() &&
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            (block->block_id() + 1) == goto_block_id) {
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          has_unreachable_last_predecessor = true;
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (has_unreachable_last_predecessor) {
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (cgen->x87_stack_map_.find(goto_block_id) ==
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            cgen->x87_stack_map_.end()) {
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          X87Stack* stack = new (cgen->zone()) X87Stack(*this);
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          cgen->x87_stack_map_.insert(std::make_pair(goto_block_id, stack));
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Discard the stack state.
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stack_depth_ = 0;
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitFlushX87ForDeopt() {
653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The deoptimizer does not support X87 Registers. But as long as we
654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // deopt from a stub its not a problem, since we will re-materialize the
655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // original stub inputs, which can't be double registers.
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // DCHECK(info()->IsStub());
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code && FLAG_enable_slow_asserts) {
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pushfd();
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ VerifyX87StackDepth(x87_stack_.depth());
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ popfd();
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Flush X87 stack in the deoptimizer entry.
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister LCodeGen::ToRegister(LOperand* op) const {
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(op->IsRegister());
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return ToRegister(op->index());
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochX87Register LCodeGen::ToX87Register(LOperand* op) const {
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(op->IsDoubleRegister());
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return ToX87Register(op->index());
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return ToRepresentation(op, Representation::Integer32());
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint32_t LCodeGen::ToRepresentation(LConstantOperand* op,
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   const Representation& r) const {
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HConstant* constant = chunk_->LookupConstant(op);
687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (r.IsExternal()) {
688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return reinterpret_cast<int32_t>(
689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        constant->ExternalReferenceValue().address());
690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t value = constant->Integer32Value();
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger32()) return value;
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(r.IsSmiOrTagged());
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return reinterpret_cast<int32_t>(Smi::FromInt(value));
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HConstant* constant = chunk_->LookupConstant(op);
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return constant->handle(isolate());
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble LCodeGen::ToDouble(LConstantOperand* op) const {
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HConstant* constant = chunk_->LookupConstant(op);
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(constant->HasDoubleValue());
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return constant->DoubleValue();
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochExternalReference LCodeGen::ToExternalReference(LConstantOperand* op) const {
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HConstant* constant = chunk_->LookupConstant(op);
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(constant->HasExternalReferenceValue());
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return constant->ExternalReferenceValue();
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::IsInteger32(LConstantOperand* op) const {
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32();
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::IsSmi(LConstantOperand* op) const {
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return chunk_->LookupLiteralRepresentation(op).IsSmi();
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int ArgumentsOffsetWithoutFrame(int index) {
730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(index < 0);
731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return -(index + 1) * kPointerSize + kPCOnStackSize;
732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOperand LCodeGen::ToOperand(LOperand* op) const {
736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (op->IsRegister()) return Operand(ToRegister(op));
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!op->IsDoubleRegister());
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (NeedsEagerFrame()) {
740109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return Operand(ebp, FrameSlotToFPOffset(op->index()));
741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Retrieve parameter without eager stack-frame relative to the
743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // stack-pointer.
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Operand(esp, ArgumentsOffsetWithoutFrame(op->index()));
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOperand LCodeGen::HighOperand(LOperand* op) {
750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(op->IsDoubleStackSlot());
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (NeedsEagerFrame()) {
752109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return Operand(ebp, FrameSlotToFPOffset(op->index()) + kPointerSize);
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Retrieve parameter without eager stack-frame relative to the
755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // stack-pointer.
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Operand(
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        esp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize);
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::WriteTranslation(LEnvironment* environment,
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                Translation* translation) {
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (environment == NULL) return;
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The translation includes one command per value in the environment.
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int translation_size = environment->translation_size();
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WriteTranslation(environment->outer(), translation);
770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  WriteTranslationFrame(environment, translation);
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int object_index = 0;
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int dematerialized_index = 0;
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < translation_size; ++i) {
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LOperand* value = environment->values()->at(i);
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AddToTranslation(environment,
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     translation,
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     value,
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     environment->HasTaggedValueAt(i),
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     environment->HasUint32ValueAt(i),
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     &object_index,
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     &dematerialized_index);
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::AddToTranslation(LEnvironment* environment,
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                Translation* translation,
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                LOperand* op,
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                bool is_tagged,
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                bool is_uint32,
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                int* object_index_pointer,
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                int* dematerialized_index_pointer) {
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (op == LEnvironment::materialization_marker()) {
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int object_index = (*object_index_pointer)++;
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (environment->ObjectIsDuplicateAt(object_index)) {
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int dupe_of = environment->ObjectDuplicateOfAt(object_index);
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      translation->DuplicateObject(dupe_of);
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int object_length = environment->ObjectLengthAt(object_index);
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (environment->ObjectIsArgumentsAt(object_index)) {
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      translation->BeginArgumentsObject(object_length);
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      translation->BeginCapturedObject(object_length);
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int dematerialized_index = *dematerialized_index_pointer;
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int env_offset = environment->translation_size() + dematerialized_index;
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *dematerialized_index_pointer += object_length;
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < object_length; ++i) {
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      LOperand* value = environment->values()->at(env_offset + i);
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AddToTranslation(environment,
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       translation,
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       value,
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       environment->HasTaggedValueAt(env_offset + i),
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       environment->HasUint32ValueAt(env_offset + i),
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       object_index_pointer,
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       dematerialized_index_pointer);
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (op->IsStackSlot()) {
824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int index = op->index();
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (is_tagged) {
826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      translation->StoreStackSlot(index);
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (is_uint32) {
828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      translation->StoreUint32StackSlot(index);
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      translation->StoreInt32StackSlot(index);
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (op->IsDoubleStackSlot()) {
833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int index = op->index();
834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    translation->StoreDoubleStackSlot(index);
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (op->IsRegister()) {
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register reg = ToRegister(op);
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (is_tagged) {
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      translation->StoreRegister(reg);
839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (is_uint32) {
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      translation->StoreUint32Register(reg);
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      translation->StoreInt32Register(reg);
843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (op->IsDoubleRegister()) {
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Register reg = ToX87Register(op);
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    translation->StoreDoubleRegister(reg);
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (op->IsConstantOperand()) {
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int src_index = DefineDeoptimizationLiteral(constant->handle(isolate()));
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    translation->StoreLiteral(src_index);
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::CallCodeGeneric(Handle<Code> code,
858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               RelocInfo::Mode mode,
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               LInstruction* instr,
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               SafepointMode safepoint_mode) {
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr != NULL);
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ call(code, mode);
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordSafepointWithLazyDeopt(instr, safepoint_mode);
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Signal that we don't inline smi code before these stubs in the
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // optimizing code generator.
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (code->kind() == Code::BINARY_OP_IC ||
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      code->kind() == Code::COMPARE_IC) {
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ nop();
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::CallCode(Handle<Code> code,
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        RelocInfo::Mode mode,
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        LInstruction* instr) {
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::CallRuntime(const Runtime::Function* fun, int argc,
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           LInstruction* instr, SaveFPRegsMode save_doubles) {
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr != NULL);
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->HasPointerMap());
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(fun, argc, save_doubles);
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(info()->is_calling());
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::LoadContextFromDeferred(LOperand* context) {
895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (context->IsRegister()) {
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!ToRegister(context).is(esi)) {
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(esi, ToRegister(context));
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (context->IsStackSlot()) {
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(esi, ToOperand(context));
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (context->IsConstantOperand()) {
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HConstant* constant =
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        chunk_->LookupConstant(LConstantOperand::cast(context));
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadObject(esi, Handle<Object>::cast(constant->handle(isolate())));
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       int argc,
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       LInstruction* instr,
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       LOperand* context) {
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadContextFromDeferred(context);
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntimeSaveDoubles(id);
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordSafepointWithRegisters(
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(info()->is_calling());
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::RegisterEnvironmentForDeoptimization(
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LEnvironment* environment, Safepoint::DeoptMode mode) {
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  environment->set_has_been_used();
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!environment->HasBeenRegistered()) {
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Physical stack frame layout:
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // -x ............. -4  0 ..................................... y
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // [incoming arguments] [spill slots] [pushed outgoing arguments]
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Layout of the environment:
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // 0 ..................................................... size-1
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // [parameters] [locals] [expression stack including arguments]
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Layout of the translation:
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // 0 ........................................................ size - 1 + 4
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // [expression stack including arguments] [locals] [4 words] [parameters]
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // |>------------  translation_size ------------<|
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int frame_count = 0;
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int jsframe_count = 0;
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ++frame_count;
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (e->frame_type() == JS_FUNCTION) {
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ++jsframe_count;
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Translation translation(&translations_, frame_count, jsframe_count, zone());
950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    WriteTranslation(environment, &translation);
951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int deoptimization_index = deoptimizations_.length();
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int pc_offset = masm()->pc_offset();
953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    environment->Register(deoptimization_index,
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          translation.index(),
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    deoptimizations_.Add(environment, zone());
957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
961f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                            DeoptimizeReason deopt_reason,
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Deoptimizer::BailoutType bailout_type) {
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LEnvironment* environment = instr->environment();
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(environment->HasBeenRegistered());
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int id = environment->deoptimization_index();
967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address entry =
968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (entry == NULL) {
970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kBailoutWasNotPrepared);
971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (DeoptEveryNTimes()) {
975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalReference count = ExternalReference::stress_deopt_count(isolate());
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label no_deopt;
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pushfd();
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(eax);
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(eax, Operand::StaticVariable(count));
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(eax, Immediate(1));
981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_zero, &no_deopt, Label::kNear);
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_trap_on_deopt) __ int3();
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(eax, Immediate(FLAG_deopt_every_n_times));
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(Operand::StaticVariable(count), eax);
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop(eax);
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ popfd();
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(frame_is_built_);
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Put the x87 stack layout in TOS.
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (x87_stack_.depth() > 0) EmitFlushX87ForDeopt();
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(Immediate(x87_stack_.GetLayout()));
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fild_s(MemOperand(esp, 0));
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Don't touch eflags.
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lea(esp, Operand(esp, kPointerSize));
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ call(entry, RelocInfo::RUNTIME_ENTRY);
995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&no_deopt);
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(Operand::StaticVariable(count), eax);
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop(eax);
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ popfd();
999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Put the x87 stack layout in TOS, so that we can save x87 fp registers in
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the correct location.
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (x87_stack_.depth() > 0) EmitFlushX87ForDeopt();
1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int x87_stack_layout = x87_stack_.GetLayout();
1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(Immediate(x87_stack_layout));
1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fild_s(MemOperand(esp, 0));
1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Don't touch eflags.
1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lea(esp, Operand(esp, kPointerSize));
1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info()->ShouldTrapOnDeopt()) {
1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ int3();
1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1023bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason, id);
1024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(info()->IsStub() || frame_is_built_);
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cc == no_condition && frame_is_built_) {
1027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DeoptComment(deopt_info);
1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ call(entry, RelocInfo::RUNTIME_ENTRY);
1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Deoptimizer::JumpTableEntry table_entry(entry, deopt_info, bailout_type,
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            !frame_is_built_);
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We often have several deopts to the same entry, reuse the last
1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // jump entry if this is the case.
103413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (FLAG_trace_deopt || isolate()->is_profiling() ||
1035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        jump_table_.is_empty() ||
1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        !table_entry.IsEquivalentTo(jump_table_.last())) {
1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      jump_table_.Add(table_entry, zone());
1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (cc == no_condition) {
1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&jump_table_.last().label);
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(cc, &jump_table_.last().label);
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
1048f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                            DeoptimizeReason deopt_reason) {
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Deoptimizer::BailoutType bailout_type = info()->IsStub()
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? Deoptimizer::LAZY
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Deoptimizer::EAGER;
1052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DeoptimizeIf(cc, instr, deopt_reason, bailout_type);
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::RecordSafepointWithLazyDeopt(
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LInstruction* instr, SafepointMode safepoint_mode) {
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordSafepointWithRegisters(
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->pointer_map(), 0, Safepoint::kLazyDeopt);
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::RecordSafepoint(
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LPointerMap* pointers,
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Safepoint::Kind kind,
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int arguments,
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Safepoint::DeoptMode deopt_mode) {
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kind == expected_safepoint_kind_);
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands();
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Safepoint safepoint =
1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      safepoints_.DefineSafepoint(masm(), kind, arguments, deopt_mode);
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < operands->length(); i++) {
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LOperand* pointer = operands->at(i);
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (pointer->IsStackSlot()) {
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      safepoint.DefinePointerSlot(pointer->index(), zone());
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      safepoint.DefinePointerRegister(ToRegister(pointer), zone());
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::RecordSafepoint(LPointerMap* pointers,
1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Safepoint::DeoptMode mode) {
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordSafepoint(pointers, Safepoint::kSimple, 0, mode);
1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::RecordSafepoint(Safepoint::DeoptMode mode) {
1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LPointerMap empty_pointers(zone());
1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordSafepoint(&empty_pointers, mode);
1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            int arguments,
1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            Safepoint::DeoptMode mode) {
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, mode);
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const char* LabelType(LLabel* label) {
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (label->is_loop_header()) return " (loop header)";
1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (label->is_osr_entry()) return " (OSR entry)";
1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return "";
1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLabel(LLabel* label) {
1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------",
1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          current_instruction_,
1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          label->hydrogen_value()->id(),
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          label->block_id(),
1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          LabelType(label));
1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(label->label());
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  current_block_ = label->block_id();
1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (label->block()->predecessors()->length() > 1) {
1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // A join block's x87 stack is that of its last visited predecessor.
1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If the last visited predecessor block is unreachable, the stack state
1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // will be wrong. In such case, use the x87 stack of reachable predecessor.
1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87StackMap::const_iterator it = x87_stack_map_.find(current_block_);
1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Restore x87 stack.
1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (it != x87_stack_map_.end()) {
1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      x87_stack_ = *(it->second);
1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoGap(label);
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoParallelMove(LParallelMove* move) {
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  resolver_.Resolve(move);
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoGap(LGap* gap) {
1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = LGap::FIRST_INNER_POSITION;
1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       i <= LGap::LAST_INNER_POSITION;
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       i++) {
1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LParallelMove* move = gap->GetParallelMove(inner_pos);
1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (move != NULL) DoParallelMove(move);
1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoInstructionGap(LInstructionGap* instr) {
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoGap(instr);
1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoParameter(LParameter* instr) {
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Nothing to do.
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateOsrPrologue();
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t divisor = instr->divisor();
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(dividend.is(ToRegister(instr->result())));
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Theoretically, a variation of the branch-free code for integer division by
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // a power of 2 (calculating the remainder via an additional multiplication
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (which gets simplified to an 'and') and subtraction) should be faster, and
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // indicate that positive dividends are heavily favored, so the branching
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // version performs better.
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HMod* hmod = instr->hydrogen();
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label dividend_is_not_negative, done;
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(dividend, dividend);
1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_sign, &dividend_is_not_negative, Label::kNear);
1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Note that this is correct even for kMinInt operands.
1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ neg(dividend);
1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ and_(dividend, mask);
1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ neg(dividend);
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done, Label::kNear);
1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&dividend_is_not_negative);
1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ and_(dividend, mask);
1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoModByConstI(LModByConstI* instr) {
1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t divisor = instr->divisor();
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->result()).is(eax));
1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor == 0) {
1206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(no_condition, instr, DeoptimizeReason::kDivisionByZero);
1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TruncatingDiv(dividend, Abs(divisor));
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ imul(edx, edx, Abs(divisor));
1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(eax, dividend);
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(eax, edx);
1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for negative zero.
1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HMod* hmod = instr->hydrogen();
1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label remainder_not_zero;
1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_zero, &remainder_not_zero, Label::kNear);
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(dividend, Immediate(0));
1221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(less, instr, DeoptimizeReason::kMinusZero);
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&remainder_not_zero);
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoModI(LModI* instr) {
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HMod* hmod = instr->hydrogen();
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register left_reg = ToRegister(instr->left());
1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(left_reg.is(eax));
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register right_reg = ToRegister(instr->right());
1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!right_reg.is(eax));
1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!right_reg.is(edx));
1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result_reg = ToRegister(instr->result());
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(result_reg.is(edx));
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for x % 0, idiv would signal a divide error. We have to
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // deopt in this case because we can't return a NaN.
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(right_reg, Operand(right_reg));
1243f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(zero, instr, DeoptimizeReason::kDivisionByZero);
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for kMinInt % -1, idiv would signal a divide error. We
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // have to deopt if we care about -0, because we can't return that.
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hmod->CheckFlag(HValue::kCanOverflow)) {
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label no_overflow_possible;
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(left_reg, kMinInt);
1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, &no_overflow_possible, Label::kNear);
1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(right_reg, -1);
1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(equal, instr, DeoptimizeReason::kMinusZero);
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(not_equal, &no_overflow_possible, Label::kNear);
1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Move(result_reg, Immediate(0));
1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&done, Label::kNear);
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&no_overflow_possible);
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Sign extend dividend in eax into edx:eax.
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cdq();
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If we care about -0, test if the dividend is <0 and the result is 0.
1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label positive_left;
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(left_reg, Operand(left_reg));
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_sign, &positive_left, Label::kNear);
1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ idiv(right_reg);
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(result_reg, Operand(result_reg));
1273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done, Label::kNear);
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&positive_left);
1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ idiv(right_reg);
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t divisor = instr->divisor();
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(dividend));
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (0 / -x) that will produce negative zero.
1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HDiv* hdiv = instr->hydrogen();
1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(dividend, dividend);
1293f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (kMinInt / -1).
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(dividend, kMinInt);
1298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(zero, instr, DeoptimizeReason::kOverflow);
1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Deoptimize if remainder will not be 0.
1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      divisor != 1 && divisor != -1) {
1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(dividend, Immediate(mask));
1305f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(not_zero, instr, DeoptimizeReason::kLostPrecision);
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(result, dividend);
1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t shift = WhichPowerOf2Abs(divisor);
1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (shift > 0) {
1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The arithmetic shift is always OK, the 'if' is an optimization only.
1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (shift > 1) __ sar(result, 31);
1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ shr(result, 32 - shift);
1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(result, dividend);
1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sar(result, shift);
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0) __ neg(result);
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t divisor = instr->divisor();
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->result()).is(edx));
1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor == 0) {
1326f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(no_condition, instr, DeoptimizeReason::kDivisionByZero);
1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (0 / -x) that will produce negative zero.
1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HDiv* hdiv = instr->hydrogen();
1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(dividend, dividend);
1334f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TruncatingDiv(dividend, Abs(divisor));
1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0) __ neg(edx);
1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(eax, edx);
1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ imul(eax, eax, divisor);
1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(eax, dividend);
1344f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(not_equal, instr, DeoptimizeReason::kLostPrecision);
1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDivI(LDivI* instr) {
1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HBinaryOperation* hdiv = instr->hydrogen();
1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register divisor = ToRegister(instr->divisor());
1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register remainder = ToRegister(instr->temp());
1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(dividend.is(eax));
1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(remainder.is(edx));
1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->result()).is(eax));
1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!divisor.is(eax));
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!divisor.is(edx));
1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for x / 0.
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(divisor, divisor);
1364f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(zero, instr, DeoptimizeReason::kDivisionByZero);
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (0 / -x) that will produce negative zero.
1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label dividend_not_zero;
1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(dividend, dividend);
1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_zero, &dividend_not_zero, Label::kNear);
1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(divisor, divisor);
1373f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(sign, instr, DeoptimizeReason::kMinusZero);
1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&dividend_not_zero);
1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (kMinInt / -1).
1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label dividend_not_min_int;
1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(dividend, kMinInt);
1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_zero, &dividend_not_min_int, Label::kNear);
1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(divisor, -1);
1383f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(zero, instr, DeoptimizeReason::kOverflow);
1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&dividend_not_min_int);
1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Sign extend to edx (= remainder).
1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cdq();
1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ idiv(divisor);
1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Deoptimize if remainder is not 0.
1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(remainder, remainder);
1394f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(not_zero, instr, DeoptimizeReason::kLostPrecision);
1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t divisor = instr->divisor();
1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(dividend.is(ToRegister(instr->result())));
1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the divisor is positive, things are easy: There can be no deopts and we
1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // can simply do an arithmetic right shift.
1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor == 1) return;
1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t shift = WhichPowerOf2Abs(divisor);
1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor > 1) {
1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sar(dividend, shift);
1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the divisor is negative, we have to negate and handle edge cases.
1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ neg(dividend);
1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1416f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Dividing by -1 is basically negation, unless we overflow.
1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor == -1) {
1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1422f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the negation could not overflow, simply shifting is OK.
1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sar(dividend, shift);
1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label not_kmin_int, done;
1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(no_overflow, &not_kmin_int, Label::kNear);
1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(dividend, Immediate(kMinInt / divisor));
1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done, Label::kNear);
1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&not_kmin_int);
1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sar(dividend, shift);
1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t divisor = instr->divisor();
1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->result()).is(edx));
1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor == 0) {
1449f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(no_condition, instr, DeoptimizeReason::kDivisionByZero);
1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (0 / -x) that will produce negative zero.
1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HMathFloorOfDiv* hdiv = instr->hydrogen();
1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(dividend, dividend);
1457f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Easy case: We need no dynamic check for the dividend and the flooring
1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // division is the same as the truncating division.
1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ TruncatingDiv(dividend, Abs(divisor));
1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (divisor < 0) __ neg(edx);
1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // In the general case we may need to adjust before and after the truncating
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // division to get a flooring division.
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp = ToRegister(instr->temp3());
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!temp.is(dividend) && !temp.is(eax) && !temp.is(edx));
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label needs_adjustment, done;
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(dividend, Immediate(0));
1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(divisor > 0 ? less : greater, &needs_adjustment, Label::kNear);
1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TruncatingDiv(dividend, Abs(divisor));
1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0) __ neg(edx);
1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done, Label::kNear);
1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&needs_adjustment);
1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lea(temp, Operand(dividend, divisor > 0 ? 1 : -1));
1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TruncatingDiv(temp, Abs(divisor));
1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0) __ neg(edx);
1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ dec(edx);
1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(svenpanne) Refactor this to avoid code duplication with DoDivI.
1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HBinaryOperation* hdiv = instr->hydrogen();
1491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register divisor = ToRegister(instr->divisor());
1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register remainder = ToRegister(instr->temp());
1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(dividend.is(eax));
1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(remainder.is(edx));
1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(result.is(eax));
1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!divisor.is(eax));
1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!divisor.is(edx));
1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for x / 0.
1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(divisor, divisor);
1504f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(zero, instr, DeoptimizeReason::kDivisionByZero);
1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (0 / -x) that will produce negative zero.
1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label dividend_not_zero;
1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(dividend, dividend);
1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_zero, &dividend_not_zero, Label::kNear);
1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(divisor, divisor);
1513f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(sign, instr, DeoptimizeReason::kMinusZero);
1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&dividend_not_zero);
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (kMinInt / -1).
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label dividend_not_min_int;
1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(dividend, kMinInt);
1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_zero, &dividend_not_min_int, Label::kNear);
1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(divisor, -1);
1523f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(zero, instr, DeoptimizeReason::kOverflow);
1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&dividend_not_min_int);
1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Sign extend to edx (= remainder).
1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cdq();
1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ idiv(divisor);
1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ test(remainder, remainder);
1533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(zero, &done, Label::kNear);
1534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ xor_(remainder, divisor);
1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sar(remainder, 31);
1536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(result, remainder);
1537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMulI(LMulI* instr) {
1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register left = ToRegister(instr->left());
1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* right = instr->right();
1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(ToRegister(instr->temp()), left);
1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (right->IsConstantOperand()) {
1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Try strength reductions on the multiplication.
1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // All replacement instructions are at most as long as the imul
1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // and have better latency.
1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int constant = ToInteger32(LConstantOperand::cast(right));
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (constant == -1) {
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ neg(left);
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (constant == 0) {
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ xor_(left, Operand(left));
1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (constant == 2) {
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ add(left, Operand(left));
1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (!instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // If we know that the multiplication can't overflow, it's safe to
1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // use instructions that don't set the overflow flag for the
1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // multiplication.
1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      switch (constant) {
1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 1:
1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // Do nothing.
1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 3:
1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ lea(left, Operand(left, left, times_2, 0));
1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 4:
1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ shl(left, 2);
1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 5:
1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ lea(left, Operand(left, left, times_4, 0));
1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 8:
1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ shl(left, 3);
1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 9:
1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ lea(left, Operand(left, left, times_8, 0));
1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        case 16:
1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ shl(left, 4);
1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        default:
1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ imul(left, left, constant);
1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          break;
1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ imul(left, left, constant);
1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->hydrogen()->representation().IsSmi()) {
1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ SmiUntag(left);
1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ imul(left, ToOperand(right));
1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1601f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Bail out if the result is supposed to be negative zero.
1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(left, Operand(left));
1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_zero, &done);
1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (right->IsConstantOperand()) {
1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (ToInteger32(LConstantOperand::cast(right)) < 0) {
1611f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        DeoptimizeIf(no_condition, instr, DeoptimizeReason::kMinusZero);
1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (ToInteger32(LConstantOperand::cast(right)) == 0) {
1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmp(ToRegister(instr->temp()), Immediate(0));
1614f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        DeoptimizeIf(less, instr, DeoptimizeReason::kMinusZero);
1615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Test the non-zero operand for negative sign.
1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ or_(ToRegister(instr->temp()), ToOperand(right));
1619f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(sign, instr, DeoptimizeReason::kMinusZero);
1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoBitI(LBitI* instr) {
1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* left = instr->left();
1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* right = instr->right();
1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(left->Equals(instr->result()));
1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(left->IsRegister());
1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (right->IsConstantOperand()) {
1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t right_operand =
1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ToRepresentation(LConstantOperand::cast(right),
1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         instr->hydrogen()->representation());
1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (instr->op()) {
1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::BIT_AND:
1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ and_(ToRegister(left), right_operand);
1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::BIT_OR:
1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ or_(ToRegister(left), right_operand);
1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::BIT_XOR:
1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (right_operand == int32_t(~0)) {
1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ not_(ToRegister(left));
1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ xor_(ToRegister(left), right_operand);
1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      default:
1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        UNREACHABLE();
1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (instr->op()) {
1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::BIT_AND:
1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ and_(ToRegister(left), ToOperand(right));
1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::BIT_OR:
1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ or_(ToRegister(left), ToOperand(right));
1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::BIT_XOR:
1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ xor_(ToRegister(left), ToOperand(right));
1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      default:
1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        UNREACHABLE();
1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoShiftI(LShiftI* instr) {
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* left = instr->left();
1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* right = instr->right();
1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(left->Equals(instr->result()));
1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(left->IsRegister());
1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (right->IsRegister()) {
1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(ToRegister(right).is(ecx));
1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (instr->op()) {
1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::ROR:
1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ ror_cl(ToRegister(left));
1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::SAR:
1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ sar_cl(ToRegister(left));
1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::SHR:
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ shr_cl(ToRegister(left));
1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (instr->can_deopt()) {
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ test(ToRegister(left), ToRegister(left));
1692f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          DeoptimizeIf(sign, instr, DeoptimizeReason::kNegativeValue);
1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::SHL:
1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ shl_cl(ToRegister(left));
1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      default:
1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        UNREACHABLE();
1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int value = ToInteger32(LConstantOperand::cast(right));
1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (instr->op()) {
1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::ROR:
1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (shift_count == 0 && instr->can_deopt()) {
1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ test(ToRegister(left), ToRegister(left));
1709f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          DeoptimizeIf(sign, instr, DeoptimizeReason::kNegativeValue);
1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ ror(ToRegister(left), shift_count);
1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::SAR:
1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (shift_count != 0) {
1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ sar(ToRegister(left), shift_count);
1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::SHR:
1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (shift_count != 0) {
1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ shr(ToRegister(left), shift_count);
1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (instr->can_deopt()) {
1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ test(ToRegister(left), ToRegister(left));
1724f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          DeoptimizeIf(sign, instr, DeoptimizeReason::kNegativeValue);
1725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::SHL:
1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (shift_count != 0) {
1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (instr->hydrogen_value()->representation().IsSmi() &&
1730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              instr->can_deopt()) {
1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            if (shift_count != 1) {
1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              __ shl(ToRegister(left), shift_count - 1);
1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            }
1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ SmiTag(ToRegister(left));
1735f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else {
1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ shl(ToRegister(left), shift_count);
1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          }
1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      default:
1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        UNREACHABLE();
1743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoSubI(LSubI* instr) {
1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* left = instr->left();
1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* right = instr->right();
1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(left->Equals(instr->result()));
1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (right->IsConstantOperand()) {
1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(ToOperand(left),
1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ToImmediate(right, instr->hydrogen()->representation()));
1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(ToRegister(left), ToOperand(right));
1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1761f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoConstantI(LConstantI* instr) {
1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(ToRegister(instr->result()), Immediate(instr->value()));
1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoConstantS(LConstantS* instr) {
1772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(ToRegister(instr->result()), Immediate(instr->value()));
1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoConstantD(LConstantD* instr) {
1777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint64_t const bits = instr->bits();
1778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t const lower = static_cast<uint32_t>(bits);
1779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t const upper = static_cast<uint32_t>(bits >> 32);
1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->result()->IsDoubleRegister());
1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(Immediate(upper));
1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(Immediate(lower));
1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register reg = ToX87Register(instr->result());
1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Mov(reg, Operand(esp, 0));
1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(Operand(esp), Immediate(kDoubleSize));
1787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoConstantE(LConstantE* instr) {
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value()));
1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoConstantT(LConstantT* instr) {
1796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg = ToRegister(instr->result());
1797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> object = instr->value(isolate());
1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference smi_check;
1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadObject(reg, object);
1800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOperand LCodeGen::BuildSeqStringOperand(Register string,
1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        LOperand* index,
1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        String::Encoding encoding) {
1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (index->IsConstantOperand()) {
1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int offset = ToRepresentation(LConstantOperand::cast(index),
1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Representation::Integer32());
1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (encoding == String::TWO_BYTE_ENCODING) {
1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      offset *= kUC16Size;
1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kCharSize == 1);
1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return FieldOperand(string, SeqString::kHeaderSize + offset);
1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return FieldOperand(
1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      string, ToRegister(index),
1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      encoding == String::ONE_BYTE_ENCODING ? times_1 : times_2,
1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SeqString::kHeaderSize);
1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) {
1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Encoding encoding = instr->hydrogen()->encoding();
1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register string = ToRegister(instr->string());
1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(string);
1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(string, FieldOperand(string, HeapObject::kMapOffset));
1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset));
1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ and_(string, Immediate(kStringRepresentationMask | kStringEncodingMask));
1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(string, Immediate(encoding == String::ONE_BYTE_ENCODING
1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             ? one_byte_seq_type : two_byte_seq_type));
1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(equal, kUnexpectedStringType);
1838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop(string);
1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (encoding == String::ONE_BYTE_ENCODING) {
1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movzx_b(result, operand);
1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movzx_w(result, operand);
1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
1851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Encoding encoding = instr->hydrogen()->encoding();
1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register string = ToRegister(instr->string());
1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value = ToRegister(instr->value());
1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register index = ToRegister(instr->index());
1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
1858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
1859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int encoding_mask =
1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING
1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ? one_byte_seq_type : two_byte_seq_type;
1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask);
1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->value()->IsConstantOperand()) {
1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int value = ToRepresentation(LConstantOperand::cast(instr->value()),
1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Representation::Integer32());
1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_LE(0, value);
1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (encoding == String::ONE_BYTE_ENCODING) {
1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK_LE(value, String::kMaxOneByteCharCode);
1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov_b(operand, static_cast<int8_t>(value));
1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK_LE(value, String::kMaxUtf16CodeUnit);
1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov_w(operand, static_cast<int16_t>(value));
1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value = ToRegister(instr->value());
1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (encoding == String::ONE_BYTE_ENCODING) {
1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov_b(operand, value);
1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov_w(operand, value);
1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoAddI(LAddI* instr) {
1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* left = instr->left();
1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* right = instr->right();
1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) {
1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (right->IsConstantOperand()) {
1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int32_t offset = ToRepresentation(LConstantOperand::cast(right),
1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        instr->hydrogen()->representation());
1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lea(ToRegister(instr->result()), MemOperand(ToRegister(left), offset));
1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Operand address(ToRegister(left), ToRegister(right), times_1, 0);
1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lea(ToRegister(instr->result()), address);
1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (right->IsConstantOperand()) {
1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ add(ToOperand(left),
1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             ToImmediate(right, instr->hydrogen()->representation()));
1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ add(ToRegister(left), ToOperand(right));
1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1909f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathMinMax(LMathMinMax* instr) {
1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* left = instr->left();
1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* right = instr->right();
1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(left->Equals(instr->result()));
1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HMathMinMax::Operation operation = instr->hydrogen()->operation();
1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label return_left;
1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition condition = (operation == HMathMinMax::kMathMin)
1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ? less_equal
1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : greater_equal;
1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (right->IsConstantOperand()) {
1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Operand left_op = ToOperand(left);
1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate immediate = ToImmediate(LConstantOperand::cast(instr->right()),
1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        instr->hydrogen()->representation());
1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmp(left_op, immediate);
1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(condition, &return_left, Label::kNear);
1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(left_op, immediate);
1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register left_reg = ToRegister(left);
1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Operand right_op = ToOperand(right);
1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmp(left_reg, right_op);
1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(condition, &return_left, Label::kNear);
1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(left_reg, right_op);
1938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&return_left);
1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(instr->hydrogen()->representation().IsDouble());
1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label check_nan_left, check_zero, return_left, return_right;
1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition condition = (operation == HMathMinMax::kMathMin) ? below : above;
1944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Register left_reg = ToX87Register(left);
1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Register right_reg = ToX87Register(right);
1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87PrepareBinaryOp(left_reg, right_reg, ToX87Register(instr->result()));
1948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fld(1);
1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fld(1);
1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ FCmp();
1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(parity_even, &check_nan_left, Label::kNear);  // At least one NaN.
1952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(equal, &check_zero, Label::kNear);            // left == right.
1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(condition, &return_left, Label::kNear);
1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&return_right, Label::kNear);
1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&check_zero);
1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fld(0);
1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fldz();
1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ FCmp();
1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, &return_left, Label::kNear);  // left == right != 0.
1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // At this point, both left and right are either 0 or -0.
1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (operation == HMathMinMax::kMathMin) {
1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Push st0 and st1 to stack, then pop them to temp registers and OR them,
1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // load it to left.
1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register scratch_reg = ToRegister(instr->temp());
1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fld(1);
1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fld(1);
1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ sub(esp, Immediate(2 * kPointerSize));
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fstp_s(MemOperand(esp, 0));
1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fstp_s(MemOperand(esp, kPointerSize));
1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pop(scratch_reg);
1972109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ or_(MemOperand(esp, 0), scratch_reg);
1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      X87Mov(left_reg, MemOperand(esp, 0), kX87FloatOperand);
1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pop(scratch_reg);  // restore esp
1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Since we operate on +0 and/or -0, addsd and andsd have the same effect.
1977f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Should put the result in stX0
1978f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ fadd_i(1);
1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&return_left, Label::kNear);
1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&check_nan_left);
1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fld(0);
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fld(0);
1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ FCmp();                                      // NaN check.
1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(parity_even, &return_left, Label::kNear);  // left == NaN.
1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&return_right);
1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Mov(left_reg, right_reg);
1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&return_left);
1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoArithmeticD(LArithmeticD* instr) {
1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register left = ToX87Register(instr->left());
1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register right = ToX87Register(instr->right());
1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register result = ToX87Register(instr->result());
2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->op() != Token::MOD) {
2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87PrepareBinaryOp(left, right, result);
2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set the precision control to double-precision.
2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ X87SetFPUCW(0x027F);
2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (instr->op()) {
2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::ADD:
2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fadd_i(1);
2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::SUB:
2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fsub_i(1);
2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::MUL:
2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fmul_i(1);
2014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::DIV:
2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fdiv_i(1);
2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::MOD: {
2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Pass two doubles as arguments on the stack.
2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ PrepareCallCFunction(4, eax);
2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      X87Mov(Operand(esp, 1 * kDoubleSize), right);
2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      X87Mov(Operand(esp, 0), left);
2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      X87Free(right);
2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(left.is(result));
2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      X87PrepareToWrite(result);
2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallCFunction(
2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ExternalReference::mod_two_doubles_operation(isolate()),
2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          4);
2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Return value is in st(0) on ia32.
2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      X87CommitWrite(result);
2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore the default value of control word.
2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ X87SetFPUCW(0x037F);
2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoArithmeticT(LArithmeticT* instr) {
2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(esi));
2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->left()).is(edx));
2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->right()).is(eax));
2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->result()).is(eax));
2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2050109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), instr->op()).code();
2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallCode(code, RelocInfo::CODE_TARGET, instr);
2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class InstrType>
2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitBranch(InstrType instr, Condition cc) {
2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int left_block = instr->TrueDestination(chunk_);
2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int right_block = instr->FalseDestination(chunk_);
2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int next_block = GetNextEmittedBlock();
2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (right_block == left_block || cc == no_condition) {
2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitGoto(left_block);
2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (left_block == next_block) {
2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block));
2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (right_block == next_block) {
2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(cc, chunk_->GetAssemblyLabel(left_block));
2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(cc, chunk_->GetAssemblyLabel(left_block));
2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(chunk_->GetAssemblyLabel(right_block));
2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <class InstrType>
2076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LCodeGen::EmitTrueBranch(InstrType instr, Condition cc) {
2077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int true_block = instr->TrueDestination(chunk_);
2078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (cc == no_condition) {
2079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ jmp(chunk_->GetAssemblyLabel(true_block));
2080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ j(cc, chunk_->GetAssemblyLabel(true_block));
2082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class InstrType>
2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) {
2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int false_block = instr->FalseDestination(chunk_);
2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cc == no_condition) {
2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(chunk_->GetAssemblyLabel(false_block));
2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(cc, chunk_->GetAssemblyLabel(false_block));
2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoBranch(LBranch* instr) {
2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Representation r = instr->hydrogen()->value()->representation();
2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsSmiOrInteger32()) {
2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register reg = ToRegister(instr->value());
2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(reg, Operand(reg));
2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitBranch(instr, not_zero);
2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsDouble()) {
2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Register reg = ToX87Register(instr->value());
2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87LoadForUsage(reg);
2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fldz();
2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ FCmp();
2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitBranch(instr, not_zero);
2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(r.IsTagged());
2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register reg = ToRegister(instr->value());
2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HType type = instr->hydrogen()->value()->type();
2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (type.IsBoolean()) {
2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!info()->IsStub());
2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmp(reg, factory()->true_value());
2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitBranch(instr, equal);
2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (type.IsSmi()) {
2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!info()->IsStub());
2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ test(reg, Operand(reg));
2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitBranch(instr, not_equal);
2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (type.IsJSArray()) {
2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!info()->IsStub());
2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitBranch(instr, no_condition);
2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (type.IsHeapNumber()) {
2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (type.IsString()) {
2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!info()->IsStub());
2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitBranch(instr, not_equal);
2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2131c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      ToBooleanHints expected = instr->hydrogen()->expected_input_types();
2132c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny;
2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2134c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kUndefined) {
2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // undefined -> false.
2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmp(reg, factory()->undefined_value());
2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(equal, instr->FalseLabel(chunk_));
2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2139c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kBoolean) {
2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // true -> true.
2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmp(reg, factory()->true_value());
2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(equal, instr->TrueLabel(chunk_));
2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // false -> false.
2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmp(reg, factory()->false_value());
2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(equal, instr->FalseLabel(chunk_));
2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2147c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kNull) {
2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // 'null' -> false.
2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmp(reg, factory()->null_value());
2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(equal, instr->FalseLabel(chunk_));
2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2153c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kSmallInteger) {
2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Smis: 0 -> false, all other -> true.
2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ test(reg, Operand(reg));
2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(equal, instr->FalseLabel(chunk_));
2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2158c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      } else if (expected & ToBooleanHint::kNeedsMap) {
2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // If we need a map later and have a Smi -> deopt.
2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ test(reg, Immediate(kSmiTagMask));
2161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        DeoptimizeIf(zero, instr, DeoptimizeReason::kSmi);
2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register map = no_reg;  // Keep the compiler happy.
2165c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kNeedsMap) {
2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        map = ToRegister(instr->temp());
2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!map.is(reg));
2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov(map, FieldOperand(reg, HeapObject::kMapOffset));
2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2170c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        if (expected & ToBooleanHint::kCanBeUndetectable) {
2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // Undetectable -> false.
2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ test_b(FieldOperand(map, Map::kBitFieldOffset),
21733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                    Immediate(1 << Map::kIsUndetectable));
2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ j(not_zero, instr->FalseLabel(chunk_));
2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2178c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kReceiver) {
2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // spec object -> true.
2180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ CmpInstanceType(map, FIRST_JS_RECEIVER_TYPE);
2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(above_equal, instr->TrueLabel(chunk_));
2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2184c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kString) {
2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // String value -> false iff empty.
2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label not_string;
2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(above_equal, &not_string, Label::kNear);
2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(not_zero, instr->TrueLabel(chunk_));
2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ jmp(instr->FalseLabel(chunk_));
2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ bind(&not_string);
2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2195c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kSymbol) {
2196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Symbol value -> true.
2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ CmpInstanceType(map, SYMBOL_TYPE);
2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(equal, instr->TrueLabel(chunk_));
2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2201c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kHeapNumber) {
2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // heap number -> false iff +0, -0, or NaN.
2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Label not_heap_number;
2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               factory()->heap_number_map());
2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(not_equal, &not_heap_number, Label::kNear);
2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ fldz();
2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ FCmp();
2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ j(zero, instr->FalseLabel(chunk_));
2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ jmp(instr->TrueLabel(chunk_));
2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ bind(&not_heap_number);
2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2215c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected != ToBooleanHint::kAny) {
2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // We've seen something for the first time -> deopt.
2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // This can only happen if we are not generic already.
2218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        DeoptimizeIf(no_condition, instr, DeoptimizeReason::kUnexpectedObject);
2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitGoto(int block) {
2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!IsNextEmittedBlock(block)) {
2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
2228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoClobberDoubles(LClobberDoubles* instr) {
2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoGoto(LGoto* instr) {
2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitGoto(instr->block_id());
2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition cond = no_condition;
2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (op) {
2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::EQ:
2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::EQ_STRICT:
2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cond = equal;
2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::NE:
2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::NE_STRICT:
2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cond = not_equal;
2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::LT:
2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cond = is_unsigned ? below : less;
2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::GT:
2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cond = is_unsigned ? above : greater;
2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::LTE:
2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cond = is_unsigned ? below_equal : less_equal;
2260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::GTE:
2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cond = is_unsigned ? above_equal : greater_equal;
2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::IN:
2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::INSTANCEOF:
2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return cond;
2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* left = instr->left();
2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* right = instr->right();
2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_unsigned =
2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->is_double() ||
2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->hydrogen()->left()->CheckFlag(HInstruction::kUint32) ||
2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->hydrogen()->right()->CheckFlag(HInstruction::kUint32);
2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition cc = TokenToCondition(instr->op(), is_unsigned);
2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (left->IsConstantOperand() && right->IsConstantOperand()) {
2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We can statically evaluate the comparison.
2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double left_val = ToDouble(LConstantOperand::cast(left));
2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double right_val = ToDouble(LConstantOperand::cast(right));
2286109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int next_block = Token::EvalComparison(instr->op(), left_val, right_val)
2287109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                         ? instr->TrueDestination(chunk_)
2288109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                         : instr->FalseDestination(chunk_);
2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitGoto(next_block);
2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->is_double()) {
2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      X87LoadForUsage(ToX87Register(right), ToX87Register(left));
2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ FCmp();
2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Don't base result on EFLAGS when a NaN is involved. Instead
2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // jump to the false block.
2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_even, instr->FalseLabel(chunk_));
2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (right->IsConstantOperand()) {
2299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmp(ToOperand(left),
2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               ToImmediate(right, instr->hydrogen()->representation()));
2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (left->IsConstantOperand()) {
2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmp(ToOperand(right),
2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               ToImmediate(left, instr->hydrogen()->representation()));
2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // We commuted the operands, so commute the condition.
2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        cc = CommuteCondition(cc);
2306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmp(ToRegister(left), ToOperand(right));
2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitBranch(instr, cc);
2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register left = ToRegister(instr->left());
2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->right()->IsConstantOperand()) {
2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right()));
2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CmpObject(left, right);
2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand right = ToOperand(instr->right());
2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(left, right);
2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, equal);
2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->representation().IsTagged()) {
2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register input_reg = ToRegister(instr->object());
2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(input_reg, factory()->the_hole_value());
2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitBranch(instr, equal);
2334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
2335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Put the value to the top of stack
2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register src = ToX87Register(instr->object());
2339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87LoadForUsage(src);
2340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fld(0);
2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fld(0);
2342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ FCmp();
2343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label ok;
2344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(parity_even, &ok, Label::kNear);
2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fstp(0);
2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitFalseBranch(instr, no_condition);
2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&ok);
2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(esp, Immediate(kDoubleSize));
2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fstp_d(MemOperand(esp, 0));
2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(esp, Immediate(kDoubleSize));
2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = sizeof(kHoleNanUpper32);
235513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, equal);
2357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition LCodeGen::EmitIsString(Register input,
2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register temp1,
2362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Label* is_not_string,
2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 SmiCheck check_needed = INLINE_SMI_CHECK) {
2364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (check_needed == INLINE_SMI_CHECK) {
2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input, is_not_string);
2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition cond = masm_->IsObjectStringType(input, temp1, temp1);
2369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return cond;
2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg = ToRegister(instr->value());
2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp = ToRegister(instr->temp());
2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiCheck check_needed =
2379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->hydrogen()->value()->type().IsHeapObject()
2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition true_cond = EmitIsString(
2383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reg, temp, instr->FalseLabel(chunk_), check_needed);
2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, true_cond);
2386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand input = ToOperand(instr->value());
2391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ test(input, Immediate(kSmiTagMask));
2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, zero);
2394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
2398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
2399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp = ToRegister(instr->temp());
2400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
2402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
2403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ test_b(FieldOperand(temp, Map::kBitFieldOffset),
24073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            Immediate(1 << Map::kIsUndetectable));
2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, not_zero);
2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Condition ComputeCompareCondition(Token::Value op) {
2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (op) {
2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::EQ_STRICT:
2415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::EQ:
2416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return equal;
2417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::LT:
2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return less;
2419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::GT:
2420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return greater;
2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::LTE:
2422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return less_equal;
2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::GTE:
2424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return greater_equal;
2425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    default:
2426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNREACHABLE();
2427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return no_condition;
2428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
2433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(ToRegister(instr->context()).is(esi));
2434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(ToRegister(instr->left()).is(edx));
2435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(ToRegister(instr->right()).is(eax));
2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
24373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Handle<Code> code = CodeFactory::StringCompare(isolate(), instr->op()).code();
2438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallCode(code, RelocInfo::CODE_TARGET, instr);
24393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ CompareRoot(eax, Heap::kTrueValueRootIndex);
24403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  EmitBranch(instr, equal);
2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
2445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstanceType from = instr->from();
2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstanceType to = instr->to();
2447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (from == FIRST_TYPE) return to;
2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(from == to || to == LAST_TYPE);
2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return from;
2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstanceType from = instr->from();
2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstanceType to = instr->to();
2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (from == to) return equal;
2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (to == LAST_TYPE) return above_equal;
2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (from == FIRST_TYPE) return below_equal;
2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UNREACHABLE();
2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return equal;
2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp = ToRegister(instr->temp());
2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CmpObjectType(input, TestType(instr->hydrogen()), temp);
2473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, BranchCondition(instr->hydrogen()));
2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Branches to a label or falls through with the answer in the z flag.  Trashes
2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the temp registers, but not the input.
2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitClassOfTest(Label* is_true,
2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Label* is_false,
2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Handle<String>class_name,
2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register input,
2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register temp,
2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Register temp2) {
2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input.is(temp));
2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input.is(temp2));
2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!temp.is(temp2));
2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(input, is_false);
2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
24893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ CmpObjectType(input, FIRST_FUNCTION_TYPE, temp);
24903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
2491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
24923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ j(above_equal, is_true);
2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
24943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ j(above_equal, is_false);
2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
2498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check if the constructor in the map is a function.
2499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ GetMapConstructor(temp, temp, temp2);
2500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Objects with a non-function constructor have class 'Object'.
2501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CmpInstanceType(temp2, JS_FUNCTION_TYPE);
2502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (String::Equals(class_name, isolate()->factory()->Object_string())) {
2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, is_true);
2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, is_false);
2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // temp now contains the constructor function. Grab the
2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // instance class name from there.
2510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset));
2511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(temp, FieldOperand(temp,
2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            SharedFunctionInfo::kInstanceClassNameOffset));
2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The class name we are testing against is internalized since it's a literal.
2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The name in the constructor is internalized because of the way the context
2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // is booted.  This routine isn't expected to work for random API-created
2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // classes and it doesn't have to because you can't access it with natives
2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // syntax.  Since both sides are internalized it is sufficient to use an
2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // identity comparison.
2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(temp, class_name);
2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // End with the answer in the z flag.
2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp = ToRegister(instr->temp());
2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp2 = ToRegister(instr->temp2());
2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> class_name = instr->hydrogen()->class_name();
2530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      class_name, input, temp, temp2);
2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, equal);
2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg = ToRegister(instr->value());
2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map());
2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, equal);
2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LCodeGen::DoHasInPrototypeChainAndBranch(
2546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LHasInPrototypeChainAndBranch* instr) {
2547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register const object = ToRegister(instr->object());
2548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register const object_map = ToRegister(instr->scratch());
2549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register const object_prototype = object_map;
2550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register const prototype = ToRegister(instr->prototype());
2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // The {object} must be a spec object.  It's sufficient to know that {object}
2553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // is not a smi, since all other non-spec objects have {null} prototypes and
2554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // will be ruled out below.
2555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (instr->hydrogen()->ObjectNeedsSmiCheck()) {
2556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ test(object, Immediate(kSmiTagMask));
2557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    EmitFalseBranch(instr, zero);
2558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Loop through the {object}s prototype chain looking for the {prototype}.
2561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset));
2562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label loop;
2563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&loop);
2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Deoptimize if the object needs to be access checked.
2566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ test_b(FieldOperand(object_map, Map::kBitFieldOffset),
25673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            Immediate(1 << Map::kIsAccessCheckNeeded));
2568f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(not_zero, instr, DeoptimizeReason::kAccessCheck);
2569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Deoptimize for proxies.
2570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CmpInstanceType(object_map, JS_PROXY_TYPE);
2571f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(equal, instr, DeoptimizeReason::kProxy);
2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(object_prototype, FieldOperand(object_map, Map::kPrototypeOffset));
2574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ cmp(object_prototype, factory()->null_value());
2575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitFalseBranch(instr, equal);
257613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ cmp(object_prototype, prototype);
257713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  EmitTrueBranch(instr, equal);
2578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(object_map, FieldOperand(object_prototype, HeapObject::kMapOffset));
2579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ jmp(&loop);
2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCmpT(LCmpT* instr) {
2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Token::Value op = instr->op();
2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2586109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallCode(ic, RelocInfo::CODE_TARGET, instr);
2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition condition = ComputeCompareCondition(op);
2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label true_value, done;
2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ test(eax, Operand(eax));
2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(condition, &true_value, Label::kNear);
2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ToRegister(instr->result()), factory()->false_value());
2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done, Label::kNear);
2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&true_value);
2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ToRegister(instr->result()), factory()->true_value());
2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
26003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid LCodeGen::EmitReturn(LReturn* instr) {
26013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int extra_value_count = 1;
2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->has_constant_parameter_count()) {
2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int parameter_count = ToInteger32(instr->constant_parameter_count());
2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Ret((parameter_count + extra_value_count) * kPointerSize, ecx);
2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(info()->IsStub());  // Functions would need to drop one more value.
2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register reg = ToRegister(instr->parameter_count());
2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The argument count parameter is a smi
2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiUntag(reg);
2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register return_addr_reg = reg.is(ecx) ? ebx : ecx;
2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // emit code to restore stack based on instr->parameter_count()
2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop(return_addr_reg);  // save return address
2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ shl(reg, kPointerSizeLog2);
2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(esp, reg);
2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(return_addr_reg);
2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoReturn(LReturn* instr) {
2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trace && info()->IsOptimizing()) {
2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Preserve the return value on the stack and rely on the runtime call
2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // to return the value in the same register.  We're leaving the code
2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // managed by the register allocator and tearing down the frame, it's
2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // safe to write to the context register.
2628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(eax);
2629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kTraceExit);
2631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (NeedsEagerFrame()) {
2633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(esp, ebp);
2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop(ebp);
2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
26373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  EmitReturn(instr);
2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register context = ToRegister(instr->context());
2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(result, ContextOperand(context, instr->slot_index()));
2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->RequiresHoleCheck()) {
2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(result, factory()->the_hole_value());
2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->hydrogen()->DeoptimizesOnHole()) {
2649f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label is_not_hole;
2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(not_equal, &is_not_hole, Label::kNear);
2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(result, factory()->undefined_value());
2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&is_not_hole);
2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register context = ToRegister(instr->context());
2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value = ToRegister(instr->value());
2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label skip_assignment;
2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand target = ContextOperand(context, instr->slot_index());
2667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->RequiresHoleCheck()) {
2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(target, factory()->the_hole_value());
2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->hydrogen()->DeoptimizesOnHole()) {
2670f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(not_equal, &skip_assignment, Label::kNear);
2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(target, value);
2677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->NeedsWriteBarrier()) {
2678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck check_needed =
2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->hydrogen()->value()->type().IsHeapObject()
2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp = ToRegister(instr->temp());
2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int offset = Context::SlotOffset(instr->slot_index());
2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RecordWriteContextSlot(context, offset, value, temp, kSaveFPRegs,
2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              EMIT_REMEMBERED_SET, check_needed);
2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&skip_assignment);
2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HObjectAccess access = instr->hydrogen()->access();
2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = access.offset();
2694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (access.IsExternalMemory()) {
2696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register result = ToRegister(instr->result());
2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand operand = instr->object()->IsConstantOperand()
2698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ? MemOperand::StaticVariable(ToExternalReference(
2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                LConstantOperand::cast(instr->object())))
2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : MemOperand(ToRegister(instr->object()), offset);
2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Load(result, operand, access.representation());
2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register object = ToRegister(instr->object());
2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->representation().IsDouble()) {
2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset));
2708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
2709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!access.IsInobject()) {
2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object = result;
2715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Load(result, FieldOperand(object, offset), access.representation());
2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!operand->IsDoubleRegister());
2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (operand->IsConstantOperand()) {
2723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Object> object = ToHandle(LConstantOperand::cast(operand));
2724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllowDeferredHandleDereference smi_check;
2725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (object->IsSmi()) {
2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(Handle<Smi>::cast(object));
2727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ PushHeapObject(Handle<HeapObject>::cast(object));
2729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (operand->IsRegister()) {
2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(ToRegister(operand));
2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(ToOperand(operand));
2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
2739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register function = ToRegister(instr->function());
2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp = ToRegister(instr->temp());
2741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
2742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the prototype or initial map from the function.
2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(result,
2745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that the function has a prototype or an initial map.
2748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(Operand(result), Immediate(factory()->the_hole_value()));
2749f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the function does not have an initial map, we're done.
2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CmpObjectType(result, MAP_TYPE, temp);
2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &done, Label::kNear);
2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the prototype from the initial map.
2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(result, FieldOperand(result, Map::kPrototypeOffset));
2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // All done.
2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
2761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadRoot(LLoadRoot* instr) {
2765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
2766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(result, instr->index());
2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register arguments = ToRegister(instr->arguments());
2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
2773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->length()->IsConstantOperand() &&
2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->index()->IsConstantOperand()) {
2775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
2776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
2777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int index = (const_length - const_index) + 1;
2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(result, Operand(arguments, index * kPointerSize));
2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register length = ToRegister(instr->length());
2781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand index = ToOperand(instr->index());
2782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // There are two words between the frame pointer and the last argument.
2783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Subtracting from length accounts for one of them add one more.
2784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(length, index);
2785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(result, Operand(arguments, length, times_4, kPointerSize));
2786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
2791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ElementsKind elements_kind = instr->elements_kind();
2792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* key = instr->key();
2793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!key->IsConstantOperand() &&
2794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
2795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  elements_kind)) {
2796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiUntag(ToRegister(key));
2797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand operand(BuildFastArrayOperand(
2799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->elements(),
2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      key,
2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->hydrogen()->key()->representation(),
2802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      elements_kind,
2803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->base_offset()));
2804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (elements_kind == FLOAT32_ELEMENTS) {
2805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand);
2806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (elements_kind == FLOAT64_ELEMENTS) {
2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Mov(ToX87Register(instr->result()), operand);
2808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register result(ToRegister(instr->result()));
2810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (elements_kind) {
2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case INT8_ELEMENTS:
2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movsx_b(result, operand);
2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
2814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT8_ELEMENTS:
2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT8_CLAMPED_ELEMENTS:
2816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movzx_b(result, operand);
2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case INT16_ELEMENTS:
2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movsx_w(result, operand);
2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT16_ELEMENTS:
2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movzx_w(result, operand);
2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case INT32_ELEMENTS:
2825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov(result, operand);
2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT32_ELEMENTS:
2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov(result, operand);
2829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ test(result, Operand(result));
2831f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          DeoptimizeIf(negative, instr, DeoptimizeReason::kNegativeValue);
2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
2834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FLOAT32_ELEMENTS:
2835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FLOAT64_ELEMENTS:
2836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_SMI_ELEMENTS:
2837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_ELEMENTS:
2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_DOUBLE_ELEMENTS:
2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_HOLEY_SMI_ELEMENTS:
2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_HOLEY_ELEMENTS:
2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_HOLEY_DOUBLE_ELEMENTS:
2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case DICTIONARY_ELEMENTS:
2843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
2844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
2845109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case FAST_STRING_WRAPPER_ELEMENTS:
2846109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case SLOW_STRING_WRAPPER_ELEMENTS:
2847109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case NO_ELEMENTS:
2848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        UNREACHABLE();
2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
2856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->RequiresHoleCheck()) {
2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand hole_check_operand = BuildFastArrayOperand(
2858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->elements(), instr->key(),
2859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->hydrogen()->key()->representation(),
2860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        FAST_DOUBLE_ELEMENTS,
2861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->base_offset() + sizeof(kHoleNanLower32));
2862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
2863f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand double_load_operand = BuildFastArrayOperand(
2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->elements(),
2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->key(),
2869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->hydrogen()->key()->representation(),
2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FAST_DOUBLE_ELEMENTS,
2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->base_offset());
2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Mov(ToX87Register(instr->result()), double_load_operand);
2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the result.
2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(result,
2881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         BuildFastArrayOperand(instr->elements(), instr->key(),
2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               instr->hydrogen()->key()->representation(),
2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               FAST_ELEMENTS, instr->base_offset()));
2884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for the hole value.
2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->RequiresHoleCheck()) {
2887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
2888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ test(result, Immediate(kSmiTagMask));
2889f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotASmi);
2890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmp(result, factory()->the_hole_value());
2892f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
2893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (instr->hydrogen()->hole_mode() == CONVERT_HOLE_TO_UNDEFINED) {
2895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(instr->hydrogen()->elements_kind() == FAST_HOLEY_ELEMENTS);
2896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label done;
2897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ cmp(result, factory()->the_hole_value());
2898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ j(not_equal, &done);
2899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (info()->IsStub()) {
2900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // A stub can safely convert the hole to undefined only if the array
2901c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // protector cell contains (Smi) Isolate::kProtectorValid.
2902bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      // Otherwise it needs to bail out.
2903bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      __ LoadRoot(result, Heap::kArrayProtectorRootIndex);
2904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ cmp(FieldOperand(result, PropertyCell::kValueOffset),
2905c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch             Immediate(Smi::FromInt(Isolate::kProtectorValid)));
2906f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(not_equal, instr, DeoptimizeReason::kHole);
2907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(result, isolate()->factory()->undefined_value());
2909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&done);
2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
2915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (instr->is_fixed_typed_array()) {
2916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoLoadKeyedExternalArray(instr);
2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (instr->hydrogen()->representation().IsDouble()) {
2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoLoadKeyedFixedDoubleArray(instr);
2919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoLoadKeyedFixedArray(instr);
2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOperand LCodeGen::BuildFastArrayOperand(
2926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LOperand* elements_pointer,
2927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LOperand* key,
2928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Representation key_representation,
2929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ElementsKind elements_kind,
2930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t base_offset) {
2931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register elements_pointer_reg = ToRegister(elements_pointer);
2932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int element_shift_size = ElementsKindToShiftSize(elements_kind);
2933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int shift_size = element_shift_size;
2934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (key->IsConstantOperand()) {
2935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int constant_value = ToInteger32(LConstantOperand::cast(key));
2936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (constant_value & 0xF0000000) {
2937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Abort(kArrayIndexConstantValueTooBig);
2938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Operand(elements_pointer_reg,
2940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   ((constant_value) << shift_size)
2941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       + base_offset);
2942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Take the tag bit into account while computing the shift size.
2944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (key_representation.IsSmi() && (shift_size >= 1)) {
2945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shift_size -= kSmiTagSize;
2946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
2948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Operand(elements_pointer_reg,
2949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   ToRegister(key),
2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   scale_factor,
2951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   base_offset);
2952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
2957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
2958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->from_inlined()) {
2960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lea(result, Operand(esp, -2 * kPointerSize));
29613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else if (instr->hydrogen()->arguments_adaptor()) {
2962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check for arguments adapter frame.
2963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done, adapted;
2964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
29653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ mov(result,
29663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch           Operand(result, CommonFrameConstants::kContextOrFrameTypeOffset));
2967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(Operand(result),
2968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(equal, &adapted, Label::kNear);
2970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // No arguments adaptor frame.
2972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(result, Operand(ebp));
2973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done, Label::kNear);
2974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Arguments adaptor frame present.
2976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&adapted);
2977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Result is the frame pointer for the frame if not adapted and for the real
2980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // frame below the adaptor frame if adapted.
2981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
29823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
29833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ mov(result, Operand(ebp));
2984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
2989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand elem = ToOperand(instr->elements());
2990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
2991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
2993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If no arguments adaptor frame the number of arguments is fixed.
2995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(ebp, elem);
2996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(result, Immediate(scope()->num_parameters()));
2997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &done, Label::kNear);
2998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Arguments adaptor frame present. Get argument length from there.
3000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(result, Operand(result,
3002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         ArgumentsAdaptorFrameConstants::kLengthOffset));
3003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiUntag(result);
3004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Argument length is in result register.
3006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
3007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
3011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register receiver = ToRegister(instr->receiver());
3012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register function = ToRegister(instr->function());
3013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the receiver is null or undefined, we have to pass the global
3015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // object as a receiver to normal functions. Values have to be
3016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // passed unchanged to builtins and strict-mode functions.
3017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label receiver_ok, global_object;
301862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label::Distance dist;
301962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
302062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // For x87 debug version jitted code's size exceeds 128 bytes whether
302162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // FLAG_deopt_every_n_times
302262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // is set or not. Always use Label:kFar for label distance for debug mode.
302362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (FLAG_debug_code)
302462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    dist = Label::kFar;
302562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  else
302662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
302762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
3028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = ToRegister(instr->temp());
3029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!instr->hydrogen()->known_function()) {
3031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Do not transform the receiver to object for strict mode
3032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // functions.
3033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(scratch,
3034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
3035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset),
30363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch              Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
30373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ j(not_equal, &receiver_ok, dist);
3038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Do not transform the receiver to object for builtins.
3040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
30413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch              Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
30423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ j(not_equal, &receiver_ok, dist);
3043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Normal function. Replace undefined or null with global receiver.
3046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(receiver, factory()->null_value());
304762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ j(equal, &global_object, dist);
3048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(receiver, factory()->undefined_value());
304962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ j(equal, &global_object, dist);
3050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The receiver should be a JS object.
3052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ test(receiver, Immediate(kSmiTagMask));
3053f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(equal, instr, DeoptimizeReason::kSmi);
3054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CmpObjectType(receiver, FIRST_JS_RECEIVER_TYPE, scratch);
3055f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(below, instr, DeoptimizeReason::kNotAJavaScriptObject);
3056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
305762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ jmp(&receiver_ok, dist);
3058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&global_object);
3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset));
3060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(receiver, ContextOperand(receiver, Context::NATIVE_CONTEXT_INDEX));
3061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_PROXY_INDEX));
3062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&receiver_ok);
3063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoApplyArguments(LApplyArguments* instr) {
3067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register receiver = ToRegister(instr->receiver());
3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register function = ToRegister(instr->function());
3069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register length = ToRegister(instr->length());
3070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register elements = ToRegister(instr->elements());
3071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(receiver.is(eax));  // Used for parameter count.
3072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(function.is(edi));  // Required by InvokeFunction.
3073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->result()).is(eax));
3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy the arguments to this function possibly from the
3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // adaptor frame below it.
3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const uint32_t kArgumentsLimit = 1 * KB;
3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(length, kArgumentsLimit);
3079f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(above, instr, DeoptimizeReason::kTooManyArguments);
3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(receiver);
3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(receiver, length);
3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Loop through the arguments pushing them onto the execution
3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // stack.
3086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label invoke, loop;
3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // length is a small non-negative integer, due to the test above.
3088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ test(length, Operand(length));
3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(zero, &invoke, Label::kNear);
3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&loop);
3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
3092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ dec(length);
3093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_zero, &loop);
3094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Invoke the function.
3096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&invoke);
30973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
30983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  InvokeFlag flag = CALL_FUNCTION;
30993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (instr->hydrogen()->tail_call_mode() == TailCallMode::kAllow) {
31003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!info()->saves_caller_doubles());
31013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // TODO(ishell): drop current frame before pushing arguments to the stack.
31023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    flag = JUMP_FUNCTION;
31033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ParameterCount actual(eax);
31043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // It is safe to use ebx, ecx and edx as scratch registers here given that
31053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // 1) we are not going to return to caller function anyway,
31063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // 2) ebx (expected arguments count) and edx (new.target) will be
31073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    //    initialized below.
31083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    PrepareForTailCall(actual, ebx, ecx, edx);
31093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
31103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->HasPointerMap());
3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LPointerMap* pointers = instr->pointer_map();
31133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt);
3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ParameterCount actual(eax);
31153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ InvokeFunction(function, no_reg, actual, flag, safepoint_generator);
3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDebugBreak(LDebugBreak* instr) {
3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ int3();
3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoPushArgument(LPushArgument* instr) {
3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* argument = instr->value();
3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitPushTaggedOperand(argument);
3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDrop(LDrop* instr) {
3131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Drop(instr->count());
3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoThisFunction(LThisFunction* instr) {
3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(result, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoContext(LContext* instr) {
3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
3143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info()->IsOptimizing()) {
3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If there is no frame, the context must be in esi.
3147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(result.is(esi));
3148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
3153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(esi));
315462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ push(Immediate(instr->hydrogen()->declarations()));
3155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags())));
3156f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ push(Immediate(instr->hydrogen()->feedback_vector()));
3157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallRuntime(Runtime::kDeclareGlobals, instr);
3158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::CallKnownFunction(Handle<JSFunction> function,
3161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 int formal_parameter_count, int arity,
31623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                 bool is_tail_call, LInstruction* instr) {
3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool dont_adapt_arguments =
3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool can_invoke_directly =
3166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      dont_adapt_arguments || formal_parameter_count == arity;
3167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register function_reg = edi;
3169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (can_invoke_directly) {
3171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Change context.
3172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(esi, FieldOperand(function_reg, JSFunction::kContextOffset));
3173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Always initialize new target and number of actual arguments.
3175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(edx, factory()->undefined_value());
3176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(eax, arity);
3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
31783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    bool is_self_call = function.is_identical_to(info()->closure());
31793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Invoke function directly.
31813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (is_self_call) {
31823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Handle<Code> self(reinterpret_cast<Code**>(__ CodeObject().location()));
31833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (is_tail_call) {
31843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        __ Jump(self, RelocInfo::CODE_TARGET);
31853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else {
31863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        __ Call(self, RelocInfo::CODE_TARGET);
31873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
3188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
31893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Operand target = FieldOperand(function_reg, JSFunction::kCodeEntryOffset);
31903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (is_tail_call) {
31913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        __ jmp(target);
31923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else {
31933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        __ call(target);
31943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
31953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
31963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
31973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (!is_tail_call) {
31983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      // Set up deoptimization.
31993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We need to adapt arguments.
3203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LPointerMap* pointers = instr->pointer_map();
3204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SafepointGenerator generator(
3205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        this, pointers, Safepoint::kLazyDeopt);
32063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ParameterCount actual(arity);
3207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ParameterCount expected(formal_parameter_count);
32083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION;
32093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ InvokeFunction(function_reg, expected, actual, flag, generator);
3210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
3211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
3215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->result()).is(eax));
3216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (instr->hydrogen()->IsTailCall()) {
3218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (NeedsEagerFrame()) __ leave();
3219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (instr->target()->IsConstantOperand()) {
3221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      LConstantOperand* target = LConstantOperand::cast(instr->target());
3222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Handle<Code> code = Handle<Code>::cast(ToHandle(target));
3223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ jmp(code, RelocInfo::CODE_TARGET);
3224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
3225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(instr->target()->IsRegister());
3226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Register target = ToRegister(instr->target());
3227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ add(target, Immediate(Code::kHeaderSize - kHeapObjectTag));
3228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ jmp(target);
3229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
3230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    LPointerMap* pointers = instr->pointer_map();
3232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (instr->target()->IsConstantOperand()) {
3235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      LConstantOperand* target = LConstantOperand::cast(instr->target());
3236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Handle<Code> code = Handle<Code>::cast(ToHandle(target));
3237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET));
3238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ call(code, RelocInfo::CODE_TARGET);
3239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
3240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(instr->target()->IsRegister());
3241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Register target = ToRegister(instr->target());
3242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      generator.BeforeCall(__ CallSize(Operand(target)));
3243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ add(target, Immediate(Code::kHeaderSize - kHeapObjectTag));
3244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ call(target);
3245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
3246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    generator.AfterCall();
3247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input_reg = ToRegister(instr->value());
3253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
3254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         factory()->heap_number_map());
3255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumber);
3256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label slow, allocated, done;
3258bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  uint32_t available_regs = eax.bit() | ecx.bit() | edx.bit() | ebx.bit();
3259bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  available_regs &= ~input_reg.bit();
3260bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (instr->context()->IsRegister()) {
3261bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Make sure that the context isn't overwritten in the AllocateHeapNumber
3262bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // macro below.
3263bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    available_regs &= ~ToRegister(instr->context()).bit();
3264bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
3265bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
3266bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register tmp =
3267bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      Register::from_code(base::bits::CountTrailingZeros32(available_regs));
3268bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  available_regs &= ~tmp.bit();
3269bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register tmp2 =
3270bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      Register::from_code(base::bits::CountTrailingZeros32(available_regs));
3271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Preserve the value of all registers.
3273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushSafepointRegistersScope scope(this);
3274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check the sign of the argument. If the argument is positive, just
3277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // return it. We do not need to patch the stack since |input| and
3278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // |result| are the same register and |input| will be restored
3279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // unchanged by popping safepoint registers.
3280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ test(tmp, Immediate(HeapNumber::kSignMask));
3281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(zero, &done, Label::kNear);
3282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow);
3284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&allocated, Label::kNear);
3285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Slow case: Call the runtime system to do the number allocation.
3287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&slow);
3288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0,
3289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          instr, instr->context());
3290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set the pointer to the new heap number in tmp.
3291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!tmp.is(eax)) __ mov(tmp, eax);
3292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore input_reg after call to runtime.
3293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadFromSafepointRegisterSlot(input_reg, input_reg);
3294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&allocated);
3296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ and_(tmp2, ~HeapNumber::kSignMask);
3298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2);
3299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
3300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2);
3301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ StoreToSafepointRegisterSlot(input_reg, tmp);
3302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
3304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input_reg = ToRegister(instr->value());
3309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ test(input_reg, Operand(input_reg));
3310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label is_positive;
3311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_sign, &is_positive, Label::kNear);
3312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ neg(input_reg);  // Sets flags.
3313f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(negative, instr, DeoptimizeReason::kOverflow);
3314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&is_positive);
3315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathAbs(LMathAbs* instr) {
3319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Class for deferred case.
3320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredMathAbsTaggedHeapNumber final : public LDeferredCode {
3321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
3322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
3323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    LMathAbs* instr,
3324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    const X87Stack& x87_stack)
3325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
3326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override {
3327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
3328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
3330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
3332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LMathAbs* instr_;
3333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
3334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->value()->Equals(instr->result()));
3336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Representation r = instr->hydrogen()->value()->representation();
3337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsDouble()) {
3339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Register value = ToX87Register(instr->value());
3340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Fxch(value);
3341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fabs();
3342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsSmiOrInteger32()) {
3343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitIntegerMathAbs(instr);
3344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {  // Tagged case.
3345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredMathAbsTaggedHeapNumber* deferred =
3346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr, x87_stack_);
3347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register input_reg = ToRegister(instr->value());
3348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Smi check.
3349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfNotSmi(input_reg, deferred->entry());
3350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitIntegerMathAbs(instr);
3351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(deferred->exit());
3352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathFloor(LMathFloor* instr) {
3357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register output_reg = ToRegister(instr->result());
3358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register input_reg = ToX87Register(instr->value());
3359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Fxch(input_reg);
3360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label not_minus_zero, done;
3362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Deoptimize on unordered.
3363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fldz();
3364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fld(1);
3365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ FCmp();
3366f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(parity_even, instr, DeoptimizeReason::kNaN);
3367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(below, &not_minus_zero, Label::kNear);
3368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check for negative zero.
3371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, &not_minus_zero, Label::kNear);
3372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // +- 0.0.
3373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fld(0);
3374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ FXamSign();
3375f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(not_zero, instr, DeoptimizeReason::kMinusZero);
3376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(output_reg, Immediate(0));
3377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done, Label::kFar);
3378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Positive input.
3381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rc=01B, round down.
3382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&not_minus_zero);
3383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fnclex();
3384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ X87SetRC(0x0400);
3385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(esp, Immediate(kPointerSize));
3386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fist_s(Operand(esp, 0));
3387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(output_reg);
33883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ X87SetRC(0x0000);
3389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ X87CheckIA();
3390f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(equal, instr, DeoptimizeReason::kOverflow);
3391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fnclex();
3392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ X87SetRC(0x0000);
3393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
3394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathRound(LMathRound* instr) {
3398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register input_reg = ToX87Register(instr->value());
3399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
3400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Fxch(input_reg);
3401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label below_one_half, below_minus_one_half, done;
3402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference one_half = ExternalReference::address_of_one_half();
3404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference minus_one_half =
3405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_minus_one_half();
3406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fld_d(Operand::StaticVariable(one_half));
3408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fld(1);
3409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ FCmp();
3410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(carry, &below_one_half);
3411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Use rounds towards zero, since 0.5 <= x, we use floor(0.5 + x)
3413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fld(0);
3414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fadd_d(Operand::StaticVariable(one_half));
3415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rc=11B, round toward zero.
3416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ X87SetRC(0x0c00);
3417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(esp, Immediate(kPointerSize));
3418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clear exception bits.
3419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fnclex();
3420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fistp_s(MemOperand(esp, 0));
34213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Restore round mode.
34223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ X87SetRC(0x0000);
3423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check overflow.
3424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ X87CheckIA();
3425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(result);
3426f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(equal, instr, DeoptimizeReason::kConversionOverflow);
3427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fnclex();
3428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore round mode.
3429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ X87SetRC(0x0000);
3430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done);
3431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&below_one_half);
3433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fld_d(Operand::StaticVariable(minus_one_half));
3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fld(1);
3435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ FCmp();
3436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(carry, &below_minus_one_half);
3437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
3438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // we can ignore the difference between a result of -0 and +0.
3439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If the sign is positive, we return +0.
3441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fld(0);
3442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ FXamSign();
3443f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(not_zero, instr, DeoptimizeReason::kMinusZero);
3444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(result, Immediate(0));
3446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done);
3447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&below_minus_one_half);
3449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fld(0);
3450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fadd_d(Operand::StaticVariable(one_half));
3451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rc=01B, round down.
3452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ X87SetRC(0x0400);
3453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(esp, Immediate(kPointerSize));
3454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clear exception bits.
3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fnclex();
3456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fistp_s(MemOperand(esp, 0));
34573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Restore round mode.
34583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ X87SetRC(0x0000);
3459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check overflow.
3460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ X87CheckIA();
3461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(result);
3462f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(equal, instr, DeoptimizeReason::kConversionOverflow);
3463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fnclex();
3464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore round mode.
3465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ X87SetRC(0x0000);
3466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
3468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathFround(LMathFround* instr) {
3472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register input_reg = ToX87Register(instr->value());
3473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Fxch(input_reg);
3474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(esp, Immediate(kPointerSize));
3475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fstp_s(MemOperand(esp, 0));
3476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Fld(MemOperand(esp, 0), kX87FloatOperand);
3477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(esp, Immediate(kPointerSize));
3478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathSqrt(LMathSqrt* instr) {
3482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  X87Register input_reg = ToX87Register(instr->value());
3483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ X87SetFPUCW(0x027F);
3484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  X87Fxch(input_reg);
3485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ fsqrt();
3486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ X87SetFPUCW(0x037F);
3487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
3491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register input_reg = ToX87Register(instr->value());
3492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToX87Register(instr->result()).is(input_reg));
3493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Fxch(input_reg);
3494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Note that according to ECMA-262 15.8.2.13:
3495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Math.pow(-Infinity, 0.5) == Infinity
3496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Math.sqrt(-Infinity) == NaN
3497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, sqrt;
3498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check base for -Infinity. C3 == 0, C2 == 1, C1 == 1 and C0 == 1
3499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fxam();
3500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(eax);
3501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fnstsw_ax();
3502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ and_(eax, Immediate(0x4700));
3503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(eax, Immediate(0x0700));
3504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &sqrt, Label::kNear);
3505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If input is -Infinity, return Infinity.
3506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fchs();
3507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done, Label::kNear);
3508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Square root.
3510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&sqrt);
3511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fldz();
3512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ faddp();  // Convert -0 to +0.
3513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fsqrt();
3514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
3515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(eax);
3516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoPower(LPower* instr) {
3520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Representation exponent_type = instr->hydrogen()->right()->representation();
3521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register result = ToX87Register(instr->result());
3522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Having marked this as a call, we can use any registers.
3523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register base = ToX87Register(instr->left());
3524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference one_half = ExternalReference::address_of_one_half();
3525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (exponent_type.IsSmi()) {
3527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register exponent = ToRegister(instr->right());
3528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87LoadForUsage(base);
3529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiUntag(exponent);
3530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(exponent);
3531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fild_s(MemOperand(esp, 0));
3532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop(exponent);
3533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (exponent_type.IsTagged()) {
3534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register exponent = ToRegister(instr->right());
3535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp = exponent.is(ecx) ? eax : ecx;
3536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label no_deopt, done;
3537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87LoadForUsage(base);
3538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(exponent, &no_deopt);
3539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, temp);
3540f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumber);
3541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Heap number(double)
3542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fld_d(FieldOperand(exponent, HeapNumber::kValueOffset));
3543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done);
3544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // SMI
3545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&no_deopt);
3546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiUntag(exponent);
3547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(exponent);
3548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fild_s(MemOperand(esp, 0));
3549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop(exponent);
3550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
3551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (exponent_type.IsInteger32()) {
3552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register exponent = ToRegister(instr->right());
3553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87LoadForUsage(base);
3554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(exponent);
3555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fild_s(MemOperand(esp, 0));
3556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop(exponent);
3557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(exponent_type.IsDouble());
3559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Register exponent_double = ToX87Register(instr->right());
3560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87LoadForUsage(base, exponent_double);
3561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // FP data stack {base, exponent(TOS)}.
3564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Handle (exponent==+-0.5 && base == -0).
3565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label not_plus_0;
3566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fld(0);
3567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fabs();
3568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Fld(Operand::StaticVariable(one_half), kX87DoubleOperand);
3569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ FCmp();
3570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(parity_even, &not_plus_0, Label::kNear);  // NaN.
3571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &not_plus_0, Label::kNear);
3572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fldz();
3573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // FP data stack {base, exponent(TOS), zero}.
3574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ faddp(2);
3575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&not_plus_0);
3576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
3578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ PrepareCallCFunction(4, eax);
3579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fstp_d(MemOperand(esp, kDoubleSize));  // Exponent value.
3580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fstp_d(MemOperand(esp, 0));            // Base value.
3581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87PrepareToWrite(result);
3582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallCFunction(ExternalReference::power_double_double_function(isolate()),
3583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     4);
3584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Return value is in st(0) on ia32.
3585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87CommitWrite(result);
3586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathLog(LMathLog* instr) {
3591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->value()->Equals(instr->result()));
359213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87Register result = ToX87Register(instr->result());
3593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register input_reg = ToX87Register(instr->value());
3594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Fxch(input_reg);
3595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
359613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Pass one double as argument on the stack.
359713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ PrepareCallCFunction(2, eax);
359813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ fstp_d(MemOperand(esp, 0));
359913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87PrepareToWrite(result);
360013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 2);
360113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Return value is in st(0) on ia32.
360213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87CommitWrite(result);
3603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathClz32(LMathClz32* instr) {
3607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
3608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
3609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Lzcnt(result, input);
3611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
361313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid LCodeGen::DoMathCos(LMathCos* instr) {
361413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87Register result = ToX87Register(instr->result());
361513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87Register input_reg = ToX87Register(instr->value());
361613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ fld(x87_stack_.st(input_reg));
3617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
361813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Pass one double as argument on the stack.
361913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ PrepareCallCFunction(2, eax);
362013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ fstp_d(MemOperand(esp, 0));
362113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87PrepareToWrite(result);
3622f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  __ X87SetFPUCW(0x027F);
362313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 2);
3624f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  __ X87SetFPUCW(0x037F);
362513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Return value is in st(0) on ia32.
362613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87CommitWrite(result);
362713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
3628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
362913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid LCodeGen::DoMathSin(LMathSin* instr) {
363013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87Register result = ToX87Register(instr->result());
363113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87Register input_reg = ToX87Register(instr->value());
363213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ fld(x87_stack_.st(input_reg));
3633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
363413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Pass one double as argument on the stack.
363513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ PrepareCallCFunction(2, eax);
363613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ fstp_d(MemOperand(esp, 0));
363713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87PrepareToWrite(result);
3638f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  __ X87SetFPUCW(0x027F);
363913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 2);
3640f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  __ X87SetFPUCW(0x037F);
364113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Return value is in st(0) on ia32.
364213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87CommitWrite(result);
364313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
3644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
364513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid LCodeGen::DoMathExp(LMathExp* instr) {
364613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87Register result = ToX87Register(instr->result());
364713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87Register input_reg = ToX87Register(instr->value());
364813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ fld(x87_stack_.st(input_reg));
3649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
365013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Pass one double as argument on the stack.
365113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ PrepareCallCFunction(2, eax);
365213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ fstp_d(MemOperand(esp, 0));
365313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87PrepareToWrite(result);
365413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 2);
365513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Return value is in st(0) on ia32.
365613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  X87CommitWrite(result);
3657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid LCodeGen::PrepareForTailCall(const ParameterCount& actual,
36603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                  Register scratch1, Register scratch2,
36613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                  Register scratch3) {
36623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#if DEBUG
36633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (actual.is_reg()) {
36643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(actual.reg(), scratch1, scratch2, scratch3));
3665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
36663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(scratch1, scratch2, scratch3));
3667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
36683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif
36693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (FLAG_code_comments) {
36703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (actual.is_reg()) {
367113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Comment(";;; PrepareForTailCall, actual: %s {",
367213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch              RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
367313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                  actual.reg().code()));
36743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
36753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
36763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
36773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
36783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
36793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Check if next frame is an arguments adaptor frame.
36803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register caller_args_count_reg = scratch1;
36813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label no_arguments_adaptor, formal_parameter_count_loaded;
36823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ mov(scratch2, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
36833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ cmp(Operand(scratch2, StandardFrameConstants::kContextOffset),
36843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
36853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ j(not_equal, &no_arguments_adaptor, Label::kNear);
3686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Drop current frame and load arguments count from arguments adaptor frame.
36883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ mov(ebp, scratch2);
36893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ mov(caller_args_count_reg,
36903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset));
36913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ SmiUntag(caller_args_count_reg);
36923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ jmp(&formal_parameter_count_loaded, Label::kNear);
3693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ bind(&no_arguments_adaptor);
36953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Load caller's formal parameter count.
36963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ mov(caller_args_count_reg,
36973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         Immediate(info()->literal()->parameter_count()));
36983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
36993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ bind(&formal_parameter_count_loaded);
37003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ PrepareForTailCall(actual, caller_args_count_reg, scratch2, scratch3,
37013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                        ReturnAddressState::kNotOnStack, 0);
37023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Comment(";;; }");
37033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
37043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
37053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
37063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HInvokeFunction* hinstr = instr->hydrogen();
3707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(esi));
3708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->function()).is(edi));
37093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  DCHECK(instr->HasPointerMap());
3710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
37113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bool is_tail_call = hinstr->tail_call_mode() == TailCallMode::kAllow;
3712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
37133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (is_tail_call) {
37143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!info()->saves_caller_doubles());
37153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ParameterCount actual(instr->arity());
37163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // It is safe to use ebx, ecx and edx as scratch registers here given that
37173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // 1) we are not going to return to caller function anyway,
37183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // 2) ebx (expected arguments count) and edx (new.target) will be
37193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    //    initialized below.
37203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    PrepareForTailCall(actual, ebx, ecx, edx);
37213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
3722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
37233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Handle<JSFunction> known_function = hinstr->known_function();
37243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (known_function.is_null()) {
37253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    LPointerMap* pointers = instr->pointer_map();
37263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
37273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ParameterCount actual(instr->arity());
37283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION;
37293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ InvokeFunction(edi, no_reg, actual, flag, generator);
3730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
37313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    CallKnownFunction(known_function, hinstr->formal_parameter_count(),
37323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                      instr->arity(), is_tail_call, instr);
3733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCallNewArray(LCallNewArray* instr) {
3738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(esi));
3739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->constructor()).is(edi));
3740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->result()).is(eax));
3741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(eax, Immediate(instr->arity()));
374313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ mov(ebx, instr->hydrogen()->site());
3744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ElementsKind kind = instr->hydrogen()->elements_kind();
3746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSiteOverrideMode override_mode =
3747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
3748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ? DISABLE_ALLOCATION_SITES
3749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          : DONT_OVERRIDE;
3750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->arity() == 0) {
3752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ArrayNoArgumentConstructorStub stub(isolate(), kind, override_mode);
3753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (instr->arity() == 1) {
3755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
3756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsFastPackedElementsKind(kind)) {
3757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label packed_case;
3758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // We might need a change here
3759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // look at the first argument
3760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(ecx, Operand(esp, 0));
3761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ test(ecx, ecx);
3762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(zero, &packed_case, Label::kNear);
3763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ElementsKind holey_kind = GetHoleyElementsKind(kind);
3765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ArraySingleArgumentConstructorStub stub(isolate(),
3766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              holey_kind,
3767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              override_mode);
3768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&done, Label::kNear);
3770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&packed_case);
3771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode);
3774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
3776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
377713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ArrayNArgumentsConstructorStub stub(isolate());
3778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCallRuntime(LCallRuntime* instr) {
3784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(esi));
3785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles());
3786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
3790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register function = ToRegister(instr->function());
3791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register code_object = ToRegister(instr->code_object());
3792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize));
3793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object);
3794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
3798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
3799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register base = ToRegister(instr->base_object());
3800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->offset()->IsConstantOperand()) {
3801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LConstantOperand* offset = LConstantOperand::cast(instr->offset());
3802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lea(result, Operand(base, ToInteger32(offset)));
3803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register offset = ToRegister(instr->offset());
3805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lea(result, Operand(base, offset, times_1, 0));
3806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
3811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Representation representation = instr->hydrogen()->field_representation();
3812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HObjectAccess access = instr->hydrogen()->access();
3814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = access.offset();
3815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (access.IsExternalMemory()) {
3817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
3818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand operand = instr->object()->IsConstantOperand()
3819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ? MemOperand::StaticVariable(
3820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            ToExternalReference(LConstantOperand::cast(instr->object())))
3821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : MemOperand(ToRegister(instr->object()), offset);
3822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->value()->IsConstantOperand()) {
3823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
3824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(operand, Immediate(ToInteger32(operand_value)));
3825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
3826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register value = ToRegister(instr->value());
3827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Store(value, operand, representation);
3828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
3830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register object = ToRegister(instr->object());
3833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AssertNotSmi(object);
3834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!representation.IsSmi() ||
3835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         !instr->value()->IsConstantOperand() ||
3836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         IsSmi(LConstantOperand::cast(instr->value())));
3837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (representation.IsDouble()) {
3838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(access.IsInobject());
3839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!instr->hydrogen()->has_transition());
3840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
3841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Register value = ToX87Register(instr->value());
3842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Mov(FieldOperand(object, offset), value);
3843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
3844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->has_transition()) {
3847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> transition = instr->hydrogen()->transition_map();
3848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AddDeprecationDependency(transition);
3849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(FieldOperand(object, HeapObject::kMapOffset), transition);
3850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
3851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register temp = ToRegister(instr->temp());
3852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register temp_map = ToRegister(instr->temp_map());
3853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(temp_map, transition);
3854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map);
3855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Update the write barrier for the map field.
3856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ RecordWriteForMap(object, transition, temp_map, temp, kSaveFPRegs);
3857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Do the store.
3861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register write_register = object;
3862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!access.IsInobject()) {
3863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    write_register = ToRegister(instr->temp());
3864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset));
3865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemOperand operand = FieldOperand(write_register, offset);
3868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->value()->IsConstantOperand()) {
3869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
3870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (operand_value->IsRegister()) {
3871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register value = ToRegister(operand_value);
3872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Store(value, operand, representation);
3873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (representation.IsInteger32() || representation.IsExternal()) {
3874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate immediate = ToImmediate(operand_value, representation);
3875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
3876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(operand, immediate);
3877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
3878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Object> handle_value = ToHandle(operand_value);
3879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
3880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(operand, handle_value);
3881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value = ToRegister(instr->value());
3884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Store(value, operand, representation);
3885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->NeedsWriteBarrier()) {
3888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value = ToRegister(instr->value());
3889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object;
3890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Update the write barrier for the object for in-object properties.
3891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RecordWriteField(write_register, offset, value, temp, kSaveFPRegs,
3892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        EMIT_REMEMBERED_SET,
3893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        instr->hydrogen()->SmiCheckForWriteBarrier(),
3894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        instr->hydrogen()->PointersToHereCheckForValue());
3895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
3900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition cc = instr->hydrogen()->allow_equality() ? above : above_equal;
3901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->index()->IsConstantOperand()) {
3902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(ToOperand(instr->length()),
3903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ToImmediate(LConstantOperand::cast(instr->index()),
3904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       instr->hydrogen()->length()->representation()));
3905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cc = CommuteCondition(cc);
3906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (instr->length()->IsConstantOperand()) {
3907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(ToOperand(instr->index()),
3908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ToImmediate(LConstantOperand::cast(instr->length()),
3909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       instr->hydrogen()->index()->representation()));
3910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
3912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
3914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
3915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(NegateCondition(cc), &done, Label::kNear);
3916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ int3();
3917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
3918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3919f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(cc, instr, DeoptimizeReason::kOutOfBounds);
3920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
3925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ElementsKind elements_kind = instr->elements_kind();
3926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* key = instr->key();
3927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!key->IsConstantOperand() &&
3928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
3929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  elements_kind)) {
3930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiUntag(ToRegister(key));
3931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand operand(BuildFastArrayOperand(
3933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->elements(),
3934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      key,
3935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->hydrogen()->key()->representation(),
3936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      elements_kind,
3937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->base_offset()));
3938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (elements_kind == FLOAT32_ELEMENTS) {
3939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Mov(operand, ToX87Register(instr->value()), kX87FloatOperand);
3940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (elements_kind == FLOAT64_ELEMENTS) {
3941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    uint64_t int_val = kHoleNanInt64;
3942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int32_t lower = static_cast<int32_t>(int_val);
3943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
3944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Operand operand2 = BuildFastArrayOperand(
3945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        instr->elements(), instr->key(),
3946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        instr->hydrogen()->key()->representation(), elements_kind,
3947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        instr->base_offset() + kPointerSize);
3948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label no_special_nan_handling, done;
3950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    X87Register value = ToX87Register(instr->value());
3951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    X87Fxch(value);
3952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ lea(esp, Operand(esp, -kDoubleSize));
3953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ fst_d(MemOperand(esp, 0));
3954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ lea(esp, Operand(esp, kDoubleSize));
3955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int offset = sizeof(kHoleNanUpper32);
395613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
3957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ j(not_equal, &no_special_nan_handling, Label::kNear);
3958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(operand, Immediate(lower));
3959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(operand2, Immediate(upper));
3960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ jmp(&done, Label::kNear);
3961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&no_special_nan_handling);
3963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ fst_d(operand);
3964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&done);
3965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value = ToRegister(instr->value());
3967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (elements_kind) {
3968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT8_ELEMENTS:
3969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case INT8_ELEMENTS:
3970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT8_CLAMPED_ELEMENTS:
3971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov_b(operand, value);
3972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
3973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT16_ELEMENTS:
3974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case INT16_ELEMENTS:
3975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov_w(operand, value);
3976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
3977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT32_ELEMENTS:
3978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case INT32_ELEMENTS:
3979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ mov(operand, value);
3980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
3981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FLOAT32_ELEMENTS:
3982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FLOAT64_ELEMENTS:
3983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_SMI_ELEMENTS:
3984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_ELEMENTS:
3985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_DOUBLE_ELEMENTS:
3986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_HOLEY_SMI_ELEMENTS:
3987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_HOLEY_ELEMENTS:
3988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_HOLEY_DOUBLE_ELEMENTS:
3989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case DICTIONARY_ELEMENTS:
3990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
3991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
3992109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case FAST_STRING_WRAPPER_ELEMENTS:
3993109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case SLOW_STRING_WRAPPER_ELEMENTS:
3994109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case NO_ELEMENTS:
3995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        UNREACHABLE();
3996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
3997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
4003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand double_store_operand = BuildFastArrayOperand(
4004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->elements(),
4005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->key(),
4006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->hydrogen()->key()->representation(),
4007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FAST_DOUBLE_ELEMENTS,
4008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->base_offset());
4009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint64_t int_val = kHoleNanInt64;
4011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int32_t lower = static_cast<int32_t>(int_val);
4012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
4013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Operand double_store_operand2 = BuildFastArrayOperand(
4014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      instr->elements(), instr->key(),
4015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      instr->hydrogen()->key()->representation(), FAST_DOUBLE_ELEMENTS,
4016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      instr->base_offset() + kPointerSize);
4017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->IsConstantHoleStore()) {
4019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This means we should store the (double) hole. No floating point
4020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // registers required.
4021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(double_store_operand, Immediate(lower));
4022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(double_store_operand2, Immediate(upper));
4023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label no_special_nan_handling, done;
4025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Register value = ToX87Register(instr->value());
4026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Fxch(value);
4027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->NeedsCanonicalization()) {
4029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fld(0);
4030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fld(0);
4031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ FCmp();
4032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_odd, &no_special_nan_handling, Label::kNear);
4033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // All NaNs are Canonicalized to 0x7fffffffffffffff
4034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ mov(double_store_operand, Immediate(0xffffffff));
4035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ mov(double_store_operand2, Immediate(0x7fffffff));
4036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ jmp(&done, Label::kNear);
4037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
4038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ lea(esp, Operand(esp, -kDoubleSize));
4039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fst_d(MemOperand(esp, 0));
4040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ lea(esp, Operand(esp, kDoubleSize));
4041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int offset = sizeof(kHoleNanUpper32);
404213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
4043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ j(not_equal, &no_special_nan_handling, Label::kNear);
4044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ mov(double_store_operand, Immediate(lower));
4045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ mov(double_store_operand2, Immediate(upper));
4046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ jmp(&done, Label::kNear);
4047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&no_special_nan_handling);
4049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fst_d(double_store_operand);
4050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&done);
4051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
4056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register elements = ToRegister(instr->elements());
4057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
4058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand operand = BuildFastArrayOperand(
4060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->elements(),
4061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->key(),
4062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->hydrogen()->key()->representation(),
4063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FAST_ELEMENTS,
4064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->base_offset());
4065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->value()->IsRegister()) {
4066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(operand, ToRegister(instr->value()));
4067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
4069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsSmi(operand_value)) {
4070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Immediate immediate = ToImmediate(operand_value, Representation::Smi());
4071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(operand, immediate);
4072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!IsInteger32(operand_value));
4074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Object> handle_value = ToHandle(operand_value);
4075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(operand, handle_value);
4076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->NeedsWriteBarrier()) {
4080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(instr->value()->IsRegister());
4081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value = ToRegister(instr->value());
4082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!instr->key()->IsConstantOperand());
4083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck check_needed =
4084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->hydrogen()->value()->type().IsHeapObject()
4085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Compute address of modified element and store it into key register.
4087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lea(key, operand);
4088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RecordWrite(elements, key, value, kSaveFPRegs, EMIT_REMEMBERED_SET,
4089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   check_needed,
4090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   instr->hydrogen()->PointersToHereCheckForValue());
4091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
4096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // By cases...external, fast-double, fast
4097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (instr->is_fixed_typed_array()) {
4098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoStoreKeyedExternalArray(instr);
4099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (instr->hydrogen()->value()->representation().IsDouble()) {
4100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoStoreKeyedFixedDoubleArray(instr);
4101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoStoreKeyedFixedArray(instr);
4103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register object = ToRegister(instr->object());
4109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp = ToRegister(instr->temp());
4110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_memento_found;
4111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(equal, instr, DeoptimizeReason::kMementoFound);
4113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&no_memento_found);
4114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LCodeGen::DoMaybeGrowElements(LMaybeGrowElements* instr) {
4118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredMaybeGrowElements final : public LDeferredCode {
4119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch   public:
4120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DeferredMaybeGrowElements(LCodeGen* codegen,
4121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              LMaybeGrowElements* instr,
4122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              const X87Stack& x87_stack)
4123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        : LDeferredCode(codegen, x87_stack), instr_(instr) {}
4124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override { codegen()->DoDeferredMaybeGrowElements(instr_); }
4125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch   private:
4128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LMaybeGrowElements* instr_;
4129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  };
4130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register result = eax;
4132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DeferredMaybeGrowElements* deferred =
4133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      new (zone()) DeferredMaybeGrowElements(this, instr, x87_stack_);
4134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LOperand* key = instr->key();
4135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LOperand* current_capacity = instr->current_capacity();
4136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(instr->hydrogen()->key()->representation().IsInteger32());
4138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(instr->hydrogen()->current_capacity()->representation().IsInteger32());
4139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(key->IsConstantOperand() || key->IsRegister());
4140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(current_capacity->IsConstantOperand() ||
4141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         current_capacity->IsRegister());
4142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (key->IsConstantOperand() && current_capacity->IsConstantOperand()) {
4144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int32_t constant_key = ToInteger32(LConstantOperand::cast(key));
4145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int32_t constant_capacity =
4146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ToInteger32(LConstantOperand::cast(current_capacity));
4147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (constant_key >= constant_capacity) {
4148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Deferred case.
4149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ jmp(deferred->entry());
4150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (key->IsConstantOperand()) {
4152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int32_t constant_key = ToInteger32(LConstantOperand::cast(key));
4153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ cmp(ToOperand(current_capacity), Immediate(constant_key));
4154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ j(less_equal, deferred->entry());
4155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (current_capacity->IsConstantOperand()) {
4156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int32_t constant_capacity =
4157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ToInteger32(LConstantOperand::cast(current_capacity));
4158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ cmp(ToRegister(key), Immediate(constant_capacity));
4159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ j(greater_equal, deferred->entry());
4160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
4161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ cmp(ToRegister(key), ToRegister(current_capacity));
4162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ j(greater_equal, deferred->entry());
4163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
4164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(result, ToOperand(instr->elements()));
4166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(deferred->exit());
4167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LCodeGen::DoDeferredMaybeGrowElements(LMaybeGrowElements* instr) {
4171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // TODO(3095996): Get rid of this. For now, we need to make the
4172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // result register contain a valid pointer because it is already
4173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // contained in the register pointer map.
4174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register result = eax;
4175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Move(result, Immediate(0));
4176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // We have to call a stub.
4178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
4179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    PushSafepointRegistersScope scope(this);
4180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (instr->object()->IsRegister()) {
4181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ Move(result, ToRegister(instr->object()));
4182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
4183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ mov(result, ToOperand(instr->object()));
4184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LOperand* key = instr->key();
4187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (key->IsConstantOperand()) {
4188bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      LConstantOperand* constant_key = LConstantOperand::cast(key);
4189bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      int32_t int_key = ToInteger32(constant_key);
4190bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      if (Smi::IsValid(int_key)) {
4191bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        __ mov(ebx, Immediate(Smi::FromInt(int_key)));
4192bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      } else {
4193bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        // We should never get here at runtime because there is a smi check on
4194bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        // the key before this point.
4195bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        __ int3();
4196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
4197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
4198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ Move(ebx, ToRegister(key));
4199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ SmiTag(ebx);
4200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    GrowArrayElementsStub stub(isolate(), instr->hydrogen()->kind());
4203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallStub(&stub);
4204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    RecordSafepointWithLazyDeopt(
4205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
4206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ StoreToSafepointRegisterSlot(result, result);
4207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
4208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Deopt on smi, which means the elements array changed to dictionary mode.
4210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ test(result, Immediate(kSmiTagMask));
4211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(equal, instr, DeoptimizeReason::kSmi);
4212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register object_reg = ToRegister(instr->object());
4217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Map> from_map = instr->original_map();
4219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Map> to_map = instr->transitioned_map();
4220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ElementsKind from_kind = instr->from_kind();
4221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ElementsKind to_kind = instr->to_kind();
4222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label not_applicable;
4224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_simple_map_transition =
4225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      IsSimpleMapChangeTransition(from_kind, to_kind);
4226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label::Distance branch_distance =
4227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      is_simple_map_transition ? Label::kNear : Label::kFar;
4228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
4229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &not_applicable, branch_distance);
4230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (is_simple_map_transition) {
4231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register new_map_reg = ToRegister(instr->new_map_temp());
4232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(FieldOperand(object_reg, HeapObject::kMapOffset),
4233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           Immediate(to_map));
4234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Write barrier.
4235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_NOT_NULL(instr->temp());
4236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RecordWriteForMap(object_reg, to_map, new_map_reg,
4237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         ToRegister(instr->temp()), kDontSaveFPRegs);
4238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(ToRegister(instr->context()).is(esi));
4240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(object_reg.is(eax));
4241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PushSafepointRegistersScope scope(this);
4242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(ebx, to_map);
424313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    TransitionElementsKindStub stub(isolate(), from_kind, to_kind);
4244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallStub(&stub);
4245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordSafepointWithLazyDeopt(instr,
4246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
4247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&not_applicable);
4249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
4253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredStringCharCodeAt final : public LDeferredCode {
4254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
4255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredStringCharCodeAt(LCodeGen* codegen,
4256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             LStringCharCodeAt* instr,
4257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             const X87Stack& x87_stack)
4258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override { codegen()->DoDeferredStringCharCodeAt(instr_); }
4260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
4263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LStringCharCodeAt* instr_;
4264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
4265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeferredStringCharCodeAt* deferred =
4267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new(zone()) DeferredStringCharCodeAt(this, instr, x87_stack_);
4268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StringCharLoadGenerator::Generate(masm(),
4270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    factory(),
4271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    ToRegister(instr->string()),
4272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    ToRegister(instr->index()),
4273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    ToRegister(instr->result()),
4274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    deferred->entry());
4275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(deferred->exit());
4276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
4280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register string = ToRegister(instr->string());
4281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
4282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(3095996): Get rid of this. For now, we need to make the
4284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // result register contain a valid pointer because it is already
4285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // contained in the register pointer map.
4286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(result, Immediate(0));
4287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushSafepointRegistersScope scope(this);
4289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(string);
4290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push the index as a smi. This is safe because of the checks in
4291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // DoStringCharCodeAt above.
4292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
4293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->index()->IsConstantOperand()) {
4294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Immediate immediate = ToImmediate(LConstantOperand::cast(instr->index()),
4295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Representation::Smi());
4296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(immediate);
4297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register index = ToRegister(instr->index());
4299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiTag(index);
4300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(index);
4301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallRuntimeFromDeferred(Runtime::kStringCharCodeAtRT, 2,
4303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          instr, instr->context());
4304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AssertSmi(eax);
4305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiUntag(eax);
4306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ StoreToSafepointRegisterSlot(result, eax);
4307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
4311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredStringCharFromCode final : public LDeferredCode {
4312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
4313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredStringCharFromCode(LCodeGen* codegen,
4314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               LStringCharFromCode* instr,
4315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               const X87Stack& x87_stack)
4316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override {
4318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen()->DoDeferredStringCharFromCode(instr_);
4319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
4323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LStringCharFromCode* instr_;
4324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
4325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeferredStringCharFromCode* deferred =
4327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new(zone()) DeferredStringCharFromCode(this, instr, x87_stack_);
4328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->hydrogen()->value()->representation().IsInteger32());
4330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register char_code = ToRegister(instr->char_code());
4331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
4332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!char_code.is(result));
4333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(char_code, String::kMaxOneByteCharCode);
4335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(above, deferred->entry());
4336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(result, Immediate(factory()->single_character_string_cache()));
4337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(result, FieldOperand(result,
4338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              char_code, times_pointer_size,
4339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              FixedArray::kHeaderSize));
4340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(result, factory()->undefined_value());
4341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, deferred->entry());
4342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(deferred->exit());
4343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
4347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register char_code = ToRegister(instr->char_code());
4348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
4349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(3095996): Get rid of this. For now, we need to make the
4351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // result register contain a valid pointer because it is already
4352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // contained in the register pointer map.
4353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(result, Immediate(0));
4354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushSafepointRegistersScope scope(this);
4356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTag(char_code);
4357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(char_code);
4358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallRuntimeFromDeferred(Runtime::kStringCharFromCode, 1, instr,
4359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          instr->context());
4360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ StoreToSafepointRegisterSlot(result, eax);
4361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStringAdd(LStringAdd* instr) {
4365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(esi));
4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->left()).is(edx));
4367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->right()).is(eax));
4368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StringAddStub stub(isolate(),
4369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     instr->hydrogen()->flags(),
4370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     instr->hydrogen()->pretenure_flag());
4371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
4376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* output = instr->result();
4378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input->IsRegister() || input->IsStackSlot());
4379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(output->IsDoubleRegister());
4380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (input->IsRegister()) {
4381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register input_reg = ToRegister(input);
4382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(input_reg);
4383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Mov(ToX87Register(output), Operand(esp, 0), kX87IntOperand);
4384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop(input_reg);
4385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand);
4387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
4392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* output = instr->result();
4394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register res = ToX87Register(output);
4395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87PrepareToWrite(res);
4396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadUint32NoSSE2(ToRegister(input));
4397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87CommitWrite(res);
4398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoNumberTagI(LNumberTagI* instr) {
4402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredNumberTagI final : public LDeferredCode {
4403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
4404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredNumberTagI(LCodeGen* codegen,
4405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       LNumberTagI* instr,
4406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       const X87Stack& x87_stack)
4407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override {
4409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(),
4410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       SIGNED_INT32);
4411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
4415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LNumberTagI* instr_;
4416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
4417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input->IsRegister() && input->Equals(instr->result()));
4420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg = ToRegister(input);
4421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeferredNumberTagI* deferred =
4423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new(zone()) DeferredNumberTagI(this, instr, x87_stack_);
4424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTag(reg);
4425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(overflow, deferred->entry());
4426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(deferred->exit());
4427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoNumberTagU(LNumberTagU* instr) {
4431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredNumberTagU final : public LDeferredCode {
4432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
4433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredNumberTagU(LCodeGen* codegen,
4434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       LNumberTagU* instr,
4435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       const X87Stack& x87_stack)
4436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override {
4438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(),
4439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       UNSIGNED_INT32);
4440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
4444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LNumberTagU* instr_;
4445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
4446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input->IsRegister() && input->Equals(instr->result()));
4449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg = ToRegister(input);
4450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeferredNumberTagU* deferred =
4452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new(zone()) DeferredNumberTagU(this, instr, x87_stack_);
4453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(reg, Immediate(Smi::kMaxValue));
4454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(above, deferred->entry());
4455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTag(reg);
4456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(deferred->exit());
4457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
4461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     LOperand* value,
4462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     LOperand* temp,
4463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     IntegerSignedness signedness) {
4464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, slow;
4465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg = ToRegister(value);
4466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register tmp = ToRegister(temp);
4467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (signedness == SIGNED_INT32) {
4469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // There was overflow, so bits 30 and 31 of the original integer
4470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // disagree. Try to allocate a heap number in new space and store
4471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the value in there. If that fails, call the runtime system.
4472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiUntag(reg);
4473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ xor_(reg, 0x80000000);
4474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(reg);
4475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fild_s(Operand(esp, 0));
4476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop(reg);
4477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // There's no fild variant for unsigned values, so zero-extend to a 64-bit
4479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // int manually.
4480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(Immediate(0));
4481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(reg);
4482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fild_d(Operand(esp, 0));
4483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop(reg);
4484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pop(reg);
4485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_inline_new) {
4488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ AllocateHeapNumber(reg, tmp, no_reg, &slow);
4489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done, Label::kNear);
4490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Slow case: Call the runtime system to do the number allocation.
4493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&slow);
4494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // TODO(3095996): Put a valid pointer value in the stack slot where the
4496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // result register is stored, as this register is in the pointer map, but
4497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // contains an integer value.
4498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(reg, Immediate(0));
4499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Preserve the value of all registers.
4501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PushSafepointRegistersScope scope(this);
4502f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Reset the context register.
4503f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (!reg.is(esi)) {
4504f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ Move(esi, Immediate(0));
4505f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
4506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordSafepointWithRegisters(
4508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ StoreToSafepointRegisterSlot(reg, eax);
4510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
4513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
4514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoNumberTagD(LNumberTagD* instr) {
4518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredNumberTagD final : public LDeferredCode {
4519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
4520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredNumberTagD(LCodeGen* codegen,
4521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       LNumberTagD* instr,
4522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       const X87Stack& x87_stack)
4523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override { codegen()->DoDeferredNumberTagD(instr_); }
4525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
4528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LNumberTagD* instr_;
4529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
4530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg = ToRegister(instr->result());
4532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Put the value to the top of stack
4534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register src = ToX87Register(instr->value());
4535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Don't use X87LoadForUsage here, which is only used by Instruction which
4536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // clobbers fp registers.
4537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  x87_stack_.Fxch(src);
4538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeferredNumberTagD* deferred =
4540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new(zone()) DeferredNumberTagD(this, instr, x87_stack_);
4541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_inline_new) {
4542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register tmp = ToRegister(instr->temp());
4543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry());
4544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(deferred->entry());
4546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(deferred->exit());
4548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fst_d(FieldOperand(reg, HeapNumber::kValueOffset));
4549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
4553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(3095996): Get rid of this. For now, we need to make the
4554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // result register contain a valid pointer because it is already
4555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // contained in the register pointer map.
4556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg = ToRegister(instr->result());
4557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(reg, Immediate(0));
4558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushSafepointRegistersScope scope(this);
4560f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Reset the context register.
4561f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!reg.is(esi)) {
4562f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    __ Move(esi, Immediate(0));
4563f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
4564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordSafepointWithRegisters(
4566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ StoreToSafepointRegisterSlot(reg, eax);
4568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoSmiTag(LSmiTag* instr) {
4572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HChange* hchange = instr->hydrogen();
4573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
4574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hchange->CheckFlag(HValue::kCanOverflow) &&
4575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      hchange->value()->CheckFlag(HValue::kUint32)) {
4576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(input, Immediate(0xc0000000));
4577f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(not_zero, instr, DeoptimizeReason::kOverflow);
4578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTag(input);
4580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hchange->CheckFlag(HValue::kCanOverflow) &&
4581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !hchange->value()->CheckFlag(HValue::kUint32)) {
4582f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
4583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(input);
4590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input->IsRegister() && input->Equals(instr->result()));
4591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->needs_check()) {
4592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(result, Immediate(kSmiTagMask));
4593f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(not_zero, instr, DeoptimizeReason::kNotASmi);
4594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ AssertSmi(result);
4596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiUntag(result);
4598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg,
4602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      Register temp_reg, X87Register res_reg,
4603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      NumberUntagDMode mode) {
4604c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  bool can_convert_undefined_to_nan = instr->truncating();
4605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
4606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label load_smi, done;
4608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87PrepareToWrite(res_reg);
4610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
4611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Smi check.
4612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input_reg, &load_smi);
4613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Heap number map check.
4615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
4616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           factory()->heap_number_map());
4617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!can_convert_undefined_to_nan) {
4618f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumber);
4619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label heap_number, convert;
4621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(equal, &heap_number);
4622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Convert undefined (or hole) to NaN.
4624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmp(input_reg, factory()->undefined_value());
4625f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(not_equal, instr,
4626f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   DeoptimizeReason::kNotAHeapNumberUndefined);
4627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&convert);
4629f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ push(Immediate(0xfff80000));
4630f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ push(Immediate(0x00000000));
4631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ fld_d(MemOperand(esp, 0));
4632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ lea(esp, Operand(esp, kDoubleSize));
4633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&done, Label::kNear);
4634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&heap_number);
4636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Heap number to x87 conversion.
4638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
4639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (deoptimize_on_minus_zero) {
4640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fldz();
4641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ FCmp();
4642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
4643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(not_zero, &done, Label::kNear);
4644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Use general purpose registers to check if we have -0.0
4646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
4647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ test(temp_reg, Immediate(HeapNumber::kSignMask));
4648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(zero, &done, Label::kNear);
4649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Pop FPU stack before deoptimizing.
4651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fstp(0);
4652f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(not_zero, instr, DeoptimizeReason::kMinusZero);
4653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done, Label::kNear);
4655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
4657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&load_smi);
4660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clobbering a temp is faster than re-tagging the
4661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // input register since we avoid dependencies.
4662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(temp_reg, input_reg);
4663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiUntag(temp_reg);  // Untag smi before converting to float.
4664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(temp_reg);
4665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fild_s(Operand(esp, 0));
4666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(esp, Immediate(kPointerSize));
4667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
4668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87CommitWrite(res_reg);
4669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
4673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input_reg = ToRegister(instr->value());
4674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The input was optimistically untagged; revert it.
4676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kSmiTagSize == 1);
4677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lea(input_reg, Operand(input_reg, times_2, kHeapObjectTag));
4678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->truncating()) {
4680c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Label truncate;
4681c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Label::Distance truncate_distance =
4682c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        DeoptEveryNTimes() ? Label::kFar : Label::kNear;
4683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
4684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           factory()->heap_number_map());
4685c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    __ j(equal, &truncate, truncate_distance);
4686c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    __ push(input_reg);
4687c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    __ CmpObjectType(input_reg, ODDBALL_TYPE, input_reg);
4688c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    __ pop(input_reg);
4689c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotANumberOrOddball);
4690c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    __ bind(&truncate);
4691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ TruncateHeapNumberToI(input_reg, input_reg);
4692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // TODO(olivf) Converting a number on the fpu is actually quite slow. We
4694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // should first try a fast conversion and then bailout to this slow case.
4695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
4696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           isolate()->factory()->heap_number_map());
4697f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumber);
4698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(esp, Immediate(kPointerSize));
4700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
4701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
4703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label no_precision_lost, not_nan, zero_check;
4704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fld(0);
4705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fist_s(MemOperand(esp, 0));
4707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fild_s(MemOperand(esp, 0));
4708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ FCmp();
4709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pop(input_reg);
4710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(equal, &no_precision_lost, Label::kNear);
4712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fstp(0);
4713f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(no_condition, instr, DeoptimizeReason::kLostPrecision);
4714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&no_precision_lost);
4715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(parity_odd, &not_nan);
4717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fstp(0);
4718f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(no_condition, instr, DeoptimizeReason::kNaN);
4719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&not_nan);
4720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ test(input_reg, Operand(input_reg));
4722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(zero, &zero_check, Label::kNear);
4723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fstp(0);
4724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(done);
4725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&zero_check);
4727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // To check for minus zero, we load the value again as float, and check
4728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // if that is still 0.
4729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ sub(esp, Immediate(kPointerSize));
4730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fstp_s(Operand(esp, 0));
4731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pop(input_reg);
4732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ test(input_reg, Operand(input_reg));
4733f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(not_zero, instr, DeoptimizeReason::kMinusZero);
4734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fist_s(MemOperand(esp, 0));
4736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ fild_s(MemOperand(esp, 0));
4737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ FCmp();
4738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pop(input_reg);
4739f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(not_equal, instr, DeoptimizeReason::kLostPrecision);
4740f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(parity_even, instr, DeoptimizeReason::kNaN);
4741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoTaggedToI(LTaggedToI* instr) {
4747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredTaggedToI final : public LDeferredCode {
4748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
4749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredTaggedToI(LCodeGen* codegen,
4750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      LTaggedToI* instr,
4751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const X87Stack& x87_stack)
4752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override { codegen()->DoDeferredTaggedToI(instr_, done()); }
4754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
4757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LTaggedToI* instr_;
4758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
4759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input->IsRegister());
4762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input_reg = ToRegister(input);
4763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input_reg.is(ToRegister(instr->result())));
4764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->value()->representation().IsSmi()) {
4766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiUntag(input_reg);
4767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredTaggedToI* deferred =
4769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new(zone()) DeferredTaggedToI(this, instr, x87_stack_);
4770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Optimistically untag the input.
4771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If the input is a HeapObject, SmiUntag will set the carry flag.
4772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
4773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiUntag(input_reg);
4774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Branch to deferred code if the input was tagged.
4775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The deferred code will take care of restoring the tag.
4776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(carry, deferred->entry());
4777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(deferred->exit());
4778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
4783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input->IsRegister());
4785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* temp = instr->temp();
4786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(temp->IsRegister());
4787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* result = instr->result();
4788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(result->IsDoubleRegister());
4789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input_reg = ToRegister(input);
4791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp_reg = ToRegister(temp);
4792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HValue* value = instr->hydrogen()->value();
4794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NumberUntagDMode mode = value->representation().IsSmi()
4795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
4796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitNumberUntagDNoSSE2(instr, input_reg, temp_reg, ToX87Register(result),
4798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         mode);
4799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDoubleToI(LDoubleToI* instr) {
4803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input->IsDoubleRegister());
4805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* result = instr->result();
4806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(result->IsRegister());
4807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result_reg = ToRegister(result);
4808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->truncating()) {
4810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Register input_reg = ToX87Register(input);
4811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Fxch(input_reg);
4812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ TruncateX87TOSToI(result_reg);
4813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label lost_precision, is_nan, minus_zero, done;
4815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Register input_reg = ToX87Register(input);
4816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    X87Fxch(input_reg);
4817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
4818958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 &lost_precision, &is_nan, &minus_zero);
4819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done);
4820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&lost_precision);
4821f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(no_condition, instr, DeoptimizeReason::kLostPrecision);
4822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&is_nan);
4823f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(no_condition, instr, DeoptimizeReason::kNaN);
4824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&minus_zero);
4825f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(no_condition, instr, DeoptimizeReason::kMinusZero);
4826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
4827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
4832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input->IsDoubleRegister());
4834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* result = instr->result();
4835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(result->IsRegister());
4836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result_reg = ToRegister(result);
4837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label lost_precision, is_nan, minus_zero, done;
4839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register input_reg = ToX87Register(input);
4840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Fxch(input_reg);
4841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
4842958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               &lost_precision, &is_nan, &minus_zero);
4843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done);
4844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&lost_precision);
4845f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(no_condition, instr, DeoptimizeReason::kLostPrecision);
4846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&is_nan);
4847f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(no_condition, instr, DeoptimizeReason::kNaN);
4848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&minus_zero);
4849f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(no_condition, instr, DeoptimizeReason::kMinusZero);
4850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
4851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTag(result_reg);
4852f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
4853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCheckSmi(LCheckSmi* instr) {
4857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ test(ToOperand(input), Immediate(kSmiTagMask));
4859f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(not_zero, instr, DeoptimizeReason::kNotASmi);
4860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
4864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
4865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LOperand* input = instr->value();
4866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(ToOperand(input), Immediate(kSmiTagMask));
4867f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(zero, instr, DeoptimizeReason::kSmi);
4868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LCodeGen::DoCheckArrayBufferNotNeutered(
4873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LCheckArrayBufferNotNeutered* instr) {
4874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register view = ToRegister(instr->view());
4875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register scratch = ToRegister(instr->scratch());
4876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(scratch, FieldOperand(view, JSArrayBufferView::kBufferOffset));
4878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ test_b(FieldOperand(scratch, JSArrayBuffer::kBitFieldOffset),
48793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            Immediate(1 << JSArrayBuffer::WasNeutered::kShift));
4880f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(not_zero, instr, DeoptimizeReason::kOutOfBounds);
4881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
4885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
4886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp = ToRegister(instr->temp());
4887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
4889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->is_interval_check()) {
4891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InstanceType first;
4892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InstanceType last;
4893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    instr->hydrogen()->GetCheckInterval(&first, &last);
4894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
48953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), Immediate(first));
4896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If there is only one type in the interval check for equality.
4898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (first == last) {
4899f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(not_equal, instr, DeoptimizeReason::kWrongInstanceType);
4900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4901f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(below, instr, DeoptimizeReason::kWrongInstanceType);
4902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Omit check for the last type.
4903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (last != LAST_TYPE) {
49043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), Immediate(last));
4905f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        DeoptimizeIf(above, instr, DeoptimizeReason::kWrongInstanceType);
4906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
4907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint8_t mask;
4910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint8_t tag;
4911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
4912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (base::bits::IsPowerOfTwo32(mask)) {
4914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
49153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), Immediate(mask));
4916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DeoptimizeIf(tag == 0 ? not_zero : zero, instr,
4917f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   DeoptimizeReason::kWrongInstanceType);
4918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
4920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ and_(temp, mask);
4921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmp(temp, tag);
4922f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(not_equal, instr, DeoptimizeReason::kWrongInstanceType);
4923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCheckValue(LCheckValue* instr) {
4929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<HeapObject> object = instr->hydrogen()->object().handle();
4930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->object_in_new_space()) {
4931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register reg = ToRegister(instr->value());
4932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Cell> cell = isolate()->factory()->NewCell(object);
4933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(reg, Operand::ForCell(cell));
4934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand operand = ToOperand(instr->value());
4936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(operand, object);
4937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4938f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(not_equal, instr, DeoptimizeReason::kValueMismatch);
4939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
494362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label deopt, done;
494462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // If the map is not deprecated the migration attempt does not make sense.
494562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ push(object);
494662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ mov(object, FieldOperand(object, HeapObject::kMapOffset));
494762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ test(FieldOperand(object, Map::kBitField3Offset),
494862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Immediate(Map::Deprecated::kMask));
494962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ pop(object);
495062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ j(zero, &deopt);
495162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
4952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PushSafepointRegistersScope scope(this);
4954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(object);
4955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ xor_(esi, esi);
4956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
4957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordSafepointWithRegisters(
4958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
4959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test(eax, Immediate(kSmiTagMask));
4961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
496262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ j(not_zero, &done);
496362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
496462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ bind(&deopt);
496562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DeoptimizeIf(no_condition, instr, DeoptimizeReason::kInstanceMigrationFailed);
496662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
496762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ bind(&done);
4968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCheckMaps(LCheckMaps* instr) {
4972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredCheckMaps final : public LDeferredCode {
4973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
4974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredCheckMaps(LCodeGen* codegen,
4975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      LCheckMaps* instr,
4976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Register object,
4977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      const X87Stack& x87_stack)
4978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : LDeferredCode(codegen, x87_stack), instr_(instr), object_(object) {
4979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetExit(check_maps());
4980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override {
4982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen()->DoDeferredInstanceMigration(instr_, object_);
4983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* check_maps() { return &check_maps_; }
4985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4986958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
4988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LCheckMaps* instr_;
4989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label check_maps_;
4990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object_;
4991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
4992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->IsStabilityCheck()) {
4994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const UniqueSet<Map>* maps = instr->hydrogen()->maps();
4995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < maps->size(); ++i) {
4996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AddStabilityDependency(maps->at(i).handle());
4997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
4999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
5002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input->IsRegister());
5003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg = ToRegister(input);
5004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeferredCheckMaps* deferred = NULL;
5006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->HasMigrationTarget()) {
5007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_);
5008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(deferred->check_maps());
5009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label success;
5013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < maps->size() - 1; i++) {
5014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> map = maps->at(i).handle();
5015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareMap(reg, map);
5016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(equal, &success, Label::kNear);
5017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Map> map = maps->at(maps->size() - 1).handle();
5020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CompareMap(reg, map);
5021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->HasMigrationTarget()) {
5022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, deferred->entry());
5023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
5024f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(not_equal, instr, DeoptimizeReason::kWrongMap);
5025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&success);
5028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Register value_reg = ToX87Register(instr->unclamped());
5033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result_reg = ToRegister(instr->result());
5034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  X87Fxch(value_reg);
5035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ClampTOSToUint8(result_reg);
5036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
5040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->unclamped()->Equals(instr->result()));
5041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value_reg = ToRegister(instr->result());
5042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ClampUint8(value_reg);
5043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoClampTToUint8NoSSE2(LClampTToUint8NoSSE2* instr) {
5047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input_reg = ToRegister(instr->unclamped());
5048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result_reg = ToRegister(instr->result());
5049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = ToRegister(instr->scratch());
5050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch2 = ToRegister(instr->scratch2());
5051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch3 = ToRegister(instr->scratch3());
5052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label is_smi, done, heap_number, valid_exponent,
5053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      largest_value, zero_result, maybe_nan_or_infinity;
5054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(input_reg, &is_smi);
5056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for heap number
5058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         factory()->heap_number_map());
5060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &heap_number, Label::kNear);
5061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for undefined. Undefined is converted to zero for clamping
5063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // conversions.
5064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(input_reg, factory()->undefined_value());
5065f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumberUndefined);
5066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&zero_result, Label::kNear);
5067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Heap number
5069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&heap_number);
5070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Surprisingly, all of the hand-crafted bit-manipulations below are much
5072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // faster than the x86 FPU built-in instruction, especially since "banker's
5073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rounding" would be additionally very expensive
5074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get exponent word.
5076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset));
5077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test for negative values --> clamp to zero
5080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ test(scratch, scratch);
5081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(negative, &zero_result, Label::kNear);
5082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get exponent alone in scratch2.
5084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(scratch2, scratch);
5085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ and_(scratch2, HeapNumber::kExponentMask);
5086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ shr(scratch2, HeapNumber::kExponentShift);
5087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(zero, &zero_result, Label::kNear);
5088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1));
5089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(negative, &zero_result, Label::kNear);
5090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const uint32_t non_int8_exponent = 7;
5092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(scratch2, Immediate(non_int8_exponent + 1));
5093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the exponent is too big, check for special values.
5094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(greater, &maybe_nan_or_infinity, Label::kNear);
5095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&valid_exponent);
5097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent
5098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // < 7. The shift bias is the number of bits to shift the mantissa such that
5099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // with an exponent of 7 such the that top-most one is in bit 30, allowing
5100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // detection the rounding overflow of a 255.5 to 256 (bit 31 goes from 0 to
5101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 1).
5102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int shift_bias = (30 - HeapNumber::kExponentShift) - 7 - 1;
5103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lea(result_reg, MemOperand(scratch2, shift_bias));
5104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Here result_reg (ecx) is the shift, scratch is the exponent word.  Get the
5105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // top bits of the mantissa.
5106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ and_(scratch, HeapNumber::kMantissaMask);
5107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Put back the implicit 1 of the mantissa
5108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ or_(scratch, 1 << HeapNumber::kExponentShift);
5109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Shift up to round
5110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ shl_cl(scratch);
5111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Use "banker's rounding" to spec: If fractional part of number is 0.5, then
5112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // use the bit in the "ones" place and add it to the "halves" place, which has
5113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the effect of rounding to even.
5114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(scratch2, scratch);
5115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8;
5116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const uint32_t one_bit_shift = one_half_bit_shift + 1;
5117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ and_(scratch2, Immediate((1 << one_bit_shift) - 1));
5118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(scratch2, Immediate(1 << one_half_bit_shift));
5119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_round;
5120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(less, &no_round, Label::kNear);
5121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label round_up;
5122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(scratch2, Immediate(1 << one_half_bit_shift));
5123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(greater, &round_up, Label::kNear);
5124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ test(scratch3, scratch3);
5125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_zero, &round_up, Label::kNear);
5126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(scratch2, scratch);
5127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ and_(scratch2, Immediate(1 << one_bit_shift));
5128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ shr(scratch2, 1);
5129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&round_up);
5130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(scratch, scratch2);
5131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(overflow, &largest_value, Label::kNear);
5132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&no_round);
5133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ shr(scratch, 23);
5134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(result_reg, scratch);
5135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done, Label::kNear);
5136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&maybe_nan_or_infinity);
5138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for NaN/Infinity, all other values map to 255
5139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1));
5140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &largest_value, Label::kNear);
5141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for NaN, which differs from Infinity in that at least one mantissa
5143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // bit is set.
5144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ and_(scratch, HeapNumber::kMantissaMask);
5145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_zero, &zero_result, Label::kNear);  // M!=0 --> NaN
5147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Infinity -> Fall through to map to 255.
5148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&largest_value);
5150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(result_reg, Immediate(255));
5151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done, Label::kNear);
5152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&zero_result);
5154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ xor_(result_reg, result_reg);
5155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done, Label::kNear);
5156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // smi
5158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&is_smi);
5159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!input_reg.is(result_reg)) {
5160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(result_reg, input_reg);
5161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiUntag(result_reg);
5163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ClampUint8(result_reg);
5164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
5165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoAllocate(LAllocate* instr) {
5169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredAllocate final : public LDeferredCode {
5170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
5171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredAllocate(LCodeGen* codegen,
5172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     LAllocate* instr,
5173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     const X87Stack& x87_stack)
5174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
5175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override { codegen()->DoDeferredAllocate(instr_); }
5176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
5177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
5179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LAllocate* instr_;
5180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
5181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeferredAllocate* deferred =
5183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new(zone()) DeferredAllocate(this, instr, x87_stack_);
5184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
5186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp = ToRegister(instr->temp());
5187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate memory for the object.
5189bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  AllocationFlags flags = NO_ALLOCATION_FLAGS;
5190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
5191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
5192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (instr->hydrogen()->IsOldSpaceAllocation()) {
5194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    flags = static_cast<AllocationFlags>(flags | PRETENURE);
5196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5198bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
5199bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    flags = static_cast<AllocationFlags>(flags | ALLOCATION_FOLDING_DOMINATOR);
5200bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
5201bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!instr->hydrogen()->IsAllocationFolded());
5202bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->size()->IsConstantOperand()) {
5204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5205f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    CHECK(size <= kMaxRegularHeapObjectSize);
5206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
5207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
5208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register size = ToRegister(instr->size());
5209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
5210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(deferred->exit());
5213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->MustPrefillWithFiller()) {
5215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->size()->IsConstantOperand()) {
5216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(temp, (size / kPointerSize) - 1);
5218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
5219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      temp = ToRegister(instr->size());
5220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ shr(temp, kPointerSizeLog2);
5221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ dec(temp);
5222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label loop;
5224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&loop);
5225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(FieldOperand(result, temp, times_pointer_size, 0),
5226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->one_pointer_filler_map());
5227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ dec(temp);
5228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_zero, &loop);
5229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5232bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid LCodeGen::DoFastAllocate(LFastAllocate* instr) {
5233bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(instr->hydrogen()->IsAllocationFolded());
5234bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator());
5235bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register result = ToRegister(instr->result());
5236bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register temp = ToRegister(instr->temp());
5237bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5238bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  AllocationFlags flags = ALLOCATION_FOLDED;
5239bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
5240bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
5241bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
5242bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (instr->hydrogen()->IsOldSpaceAllocation()) {
5243bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5244bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    flags = static_cast<AllocationFlags>(flags | PRETENURE);
5245bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
5246bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (instr->size()->IsConstantOperand()) {
5247bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5248f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    CHECK(size <= kMaxRegularHeapObjectSize);
5249bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    __ FastAllocate(size, result, temp, flags);
5250bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
5251bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Register size = ToRegister(instr->size());
5252bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    __ FastAllocate(size, result, temp, flags);
5253bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
5254bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
5255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredAllocate(LAllocate* instr) {
5257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
5258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(3095996): Get rid of this. For now, we need to make the
5260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // result register contain a valid pointer because it is already
5261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // contained in the register pointer map.
5262c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Move(result, Immediate(Smi::kZero));
5263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushSafepointRegistersScope scope(this);
5265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->size()->IsRegister()) {
5266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register size = ToRegister(instr->size());
5267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!size.is(result));
5268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiTag(ToRegister(instr->size()));
5269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(size);
5270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
5271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (size >= 0 && size <= Smi::kMaxValue) {
5273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ push(Immediate(Smi::FromInt(size)));
5274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
5275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // We should never get here at runtime => abort
5276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ int3();
5277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
5278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int flags = AllocateDoubleAlignFlag::encode(
5282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->hydrogen()->MustAllocateDoubleAligned());
5283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (instr->hydrogen()->IsOldSpaceAllocation()) {
5284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    flags = AllocateTargetSpace::update(flags, OLD_SPACE);
5286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
5287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    flags = AllocateTargetSpace::update(flags, NEW_SPACE);
5288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(Immediate(Smi::FromInt(flags)));
5290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallRuntimeFromDeferred(
5292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
5293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ StoreToSafepointRegisterSlot(result, eax);
5294bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5295bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
5296bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    AllocationFlags allocation_flags = NO_ALLOCATION_FLAGS;
5297bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (instr->hydrogen()->IsOldSpaceAllocation()) {
5298bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5299bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE);
5300bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
5301bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // If the allocation folding dominator allocate triggered a GC, allocation
5302bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // happend in the runtime. We have to reset the top pointer to virtually
5303bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // undo the allocation.
5304bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    ExternalReference allocation_top =
5305bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags);
5306bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    __ sub(eax, Immediate(kHeapObjectTag));
5307bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    __ mov(Operand::StaticVariable(allocation_top), eax);
5308bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    __ add(eax, Immediate(kHeapObjectTag));
5309bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
5310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoTypeof(LTypeof* instr) {
5314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(esi));
5315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(ToRegister(instr->value()).is(ebx));
5316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label end, do_call;
5317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register value_register = ToRegister(instr->value());
5318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ JumpIfNotSmi(value_register, &do_call);
5319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(eax, Immediate(isolate()->factory()->number_string()));
5320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ jmp(&end);
5321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&do_call);
5322f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Callable callable = CodeFactory::Typeof(isolate());
5323f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CallCode(callable.code(), RelocInfo::CODE_TARGET, instr);
5324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&end);
5325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
5329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
5330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition final_branch_condition = EmitTypeofIs(instr, input);
5331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (final_branch_condition != no_condition) {
5332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitBranch(instr, final_branch_condition);
5333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
5338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* true_label = instr->TrueLabel(chunk_);
5339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label* false_label = instr->FalseLabel(chunk_);
5340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> type_name = instr->type_literal();
5341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int left_block = instr->TrueDestination(chunk_);
5342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int right_block = instr->FalseDestination(chunk_);
5343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int next_block = GetNextEmittedBlock();
5344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label::Distance true_distance = left_block == next_block ? Label::kNear
5346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                           : Label::kFar;
5347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label::Distance false_distance = right_block == next_block ? Label::kNear
5348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                             : Label::kFar;
5349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition final_branch_condition = no_condition;
5350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (String::Equals(type_name, factory()->number_string())) {
5351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input, true_label, true_distance);
5352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(FieldOperand(input, HeapObject::kMapOffset),
5353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           factory()->heap_number_map());
5354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    final_branch_condition = equal;
5355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(type_name, factory()->string_string())) {
5357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input, false_label, false_distance);
5358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
5359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    final_branch_condition = below;
5360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(type_name, factory()->symbol_string())) {
5362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input, false_label, false_distance);
5363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CmpObjectType(input, SYMBOL_TYPE, input);
5364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    final_branch_condition = equal;
5365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(type_name, factory()->boolean_string())) {
5367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(input, factory()->true_value());
5368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(equal, true_label, true_distance);
5369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(input, factory()->false_value());
5370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    final_branch_condition = equal;
5371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(type_name, factory()->undefined_string())) {
5373109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ cmp(input, factory()->null_value());
5374109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ j(equal, false_label, false_distance);
5375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input, false_label, false_distance);
5376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check for undetectable objects => true.
5377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(input, FieldOperand(input, HeapObject::kMapOffset));
5378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test_b(FieldOperand(input, Map::kBitFieldOffset),
53793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch              Immediate(1 << Map::kIsUndetectable));
5380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    final_branch_condition = not_zero;
5381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(type_name, factory()->function_string())) {
5383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input, false_label, false_distance);
5384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Check for callable and not undetectable objects => true.
5385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(input, FieldOperand(input, HeapObject::kMapOffset));
5386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ movzx_b(input, FieldOperand(input, Map::kBitFieldOffset));
5387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ and_(input, (1 << Map::kIsCallable) | (1 << Map::kIsUndetectable));
5388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ cmp(input, 1 << Map::kIsCallable);
5389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    final_branch_condition = equal;
5390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(type_name, factory()->object_string())) {
5392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input, false_label, false_distance);
5393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(input, factory()->null_value());
5394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(equal, true_label, true_distance);
5395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
5396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CmpObjectType(input, FIRST_JS_RECEIVER_TYPE, input);
5397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(below, false_label, false_distance);
5398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Check for callable or undetectable objects => false.
5399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ test_b(FieldOperand(input, Map::kBitFieldOffset),
54003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch              Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
5401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    final_branch_condition = zero;
5402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
5404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(false_label, false_distance);
5405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return final_branch_condition;
5407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
5411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (info()->ShouldEnsureSpaceForLazyDeopt()) {
5412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Ensure that we have enough space after the previous lazy-bailout
5413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // instruction for patching the code here.
5414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int current_pc = masm()->pc_offset();
5415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (current_pc < last_lazy_deopt_pc_ + space_needed) {
5416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
5417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Nop(padding_size);
5418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  last_lazy_deopt_pc_ = masm()->pc_offset();
5421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLazyBailout(LLazyBailout* instr) {
5425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  last_lazy_deopt_pc_ = masm()->pc_offset();
5426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->HasEnvironment());
5427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LEnvironment* env = instr->environment();
5428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
5429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
5430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeoptimize(LDeoptimize* instr) {
5434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Deoptimizer::BailoutType type = instr->hydrogen()->type();
5435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
5436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // needed return address), even though the implementation of LAZY and EAGER is
5437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // now identical. When LAZY is eventually completely folded into EAGER, remove
5438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the special case below.
5439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info()->IsStub() && type == Deoptimizer::EAGER) {
5440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    type = Deoptimizer::LAZY;
5441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeoptimizeIf(no_condition, instr, instr->hydrogen()->reason(), type);
5443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDummy(LDummy* instr) {
5447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Nothing to see here, move on!
5448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDummyUse(LDummyUse* instr) {
5452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Nothing to see here, move on!
5453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
5457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushSafepointRegistersScope scope(this);
5458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
5459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
5460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordSafepointWithLazyDeopt(
5461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
5462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->HasEnvironment());
5463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LEnvironment* env = instr->environment();
5464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
5465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStackCheck(LStackCheck* instr) {
5469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredStackCheck final : public LDeferredCode {
5470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
5471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredStackCheck(LCodeGen* codegen,
5472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       LStackCheck* instr,
5473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       const X87Stack& x87_stack)
5474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
5475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override { codegen()->DoDeferredStackCheck(instr_); }
5476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
5477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
5479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LStackCheck* instr_;
5480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
5481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->HasEnvironment());
5483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LEnvironment* env = instr->environment();
5484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // There is no LLazyBailout instruction for stack-checks. We have to
5485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // prepare for lazy deoptimization explicitly here.
5486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->is_function_entry()) {
5487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Perform stack overflow check.
5488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
5489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalReference stack_limit =
5490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ExternalReference::address_of_stack_limit(isolate());
5491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(esp, Operand::StaticVariable(stack_limit));
5492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(above_equal, &done, Label::kNear);
5493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(instr->context()->IsRegister());
5495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(ToRegister(instr->context()).is(esi));
5496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallCode(isolate()->builtins()->StackCheck(),
5497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             RelocInfo::CODE_TARGET,
5498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             instr);
5499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
5500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
5501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(instr->hydrogen()->is_backwards_branch());
5502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Perform stack overflow check if this goto needs it before jumping.
5503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredStackCheck* deferred_stack_check =
5504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new(zone()) DeferredStackCheck(this, instr, x87_stack_);
5505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalReference stack_limit =
5506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ExternalReference::address_of_stack_limit(isolate());
5507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(esp, Operand::StaticVariable(stack_limit));
5508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(below, deferred_stack_check->entry());
5509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
5510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(instr->done_label());
5511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    deferred_stack_check->SetExit(instr->done_label());
5512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
5513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Don't record a deoptimization index for the safepoint here.
5514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This will be done explicitly when emitting call and the safepoint in
5515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the deferred code.
5516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoOsrEntry(LOsrEntry* instr) {
5521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This is a pseudo-instruction that ensures that the environment here is
5522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // properly registered for deoptimization and records the assembler's PC
5523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // offset.
5524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LEnvironment* environment = instr->environment();
5525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the environment were already registered, we would have no way of
5527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // backpatching it with the spill slot operands.
5528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!environment->HasBeenRegistered());
5529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
5530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateOsrPrologue();
5532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
5536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(esi));
5537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label use_cache, call_runtime;
5539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CheckEnumCache(&call_runtime);
5540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
5542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&use_cache, Label::kNear);
5543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the set of properties to enumerate.
5545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&call_runtime);
5546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(eax);
5547109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CallRuntime(Runtime::kForInEnumerate, instr);
5548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&use_cache);
5549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
5553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register map = ToRegister(instr->map());
5554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
5555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label load_cache, done;
5556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ EnumLength(result, map);
5557c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ cmp(result, Immediate(Smi::kZero));
5558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &load_cache, Label::kNear);
5559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(result, isolate()->factory()->empty_fixed_array());
5560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done, Label::kNear);
5561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&load_cache);
5563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadInstanceDescriptors(map, result);
5564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(result,
5565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(result, DescriptorArray::kEnumCacheOffset));
5566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(result,
5567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(result, FixedArray::SizeFor(instr->idx())));
5568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
5569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ test(result, result);
5570f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(equal, instr, DeoptimizeReason::kNoCache);
5571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
5575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register object = ToRegister(instr->value());
5576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(ToRegister(instr->map()),
5577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(object, HeapObject::kMapOffset));
5578f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(not_equal, instr, DeoptimizeReason::kWrongMap);
5579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
5583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register object,
5584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register index) {
5585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushSafepointRegistersScope scope(this);
5586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(object);
5587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(index);
5588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ xor_(esi, esi);
5589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble);
5590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordSafepointWithRegisters(
5591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->pointer_map(), 2, Safepoint::kNoLazyDeopt);
5592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ StoreToSafepointRegisterSlot(object, eax);
5593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
5597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredLoadMutableDouble final : public LDeferredCode {
5598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
5599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredLoadMutableDouble(LCodeGen* codegen,
5600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              LLoadFieldByIndex* instr,
5601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register object,
5602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register index,
5603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              const X87Stack& x87_stack)
5604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : LDeferredCode(codegen, x87_stack),
5605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          instr_(instr),
5606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          object_(object),
5607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          index_(index) {
5608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5609014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override {
5610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_);
5611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
5613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
5615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LLoadFieldByIndex* instr_;
5616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object_;
5617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register index_;
5618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
5619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register object = ToRegister(instr->object());
5621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register index = ToRegister(instr->index());
5622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeferredLoadMutableDouble* deferred;
5624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  deferred = new(zone()) DeferredLoadMutableDouble(
5625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      this, instr, object, index, x87_stack_);
5626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label out_of_object, done;
5628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ test(index, Immediate(Smi::FromInt(1)));
5629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_zero, deferred->entry());
5630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sar(index, 1);
5632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(index, Immediate(0));
5634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(less, &out_of_object, Label::kNear);
5635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(object, FieldOperand(object,
5636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              index,
5637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              times_half_pointer_size,
5638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              JSObject::kHeaderSize));
5639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done, Label::kNear);
5640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&out_of_object);
5642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(object, FieldOperand(object, JSObject::kPropertiesOffset));
5643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ neg(index);
5644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Index is now equal to out of object property index plus 1.
5645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(object, FieldOperand(object,
5646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              index,
5647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              times_half_pointer_size,
5648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              FixedArray::kHeaderSize - kPointerSize));
5649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(deferred->exit());
5650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
5651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __
5654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
5656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
5657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_TARGET_ARCH_X87
5659