1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.7
23ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Redistribution and use in source and binary forms, with or without
33ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// modification, are permitted provided that the following conditions are
43ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// met:
53ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
63ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Redistributions of source code must retain the above copyright
73ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       notice, this list of conditions and the following disclaimer.
83ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Redistributions in binary form must reproduce the above
93ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       copyright notice, this list of conditions and the following
103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       disclaimer in the documentation and/or other materials provided
113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       with the distribution.
123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Neither the name of Google Inc. nor the names of its
133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       contributors may be used to endorse or promote products derived
143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       from this software without specific prior written permission.
153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/mips/lithium-codegen-mips.h"
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
3162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/builtins/builtins-constructor.h"
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h"
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h"
34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/hydrogen-osr.h"
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/crankshaft/mips/lithium-gap-resolver-mips.h"
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h"
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/stub-cache.h"
383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace v8 {
403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace internal {
413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass SafepointGenerator final : public CallWrapper {
443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SafepointGenerator(LCodeGen* codegen,
463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     LPointerMap* pointers,
473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Safepoint::DeoptMode mode)
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : codegen_(codegen),
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        pointers_(pointers),
503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        deopt_mode_(mode) { }
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual ~SafepointGenerator() {}
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BeforeCall(int call_size) const override {}
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AfterCall() const override {
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    codegen_->RecordSafepoint(pointers_, deopt_mode_);
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LCodeGen* codegen_;
613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LPointerMap* pointers_;
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Safepoint::DeoptMode deopt_mode_;
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
65c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochLCodeGen::PushSafepointRegistersScope::PushSafepointRegistersScope(
66c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    LCodeGen* codegen)
67c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    : codegen_(codegen) {
68c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DCHECK(codegen_->info()->is_calling());
69c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kSimple);
70c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  codegen_->expected_safepoint_kind_ = Safepoint::kWithRegisters;
71c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
72c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  StoreRegistersStateStub stub(codegen_->isolate());
73c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  codegen_->masm_->push(ra);
74c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  codegen_->masm_->CallStub(&stub);
75c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
76c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
77c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochLCodeGen::PushSafepointRegistersScope::~PushSafepointRegistersScope() {
78c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DCHECK(codegen_->expected_safepoint_kind_ == Safepoint::kWithRegisters);
79c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  RestoreRegistersStateStub stub(codegen_->isolate());
80c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  codegen_->masm_->push(ra);
81c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  codegen_->masm_->CallStub(&stub);
82c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  codegen_->expected_safepoint_kind_ = Safepoint::kSimple;
83c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define __ masm()->
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool LCodeGen::GenerateCode() {
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LPhase phase("Z_Code generation", chunk());
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_unused());
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  status_ = GENERATING;
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Open a frame scope to indicate that there is a frame on the stack.  The
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // NONE indicates that the scope shouldn't actually generate code to set up
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the frame (that is done in GeneratePrologue).
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameScope frame_scope(masm_, StackFrame::NONE);
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return GeneratePrologue() && GenerateBody() && GenerateDeferredCode() &&
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         GenerateJumpTable() && GenerateSafepointTable();
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::FinishCode(Handle<Code> code) {
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_done());
104109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  code->set_stack_slots(GetTotalFrameSlotCount());
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PopulateDeoptimizationData(code);
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::SaveCallerDoubles() {
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(info()->saves_caller_doubles());
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(NeedsEagerFrame());
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment(";;; Save clobbered callee double registers");
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int count = 0;
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BitVector* doubles = chunk()->allocated_double_registers();
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BitVector::Iterator save_iterator(doubles);
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (!save_iterator.Done()) {
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ sdc1(DoubleRegister::from_code(save_iterator.Current()),
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            MemOperand(sp, count * kDoubleSize));
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    save_iterator.Advance();
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    count++;
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::RestoreCallerDoubles() {
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(info()->saves_caller_doubles());
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(NeedsEagerFrame());
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment(";;; Restore clobbered callee double registers");
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BitVector* doubles = chunk()->allocated_double_registers();
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BitVector::Iterator save_iterator(doubles);
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int count = 0;
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  while (!save_iterator.Done()) {
134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ldc1(DoubleRegister::from_code(save_iterator.Current()),
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            MemOperand(sp, count * kDoubleSize));
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    save_iterator.Advance();
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    count++;
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool LCodeGen::GeneratePrologue() {
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_generating());
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info()->IsOptimizing()) {
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ProfileEntryHookStub::MaybeCallEntryHook(masm_);
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // a1: Callee's JS function.
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // cp: Callee's context.
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // fp: Caller's frame pointer.
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // lr: Caller's pc.
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info()->set_prologue_offset(masm_->pc_offset());
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (NeedsEagerFrame()) {
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (info()->IsStub()) {
1573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      __ StubPrologue(StackFrame::STUB);
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ Prologue(info()->GeneratePreagedPrologue());
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    frame_is_built_ = true;
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Reserve space for the stack slots needed by the code.
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int slots = GetStackSlotCount();
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (slots > 0) {
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_debug_code) {
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Subu(sp,  sp, Operand(slots * kPointerSize));
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(a0, a1);
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Addu(a0, sp, Operand(slots *  kPointerSize));
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ li(a1, Operand(kSlotsZapValue));
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label loop;
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&loop);
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Subu(a0, a0, Operand(kPointerSize));
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ sw(a1, MemOperand(a0, 2 * kPointerSize));
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Branch(&loop, ne, a0, Operand(sp));
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(a0, a1);
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Subu(sp, sp, Operand(slots * kPointerSize));
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info()->saves_caller_doubles()) {
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SaveCallerDoubles();
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return !is_aborted();
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LCodeGen::DoPrologue(LPrologue* instr) {
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Comment(";;; Prologue begin");
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Possibly allocate a local context.
194f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (info()->scope()->NeedsContext()) {
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Comment(";;; Allocate local context");
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool need_write_barrier = true;
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Argument to NewContext is the function, which is in a1.
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int slots = info()->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Safepoint::DeoptMode deopt_mode = Safepoint::kNoLazyDeopt;
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (info()->scope()->is_script_scope()) {
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ push(a1);
202f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      __ Push(info()->scope()->scope_info());
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ CallRuntime(Runtime::kNewScriptContext);
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      deopt_mode = Safepoint::kLazyDeopt;
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
20662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (slots <=
20762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          ConstructorBuiltinsAssembler::MaximumFunctionContextSlots()) {
20862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Callable callable = CodeFactory::FastNewFunctionContext(
20962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            isolate(), info()->scope()->scope_type());
210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ li(FastNewFunctionContextDescriptor::SlotsRegister(),
211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch              Operand(slots));
21262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ Call(callable.code(), RelocInfo::CODE_TARGET);
21362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // Result of the FastNewFunctionContext builtin is always in new space.
214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        need_write_barrier = false;
215f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      } else {
216f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ push(a1);
21762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ Push(Smi::FromInt(info()->scope()->scope_type()));
218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        __ CallRuntime(Runtime::kNewFunctionContext);
219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    RecordSafepoint(deopt_mode);
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Context is returned in both v0. It replaces the context passed to us.
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // It's saved in the stack and kept live in cp.
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(cp, v0);
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(v0, MemOperand(fp, StandardFrameConstants::kContextOffset));
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Copy any necessary parameters into the context.
228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    int num_parameters = info()->scope()->num_parameters();
229f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    int first_parameter = info()->scope()->has_this_declaration() ? -1 : 0;
230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    for (int i = first_parameter; i < num_parameters; i++) {
231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Variable* var = (i == -1) ? info()->scope()->receiver()
232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                : info()->scope()->parameter(i);
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (var->IsContextSlot()) {
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            (num_parameters - 1 - i) * kPointerSize;
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Load parameter from stack.
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lw(a0, MemOperand(fp, parameter_offset));
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Store it in the context.
239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        MemOperand target = ContextMemOperand(cp, var->index());
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sw(a0, target);
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Update the write barrier. This clobbers a3 and a0.
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (need_write_barrier) {
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ RecordWriteContextSlot(
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              cp, target.offset(), a0, a3, GetRAState(), kSaveFPRegs);
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (FLAG_debug_code) {
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Label done;
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ JumpIfInNewSpace(cp, a0, &done);
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Abort(kExpectedNewSpaceObject);
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ bind(&done);
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Comment(";;; End allocate local context");
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Comment(";;; Prologue end");
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::GenerateOsrPrologue() {
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generate the OSR entry prologue at the first unknown OSR value, or if there
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // are none, at the OSR entrypoint instruction.
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (osr_pc_offset_ >= 0) return;
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  osr_pc_offset_ = masm()->pc_offset();
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Adjust the frame size, subsuming the unoptimized frame into the
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // optimized frame.
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots();
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(slots >= 0);
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Subu(sp, sp, Operand(slots * kPointerSize));
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->IsCall()) {
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!instr->IsLazyBailout() && !instr->IsGap()) {
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    safepoints_.BumpLastLazySafepointIndex();
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool LCodeGen::GenerateDeferredCode() {
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_generating());
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (deferred_.length() > 0) {
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      LDeferredCode* code = deferred_[i];
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      HValue* value =
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          instructions_->at(code->instruction_index())->hydrogen_value();
293c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      RecordAndWritePosition(value->position());
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Comment(";;; <@%d,#%d> "
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              "-------------------- Deferred %s --------------------",
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              code->instruction_index(),
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              code->instr()->hydrogen_value()->id(),
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              code->instr()->Mnemonic());
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(code->entry());
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (NeedsDeferredFrame()) {
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment(";;; Build frame");
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!frame_is_built_);
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(info()->IsStub());
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        frame_is_built_ = true;
30662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ li(scratch0(), Operand(StackFrame::TypeToMarker(StackFrame::STUB)));
3073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        __ PushCommonFrame(scratch0());
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment(";;; Deferred code");
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      code->Generate();
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (NeedsDeferredFrame()) {
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment(";;; Destroy frame");
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(frame_is_built_);
3143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        __ PopCommonFrame(scratch0());
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        frame_is_built_ = false;
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(code->exit());
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Deferred code is the last part of the instruction sequence. Mark
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the generated code as done unless we bailed out.
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!is_aborted()) status_ = DONE;
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return !is_aborted();
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::GenerateJumpTable() {
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (jump_table_.length() > 0) {
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label needs_frame, call_deopt_entry;
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment(";;; -------------------- Jump table --------------------");
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address base = jump_table_[0].address;
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register entry_offset = t9;
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int length = jump_table_.length();
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < length; i++) {
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Deoptimizer::JumpTableEntry* table_entry = &jump_table_[i];
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&table_entry->label);
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(table_entry->bailout_type == jump_table_[0].bailout_type);
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Address entry = table_entry->address;
343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DeoptComment(table_entry->deopt_info);
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Second-level deopt table entries are contiguous and small, so instead
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // of loading the full, absolute address of each one, load an immediate
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // offset which will be added to the base address later.
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ li(entry_offset, Operand(entry - base));
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (table_entry->needs_frame) {
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(!info()->saves_caller_doubles());
352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Comment(";;; call deopt with frame");
3533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        __ PushCommonFrame();
354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ Call(&needs_frame);
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ Call(&call_deopt_entry);
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (needs_frame.is_linked()) {
361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ bind(&needs_frame);
362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // This variant of deopt can only be used with stubs. Since we don't
363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // have a function pointer to install in the stack frame that we're
364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // building, install a special marker there instead.
36562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ li(at, Operand(StackFrame::TypeToMarker(StackFrame::STUB)));
366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ push(at);
3673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      DCHECK(info()->IsStub());
368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Comment(";;; call deopt");
371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&call_deopt_entry);
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (info()->saves_caller_doubles()) {
374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(info()->IsStub());
375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      RestoreCallerDoubles();
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Add the base address to the offset previously loaded in entry_offset.
379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Addu(entry_offset, entry_offset,
380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            Operand(ExternalReference::ForDeoptEntry(base)));
381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Jump(entry_offset);
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordComment("]");
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The deoptimization jump table is the last part of the instruction
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // sequence. Mark the generated code as done unless we bailed out.
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!is_aborted()) status_ = DONE;
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return !is_aborted();
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool LCodeGen::GenerateSafepointTable() {
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(is_done());
394109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  safepoints_.Emit(masm(), GetTotalFrameSlotCount());
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return !is_aborted();
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister LCodeGen::ToRegister(int index) const {
400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Register::from_code(index);
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochDoubleRegister LCodeGen::ToDoubleRegister(int index) const {
405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return DoubleRegister::from_code(index);
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister LCodeGen::ToRegister(LOperand* op) const {
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(op->IsRegister());
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ToRegister(op->index());
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) {
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (op->IsRegister()) {
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ToRegister(op->index());
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsConstantOperand()) {
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LConstantOperand* const_op = LConstantOperand::cast(op);
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HConstant* constant = chunk_->LookupConstant(const_op);
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Object> literal = constant->handle(isolate());
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Representation r = chunk_->LookupLiteralRepresentation(const_op);
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (r.IsInteger32()) {
424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      AllowDeferredHandleDereference get_number;
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(literal->IsNumber());
4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ li(scratch, Operand(static_cast<int32_t>(literal->Number())));
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (r.IsSmi()) {
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(constant->HasSmiValue());
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ li(scratch, Operand(Smi::FromInt(constant->Integer32Value())));
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (r.IsDouble()) {
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Abort(kEmitLoadRegisterUnsupportedDoubleImmediate);
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(r.IsSmiOrTagged());
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ li(scratch, literal);
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return scratch;
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (op->IsStackSlot()) {
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch, ToMemOperand(op));
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return scratch;
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return scratch;
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochDoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(op->IsDoubleRegister());
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ToDoubleRegister(op->index());
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochDoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op,
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                FloatRegister flt_scratch,
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                DoubleRegister dbl_scratch) {
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (op->IsDoubleRegister()) {
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ToDoubleRegister(op->index());
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsConstantOperand()) {
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LConstantOperand* const_op = LConstantOperand::cast(op);
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HConstant* constant = chunk_->LookupConstant(const_op);
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Object> literal = constant->handle(isolate());
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Representation r = chunk_->LookupLiteralRepresentation(const_op);
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (r.IsInteger32()) {
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(literal->IsNumber());
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ li(at, Operand(static_cast<int32_t>(literal->Number())));
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mtc1(at, flt_scratch);
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cvt_d_w(dbl_scratch, flt_scratch);
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return dbl_scratch;
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (r.IsDouble()) {
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Abort(kUnsupportedDoubleImmediate);
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (r.IsTagged()) {
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Abort(kUnsupportedTaggedImmediate);
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (op->IsStackSlot()) {
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MemOperand mem_op = ToMemOperand(op);
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldc1(dbl_scratch, mem_op);
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return dbl_scratch;
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return dbl_scratch;
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HConstant* constant = chunk_->LookupConstant(op);
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return constant->handle(isolate());
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool LCodeGen::IsInteger32(LConstantOperand* op) const {
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32();
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::IsSmi(LConstantOperand* op) const {
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return chunk_->LookupLiteralRepresentation(op).IsSmi();
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return ToRepresentation(op, Representation::Integer32());
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint32_t LCodeGen::ToRepresentation(LConstantOperand* op,
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   const Representation& r) const {
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HConstant* constant = chunk_->LookupConstant(op);
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t value = constant->Integer32Value();
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger32()) return value;
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(r.IsSmiOrTagged());
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return reinterpret_cast<int32_t>(Smi::FromInt(value));
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSmi* LCodeGen::ToSmi(LConstantOperand* op) const {
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HConstant* constant = chunk_->LookupConstant(op);
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Smi::FromInt(constant->Integer32Value());
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochdouble LCodeGen::ToDouble(LConstantOperand* op) const {
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HConstant* constant = chunk_->LookupConstant(op);
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(constant->HasDoubleValue());
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return constant->DoubleValue();
5253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochOperand LCodeGen::ToOperand(LOperand* op) {
5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (op->IsConstantOperand()) {
5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LConstantOperand* const_op = LConstantOperand::cast(op);
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HConstant* constant = chunk()->LookupConstant(const_op);
5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Representation r = chunk_->LookupLiteralRepresentation(const_op);
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (r.IsSmi()) {
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(constant->HasSmiValue());
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return Operand(Smi::FromInt(constant->Integer32Value()));
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (r.IsInteger32()) {
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(constant->HasInteger32Value());
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return Operand(constant->Integer32Value());
5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (r.IsDouble()) {
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Abort(kToOperandUnsupportedDoubleImmediate);
5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(r.IsTagged());
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Operand(constant->handle(isolate()));
5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsRegister()) {
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Operand(ToRegister(op));
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsDoubleRegister()) {
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kToOperandIsDoubleRegisterUnimplemented);
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Operand(0);
5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Stack slots not implemented, use ToMemOperand instead.
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return Operand(0);
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int ArgumentsOffsetWithoutFrame(int index) {
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(index < 0);
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return -(index + 1) * kPointerSize;
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMemOperand LCodeGen::ToMemOperand(LOperand* op) const {
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!op->IsRegister());
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!op->IsDoubleRegister());
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (NeedsEagerFrame()) {
567109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return MemOperand(fp, FrameSlotToFPOffset(op->index()));
5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Retrieve parameter without eager stack-frame relative to the
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // stack-pointer.
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return MemOperand(sp, ArgumentsOffsetWithoutFrame(op->index()));
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMemOperand LCodeGen::ToHighMemOperand(LOperand* op) const {
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(op->IsDoubleStackSlot());
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (NeedsEagerFrame()) {
579109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return MemOperand(fp, FrameSlotToFPOffset(op->index()) + kPointerSize);
5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Retrieve parameter without eager stack-frame relative to the
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // stack-pointer.
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return MemOperand(
584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        sp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize);
5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::WriteTranslation(LEnvironment* environment,
5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                Translation* translation) {
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (environment == NULL) return;
5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The translation includes one command per value in the environment.
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int translation_size = environment->translation_size();
5953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  WriteTranslation(environment->outer(), translation);
597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  WriteTranslationFrame(environment, translation);
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int object_index = 0;
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int dematerialized_index = 0;
6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < translation_size; ++i) {
6023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LOperand* value = environment->values()->at(i);
603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    AddToTranslation(
604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        environment, translation, value, environment->HasTaggedValueAt(i),
605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        environment->HasUint32ValueAt(i), &object_index, &dematerialized_index);
6063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::AddToTranslation(LEnvironment* environment,
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                Translation* translation,
6123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                LOperand* op,
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                bool is_tagged,
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                bool is_uint32,
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                int* object_index_pointer,
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                int* dematerialized_index_pointer) {
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (op == LEnvironment::materialization_marker()) {
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int object_index = (*object_index_pointer)++;
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (environment->ObjectIsDuplicateAt(object_index)) {
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int dupe_of = environment->ObjectDuplicateOfAt(object_index);
621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      translation->DuplicateObject(dupe_of);
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int object_length = environment->ObjectLengthAt(object_index);
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (environment->ObjectIsArgumentsAt(object_index)) {
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      translation->BeginArgumentsObject(object_length);
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      translation->BeginCapturedObject(object_length);
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int dematerialized_index = *dematerialized_index_pointer;
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int env_offset = environment->translation_size() + dematerialized_index;
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *dematerialized_index_pointer += object_length;
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < object_length; ++i) {
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      LOperand* value = environment->values()->at(env_offset + i);
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AddToTranslation(environment,
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       translation,
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       value,
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       environment->HasTaggedValueAt(env_offset + i),
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       environment->HasUint32ValueAt(env_offset + i),
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       object_index_pointer,
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       dematerialized_index_pointer);
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (op->IsStackSlot()) {
647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int index = op->index();
6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_tagged) {
649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      translation->StoreStackSlot(index);
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (is_uint32) {
651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      translation->StoreUint32StackSlot(index);
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      translation->StoreInt32StackSlot(index);
6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsDoubleStackSlot()) {
656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int index = op->index();
657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    translation->StoreDoubleStackSlot(index);
6583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsRegister()) {
6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register reg = ToRegister(op);
6603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (is_tagged) {
6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      translation->StoreRegister(reg);
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (is_uint32) {
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      translation->StoreUint32Register(reg);
6643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
6653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      translation->StoreInt32Register(reg);
6663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsDoubleRegister()) {
6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DoubleRegister reg = ToDoubleRegister(op);
6693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    translation->StoreDoubleRegister(reg);
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (op->IsConstantOperand()) {
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int src_index = DefineDeoptimizationLiteral(constant->handle(isolate()));
6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    translation->StoreLiteral(src_index);
6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
6753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    UNREACHABLE();
6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::CallCode(Handle<Code> code,
6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        RelocInfo::Mode mode,
6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        LInstruction* instr) {
6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::CallCodeGeneric(Handle<Code> code,
6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               RelocInfo::Mode mode,
6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               LInstruction* instr,
6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               SafepointMode safepoint_mode) {
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr != NULL);
6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Call(code, mode);
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepointWithLazyDeopt(instr, safepoint_mode);
6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::CallRuntime(const Runtime::Function* function,
6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           int num_arguments,
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           LInstruction* instr,
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           SaveFPRegsMode save_doubles) {
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr != NULL);
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(function, num_arguments, save_doubles);
7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::LoadContextFromDeferred(LOperand* context) {
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (context->IsRegister()) {
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(cp, ToRegister(context));
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (context->IsStackSlot()) {
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(cp, ToMemOperand(context));
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (context->IsConstantOperand()) {
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HConstant* constant =
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        chunk_->LookupConstant(LConstantOperand::cast(context));
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ li(cp, Handle<Object>::cast(constant->handle(isolate())));
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       int argc,
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       LInstruction* instr,
727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       LOperand* context) {
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadContextFromDeferred(context);
7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallRuntimeSaveDoubles(id);
7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepointWithRegisters(
7313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                    Safepoint::DeoptMode mode) {
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  environment->set_has_been_used();
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!environment->HasBeenRegistered()) {
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Physical stack frame layout:
7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // -x ............. -4  0 ..................................... y
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // [incoming arguments] [spill slots] [pushed outgoing arguments]
7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Layout of the environment:
7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // 0 ..................................................... size-1
7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // [parameters] [locals] [expression stack including arguments]
7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Layout of the translation:
7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // 0 ........................................................ size - 1 + 4
7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // [expression stack including arguments] [locals] [4 words] [parameters]
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // |>------------  translation_size ------------<|
7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int frame_count = 0;
7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int jsframe_count = 0;
7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ++frame_count;
7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (e->frame_type() == JS_FUNCTION) {
7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ++jsframe_count;
7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Translation translation(&translations_, frame_count, jsframe_count, zone());
7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    WriteTranslation(environment, &translation);
7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int deoptimization_index = deoptimizations_.length();
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int pc_offset = masm()->pc_offset();
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    environment->Register(deoptimization_index,
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          translation.index(),
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    deoptimizations_.Add(environment, zone());
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
772f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                            DeoptimizeReason deopt_reason,
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            Deoptimizer::BailoutType bailout_type,
774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            Register src1, const Operand& src2) {
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LEnvironment* environment = instr->environment();
7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(environment->HasBeenRegistered());
7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int id = environment->deoptimization_index();
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address entry =
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (entry == NULL) {
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kBailoutWasNotPrepared);
7833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return;
7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) {
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch = scratch0();
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalReference count = ExternalReference::stress_deopt_count(isolate());
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label no_deopt;
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(a1, scratch);
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ li(scratch, Operand(count));
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(a1, MemOperand(scratch));
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Subu(a1, a1, Operand(1));
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&no_deopt, ne, a1, Operand(zero_reg));
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ li(a1, Operand(FLAG_deopt_every_n_times));
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(a1, MemOperand(scratch));
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pop(a1, scratch);
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Call(entry, RelocInfo::RUNTIME_ENTRY);
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&no_deopt);
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(a1, MemOperand(scratch));
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pop(a1, scratch);
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info()->ShouldTrapOnDeopt()) {
8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label skip;
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (condition != al) {
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Branch(&skip, NegateCondition(condition), src1, src2);
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ stop("trap_on_deopt");
8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&skip);
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
814bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason, id);
815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(info()->IsStub() || frame_is_built_);
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Go through jump table if we need to handle condition, build frame, or
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // restore caller doubles.
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (condition == al && frame_is_built_ &&
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !info()->saves_caller_doubles()) {
821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DeoptComment(deopt_info);
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Call(entry, RelocInfo::RUNTIME_ENTRY, condition, src1, src2);
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Deoptimizer::JumpTableEntry table_entry(entry, deopt_info, bailout_type,
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            !frame_is_built_);
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We often have several deopts to the same entry, reuse the last
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // jump entry if this is the case.
82813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (FLAG_trace_deopt || isolate()->is_profiling() ||
829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        jump_table_.is_empty() ||
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        !table_entry.IsEquivalentTo(jump_table_.last())) {
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      jump_table_.Add(table_entry, zone());
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&jump_table_.last().label, condition, src1, src2);
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
838f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                            DeoptimizeReason deopt_reason, Register src1,
839f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                            const Operand& src2) {
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Deoptimizer::BailoutType bailout_type = info()->IsStub()
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? Deoptimizer::LAZY
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Deoptimizer::EAGER;
843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DeoptimizeIf(condition, instr, deopt_reason, bailout_type, src1, src2);
8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::RecordSafepointWithLazyDeopt(
8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LInstruction* instr, SafepointMode safepoint_mode) {
8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RecordSafepointWithRegisters(
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        instr->pointer_map(), 0, Safepoint::kLazyDeopt);
8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::RecordSafepoint(
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LPointerMap* pointers,
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Safepoint::Kind kind,
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int arguments,
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Safepoint::DeoptMode deopt_mode) {
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(expected_safepoint_kind_ == kind);
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands();
8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      kind, arguments, deopt_mode);
8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < operands->length(); i++) {
8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LOperand* pointer = operands->at(i);
8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (pointer->IsStackSlot()) {
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      safepoint.DefinePointerSlot(pointer->index(), zone());
8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      safepoint.DefinePointerRegister(ToRegister(pointer), zone());
8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::RecordSafepoint(LPointerMap* pointers,
8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Safepoint::DeoptMode deopt_mode) {
8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode);
8833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) {
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LPointerMap empty_pointers(zone());
8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepoint(&empty_pointers, deopt_mode);
8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            int arguments,
8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            Safepoint::DeoptMode deopt_mode) {
8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepoint(
8963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      pointers, Safepoint::kWithRegisters, arguments, deopt_mode);
8973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const char* LabelType(LLabel* label) {
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (label->is_loop_header()) return " (loop header)";
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (label->is_osr_entry()) return " (OSR entry)";
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return "";
9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLabel(LLabel* label) {
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------",
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          current_instruction_,
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          label->hydrogen_value()->id(),
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          label->block_id(),
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          LabelType(label));
9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(label->label());
9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  current_block_ = label->block_id();
9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoGap(label);
9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoParallelMove(LParallelMove* move) {
9203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  resolver_.Resolve(move);
9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoGap(LGap* gap) {
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = LGap::FIRST_INNER_POSITION;
9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       i <= LGap::LAST_INNER_POSITION;
9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       i++) {
9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LParallelMove* move = gap->GetParallelMove(inner_pos);
9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (move != NULL) DoParallelMove(move);
9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoInstructionGap(LInstructionGap* instr) {
9363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoGap(instr);
9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoParameter(LParameter* instr) {
9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Nothing to do.
9423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateOsrPrologue();
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t divisor = instr->divisor();
953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(dividend.is(ToRegister(instr->result())));
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Theoretically, a variation of the branch-free code for integer division by
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // a power of 2 (calculating the remainder via an additional multiplication
957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (which gets simplified to an 'and') and subtraction) should be faster, and
958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // indicate that positive dividends are heavily favored, so the branching
960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // version performs better.
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HMod* hmod = instr->hydrogen();
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label dividend_is_not_negative, done;
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&dividend_is_not_negative, ge, dividend, Operand(zero_reg));
967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Note: The code below even works when right contains kMinInt.
968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subu(dividend, zero_reg, dividend);
969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ And(dividend, dividend, Operand(mask));
970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
971f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, dividend,
972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   Operand(zero_reg));
973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(USE_DELAY_SLOT, &done);
975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subu(dividend, zero_reg, dividend);
976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&dividend_is_not_negative);
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ And(dividend, dividend, Operand(mask));
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoModByConstI(LModByConstI* instr) {
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t divisor = instr->divisor();
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(result));
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor == 0) {
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeoptimizeIf(al, instr);
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TruncatingDiv(result, dividend, Abs(divisor));
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mul(result, result, Operand(Abs(divisor)));
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Subu(result, dividend, Operand(result));
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for negative zero.
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HMod* hmod = instr->hydrogen();
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label remainder_not_zero;
1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&remainder_not_zero, ne, result, Operand(zero_reg));
1004f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero, dividend,
1005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(zero_reg));
1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&remainder_not_zero);
1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
10083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
10093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoModI(LModI* instr) {
1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HMod* hmod = instr->hydrogen();
1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const Register left_reg = ToRegister(instr->left());
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const Register right_reg = ToRegister(instr->right());
1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const Register result_reg = ToRegister(instr->result());
1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // div runs in the background while we check for special cases.
1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mod(result_reg, left_reg, right_reg);
10193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for x % 0, we have to deopt in this case because we can't return a
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // NaN.
1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1024f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(eq, instr, DeoptimizeReason::kDivisionByZero, right_reg,
1025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(zero_reg));
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for kMinInt % -1, div will return kMinInt, which is not what we
1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // want. We have to deopt if we care about -0, because we can't return that.
1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hmod->CheckFlag(HValue::kCanOverflow)) {
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label no_overflow_possible;
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&no_overflow_possible, ne, left_reg, Operand(kMinInt));
1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1034f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, right_reg,
1035f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   Operand(-1));
1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Branch(&no_overflow_possible, ne, right_reg, Operand(-1));
1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Branch(USE_DELAY_SLOT, &done);
1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mov(result_reg, zero_reg);
10403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&no_overflow_possible);
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If we care about -0, test if the dividend is <0 and the result is 0.
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(&done, ge, left_reg, Operand(zero_reg));
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1047f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, result_reg,
1048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(zero_reg));
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t divisor = instr->divisor();
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(dividend));
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (0 / -x) that will produce negative zero.
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HDiv* hdiv = instr->hydrogen();
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1064f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, dividend,
1065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(zero_reg));
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (kMinInt / -1).
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1069f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(eq, instr, DeoptimizeReason::kOverflow, dividend,
1070f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                 Operand(kMinInt));
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Deoptimize if remainder will not be 0.
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      divisor != 1 && divisor != -1) {
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ And(at, dividend, Operand(mask));
1077f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecision, at,
1078f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                 Operand(zero_reg));
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor == -1) {  // Nice shortcut, not needed for correctness.
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Subu(result, zero_reg, dividend);
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint16_t shift = WhichPowerOf2Abs(divisor);
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (shift == 0) {
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(result, dividend);
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (shift == 1) {
1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ srl(result, dividend, 31);
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Addu(result, dividend, Operand(result));
10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sra(result, dividend, 31);
1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ srl(result, result, 32 - shift);
1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Addu(result, dividend, Operand(result));
1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (shift > 0) __ sra(result, result, shift);
1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0) __ Subu(result, zero_reg, result);
1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
10993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t divisor = instr->divisor();
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(result));
11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor == 0) {
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeoptimizeIf(al, instr);
1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (0 / -x) that will produce negative zero.
1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HDiv* hdiv = instr->hydrogen();
1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, dividend,
1116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(zero_reg));
1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TruncatingDiv(result, dividend, Abs(divisor));
1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0) __ Subu(result, zero_reg, result);
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Mul(scratch0(), result, Operand(divisor));
1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Subu(scratch0(), scratch0(), dividend);
1125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecision, scratch0(),
1126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(zero_reg));
11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
11293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDivI(LDivI* instr) {
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HBinaryOperation* hdiv = instr->hydrogen();
1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register divisor = ToRegister(instr->divisor());
11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const Register result = ToRegister(instr->result());
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register remainder = ToRegister(instr->temp());
11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // On MIPS div is asynchronous - it will run in the background while we
11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // check for special cases.
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Div(remainder, result, dividend, divisor);
11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for x / 0.
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1145f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(eq, instr, DeoptimizeReason::kDivisionByZero, divisor,
1146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(zero_reg));
11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for (0 / -x) that will produce negative zero.
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label left_not_zero;
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg));
1153f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero, divisor,
1154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(zero_reg));
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&left_not_zero);
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (kMinInt / -1).
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kCanOverflow) &&
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label left_not_min_int;
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt));
1163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(eq, instr, DeoptimizeReason::kOverflow, divisor, Operand(-1));
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&left_not_min_int);
1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecision, remainder,
1169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(zero_reg));
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) {
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister addend = ToDoubleRegister(instr->addend());
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister multiplier = ToDoubleRegister(instr->multiplier());
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand());
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This is computed in-place.
1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(addend.is(ToDoubleRegister(instr->result())));
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ madd_d(addend, addend, multiplier, multiplicand);
1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t divisor = instr->divisor();
1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = result.is(dividend) ? scratch0() : dividend;
1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(dividend) || !scratch.is(dividend));
1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the divisor is 1, return the dividend.
1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor == 1) {
1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(result, dividend);
1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the divisor is positive, things are easy: There can be no deopts and we
1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // can simply do an arithmetic right shift.
1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint16_t shift = WhichPowerOf2Abs(divisor);
1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor > 1) {
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sra(result, dividend, shift);
1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the divisor is negative, we have to negate and handle edge cases.
1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // dividend can be the same register as result so save the value of it
1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for checking overflow.
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(scratch, dividend);
1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Subu(result, zero_reg, dividend);
12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1215f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, result,
1216f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                 Operand(zero_reg));
1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Dividing by -1 is basically negation, unless we overflow.
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Xor(scratch, scratch, result);
1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor == -1) {
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(ge, instr, DeoptimizeReason::kOverflow, scratch,
1224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   Operand(zero_reg));
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the negation could not overflow, simply shifting is OK.
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sra(result, result, shift);
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_overflow, done;
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(&no_overflow, lt, scratch, Operand(zero_reg));
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ li(result, Operand(kMinInt / divisor));
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(&done);
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&no_overflow);
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sra(result, result, shift);
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t divisor = instr->divisor();
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!dividend.is(result));
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor == 0) {
1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeoptimizeIf(al, instr);
1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (0 / -x) that will produce negative zero.
1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HMathFloorOfDiv* hdiv = instr->hydrogen();
1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, dividend,
1260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(zero_reg));
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Easy case: We need no dynamic check for the dividend and the flooring
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // division is the same as the truncating division.
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ TruncatingDiv(result, dividend, Abs(divisor));
1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (divisor < 0) __ Subu(result, zero_reg, result);
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // In the general case we may need to adjust before and after the truncating
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // division to get a flooring division.
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp = ToRegister(instr->temp());
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!temp.is(dividend) && !temp.is(result));
1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label needs_adjustment, done;
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(&needs_adjustment, divisor > 0 ? lt : gt,
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            dividend, Operand(zero_reg));
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TruncatingDiv(result, dividend, Abs(divisor));
1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0) __ Subu(result, zero_reg, result);
1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done);
1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&needs_adjustment);
1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(temp, dividend, Operand(divisor > 0 ? 1 : -1));
1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TruncatingDiv(result, temp, Abs(divisor));
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (divisor < 0) __ Subu(result, zero_reg, result);
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Subu(result, result, Operand(1));
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(svenpanne) Refactor this to avoid code duplication with DoDivI.
1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HBinaryOperation* hdiv = instr->hydrogen();
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dividend = ToRegister(instr->dividend());
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register divisor = ToRegister(instr->divisor());
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const Register result = ToRegister(instr->result());
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register remainder = scratch0();
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // On MIPS div is asynchronous - it will run in the background while we
1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // check for special cases.
1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Div(remainder, result, dividend, divisor);
1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for x / 0.
1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1304f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(eq, instr, DeoptimizeReason::kDivisionByZero, divisor,
1305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(zero_reg));
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (0 / -x) that will produce negative zero.
1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label left_not_zero;
1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg));
1312f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero, divisor,
1313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(zero_reg));
13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&left_not_zero);
13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for (kMinInt / -1).
1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hdiv->CheckFlag(HValue::kCanOverflow) &&
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
13203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label left_not_min_int;
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt));
1322f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(eq, instr, DeoptimizeReason::kOverflow, divisor, Operand(-1));
13233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&left_not_min_int);
13243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We performed a truncating division. Correct the result if necessary.
1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT);
1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Xor(remainder, remainder, Operand(divisor));
1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(&done, ge, remainder, Operand(zero_reg));
1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Subu(result, result, Operand(1));
1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
13333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoMulI(LMulI* instr) {
13373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
13383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
13393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Note that result may alias left.
1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register left = ToRegister(instr->left());
1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* right_op = instr->right();
13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool bailout_on_minus_zero =
13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (right_op->IsConstantOperand()) {
13483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
13493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (bailout_on_minus_zero && (constant < 0)) {
13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // The case of a null constant will be handled separately.
13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // If constant is negative and left is null, the result should be -0.
1353f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, left,
1354f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   Operand(zero_reg));
13553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
13563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (constant) {
13583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case -1:
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (overflow) {
1360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Label no_overflow;
1361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ SubBranchNoOvf(result, zero_reg, Operand(left), &no_overflow);
1362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          DeoptimizeIf(al, instr);
1363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ bind(&no_overflow);
1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Subu(result, zero_reg, left);
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case 0:
13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (bailout_on_minus_zero) {
13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // If left is strictly negative and the constant is null, the
13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // result is -0. Deoptimize if required, otherwise return 0.
1372f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero, left,
1373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       Operand(zero_reg));
13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
13753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ mov(result, zero_reg);
13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case 1:
13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Nothing to do.
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Move(result, left);
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      default:
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Multiplying by powers of two and powers of two plus or minus
13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // one can be done faster with shifted operands.
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // For other constants we emit standard code.
13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int32_t mask = constant >> 31;
13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        uint32_t constant_abs = (constant + mask) ^ mask;
13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (base::bits::IsPowerOfTwo32(constant_abs)) {
1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          int32_t shift = WhichPowerOf2(constant_abs);
1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ sll(result, left, shift);
1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // Correct the sign of the result if the constant is negative.
1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (constant < 0)  __ Subu(result, zero_reg, result);
1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (base::bits::IsPowerOfTwo32(constant_abs - 1)) {
1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          int32_t shift = WhichPowerOf2(constant_abs - 1);
1395109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          __ Lsa(result, left, left, shift);
1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // Correct the sign of the result if the constant is negative.
1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (constant < 0)  __ Subu(result, zero_reg, result);
1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (base::bits::IsPowerOfTwo32(constant_abs + 1)) {
1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          int32_t shift = WhichPowerOf2(constant_abs + 1);
1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ sll(scratch, left, shift);
1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Subu(result, scratch, left);
1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // Correct the sign of the result if the constant is negative.
1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (constant < 0)  __ Subu(result, zero_reg, result);
14043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
14053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Generate standard code.
14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ li(at, constant);
14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Mul(result, left, at);
14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(right_op->IsRegister());
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register right = ToRegister(right_op);
14143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (overflow) {
14163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // hi:lo = left * right.
1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (instr->hydrogen()->representation().IsSmi()) {
1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ SmiUntag(result, left);
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Mul(scratch, result, result, right);
1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Mul(scratch, result, left, right);
1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sra(at, result, 31);
1424f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(ne, instr, DeoptimizeReason::kOverflow, scratch,
1425f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   Operand(at));
14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (instr->hydrogen()->representation().IsSmi()) {
1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ SmiUntag(result, left);
1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Mul(result, result, right);
1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Mul(result, left, right);
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (bailout_on_minus_zero) {
14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label done;
1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Xor(at, left, right);
1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Branch(&done, ge, at, Operand(zero_reg));
1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Bail out if the result is minus zero.
1440f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, result,
1441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   Operand(zero_reg));
14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&done);
14433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoBitI(LBitI* instr) {
1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* left_op = instr->left();
1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* right_op = instr->right();
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(left_op->IsRegister());
14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register left = ToRegister(left_op);
14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Operand right(no_reg);
14553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (right_op->IsStackSlot()) {
14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    right = Operand(EmitLoadRegister(right_op, at));
14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(right_op->IsRegister() || right_op->IsConstantOperand());
14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    right = ToOperand(right_op);
14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (instr->op()) {
14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::BIT_AND:
14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ And(result, left, right);
14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::BIT_OR:
14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Or(result, left, right);
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::BIT_XOR:
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (right_op->IsConstantOperand() && right.immediate() == int32_t(~0)) {
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Nor(result, zero_reg, left);
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Xor(result, left, right);
1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default:
14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNREACHABLE();
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoShiftI(LShiftI* instr) {
14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so
14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // result may alias either of them.
1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* right_op = instr->right();
1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register left = ToRegister(instr->left());
14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = scratch0();
14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (right_op->IsRegister()) {
14933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // No need to mask the right operand on MIPS, it is built into the variable
14943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // shift instructions.
14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (instr->op()) {
1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::ROR:
1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Ror(result, left, Operand(ToRegister(right_op)));
1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Token::SAR:
15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ srav(result, left, ToRegister(right_op));
15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Token::SHR:
15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ srlv(result, left, ToRegister(right_op));
15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (instr->can_deopt()) {
1505f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          DeoptimizeIf(lt, instr, DeoptimizeReason::kNegativeValue, result,
1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       Operand(zero_reg));
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Token::SHL:
15103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sllv(result, left, ToRegister(right_op));
15113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      default:
15133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        UNREACHABLE();
15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Mask the right_op operand.
15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int value = ToInteger32(LConstantOperand::cast(right_op));
15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (instr->op()) {
1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case Token::ROR:
1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (shift_count != 0) {
1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Ror(result, left, Operand(shift_count));
1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Move(result, left);
1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Token::SAR:
15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (shift_count != 0) {
15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ sra(result, left, shift_count);
15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Move(result, left);
15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Token::SHR:
15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (shift_count != 0) {
15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ srl(result, left, shift_count);
15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (instr->can_deopt()) {
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            __ And(at, left, Operand(0x80000000));
1541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            DeoptimizeIf(ne, instr, DeoptimizeReason::kNegativeValue, at,
1542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         Operand(zero_reg));
15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Move(result, left);
15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
15463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case Token::SHL:
15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (shift_count != 0) {
1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (instr->hydrogen_value()->representation().IsSmi() &&
1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              instr->can_deopt()) {
1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            if (shift_count != 1) {
1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              __ sll(result, left, shift_count - 1);
1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              __ SmiTagCheckOverflow(result, result, scratch);
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            } else {
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              __ SmiTagCheckOverflow(result, left, scratch);
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            }
1557f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            DeoptimizeIf(lt, instr, DeoptimizeReason::kOverflow, scratch,
1558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                         Operand(zero_reg));
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else {
1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            __ sll(result, left, shift_count);
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          }
15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ Move(result, left);
15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      default:
15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        UNREACHABLE();
15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoSubI(LSubI* instr) {
1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* left = instr->left();
1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* right = instr->right();
15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* result = instr->result();
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!can_overflow) {
1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (right->IsStackSlot()) {
15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register right_reg = EmitLoadRegister(right, at);
15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Subu(ToRegister(result), ToRegister(left), Operand(right_reg));
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(right->IsRegister() || right->IsConstantOperand());
15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Subu(ToRegister(result), ToRegister(left), ToOperand(right));
15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {  // can_overflow.
1589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Register scratch = scratch0();
1590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label no_overflow_label;
1591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (right->IsStackSlot()) {
15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register right_reg = EmitLoadRegister(right, scratch);
1593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ SubBranchNoOvf(ToRegister(result), ToRegister(left),
1594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        Operand(right_reg), &no_overflow_label);
15953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
1596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(right->IsRegister() || right->IsConstantOperand());
1597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ SubBranchNoOvf(ToRegister(result), ToRegister(left), ToOperand(right),
1598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        &no_overflow_label, scratch);
15993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DeoptimizeIf(al, instr);
1601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&no_overflow_label);
16023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
16033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoConstantI(LConstantI* instr) {
1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ li(ToRegister(instr->result()), Operand(instr->value()));
1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoConstantS(LConstantS* instr) {
16123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(ToRegister(instr->result()), Operand(instr->value()));
16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoConstantD(LConstantD* instr) {
1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->result()->IsDoubleRegister());
16183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister result = ToDoubleRegister(instr->result());
16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  double v = instr->value();
16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(result, v);
16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoConstantE(LConstantE* instr) {
1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ li(ToRegister(instr->result()), Operand(instr->value()));
16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoConstantT(LConstantT* instr) {
1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> object = instr->value(isolate());
1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference smi_check;
1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ li(ToRegister(instr->result()), object);
16333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemOperand LCodeGen::BuildSeqStringOperand(Register string,
1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           LOperand* index,
1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           String::Encoding encoding) {
1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (index->IsConstantOperand()) {
1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int offset = ToInteger32(LConstantOperand::cast(index));
1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (encoding == String::TWO_BYTE_ENCODING) {
1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      offset *= kUC16Size;
1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kCharSize == 1);
1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return FieldMemOperand(string, SeqString::kHeaderSize + offset);
1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = scratch0();
1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch.is(string));
1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch.is(ToRegister(index)));
1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (encoding == String::ONE_BYTE_ENCODING) {
1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Addu(scratch, string, ToRegister(index));
1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kUC16Size == 2);
1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sll(scratch, ToRegister(index), 1);
1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Addu(scratch, string, scratch);
1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return FieldMemOperand(scratch, SeqString::kHeaderSize);
1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) {
1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Encoding encoding = instr->hydrogen()->encoding();
1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register string = ToRegister(instr->string());
16643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch = scratch0();
1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(scratch, FieldMemOperand(string, HeapObject::kMapOffset));
1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ And(scratch, scratch,
1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           Operand(kStringRepresentationMask | kStringEncodingMask));
1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Subu(at, scratch, Operand(encoding == String::ONE_BYTE_ENCODING
1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                ? one_byte_seq_type : two_byte_seq_type));
1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(eq, kUnexpectedStringType, at, Operand(zero_reg));
1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding);
1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (encoding == String::ONE_BYTE_ENCODING) {
1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lbu(result, operand);
1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lhu(result, operand);
1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
16863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
16873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  String::Encoding encoding = instr->hydrogen()->encoding();
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register string = ToRegister(instr->string());
1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value = ToRegister(instr->value());
16933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch = scratch0();
1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register index = ToRegister(instr->index());
1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int encoding_mask =
1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING
1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ? one_byte_seq_type : two_byte_seq_type;
1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ EmitSeqStringSetCharCheck(string, index, value, scratch, encoding_mask);
1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding);
1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (encoding == String::ONE_BYTE_ENCODING) {
1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sb(value, operand);
1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sh(value, operand);
17103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
17113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
17123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoAddI(LAddI* instr) {
1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* left = instr->left();
1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* right = instr->right();
17173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* result = instr->result();
17183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
17193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!can_overflow) {
1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (right->IsStackSlot()) {
17223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register right_reg = EmitLoadRegister(right, at);
17233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(ToRegister(result), ToRegister(left), Operand(right_reg));
17243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
1725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(right->IsRegister() || right->IsConstantOperand());
17263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(ToRegister(result), ToRegister(left), ToOperand(right));
17273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
17283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {  // can_overflow.
17293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = scratch1();
1730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label no_overflow_label;
1731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (right->IsStackSlot()) {
17323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register right_reg = EmitLoadRegister(right, scratch);
1733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ AddBranchNoOvf(ToRegister(result), ToRegister(left),
1734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        Operand(right_reg), &no_overflow_label);
17353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
1736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(right->IsRegister() || right->IsConstantOperand());
1737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ AddBranchNoOvf(ToRegister(result), ToRegister(left), ToOperand(right),
1738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        &no_overflow_label, scratch);
17393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DeoptimizeIf(al, instr);
1741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&no_overflow_label);
1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathMinMax(LMathMinMax* instr) {
1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* left = instr->left();
1748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* right = instr->right();
1749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HMathMinMax::Operation operation = instr->hydrogen()->operation();
1750bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register scratch = scratch1();
1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
1752bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge;
1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register left_reg = ToRegister(left);
1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register right_reg = EmitLoadRegister(right, scratch0());
1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register result_reg = ToRegister(instr->result());
1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label return_right, done;
1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Slt(scratch, left_reg, Operand(right_reg));
1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (condition == ge) {
1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch     __  Movz(result_reg, left_reg, scratch);
1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch     __  Movn(result_reg, right_reg, scratch);
1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch     DCHECK(condition == le);
1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch     __  Movn(result_reg, left_reg, scratch);
1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch     __  Movz(result_reg, right_reg, scratch);
1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(instr->hydrogen()->representation().IsDouble());
1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FPURegister left_reg = ToDoubleRegister(left);
1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FPURegister right_reg = ToDoubleRegister(right);
1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FPURegister result_reg = ToDoubleRegister(instr->result());
177162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1772bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Label nan, done;
1773bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (operation == HMathMinMax::kMathMax) {
177462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Float64Max(result_reg, left_reg, right_reg, &nan);
1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1776bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      DCHECK(operation == HMathMinMax::kMathMin);
177762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Float64Min(result_reg, left_reg, right_reg, &nan);
1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&done);
1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1781bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    __ bind(&nan);
178262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ add_d(result_reg, left_reg, right_reg);
1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
17853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
17863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
17873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoArithmeticD(LArithmeticD* instr) {
1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister left = ToDoubleRegister(instr->left());
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister right = ToDoubleRegister(instr->right());
17923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister result = ToDoubleRegister(instr->result());
17933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (instr->op()) {
17943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::ADD:
17953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ add_d(result, left, right);
17963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
17973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::SUB:
17983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sub_d(result, left, right);
17993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
18003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::MUL:
18013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mul_d(result, left, right);
18023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
18033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::DIV:
18043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ div_d(result, left, right);
18053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
18063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::MOD: {
18073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Save a0-a3 on the stack.
18083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      RegList saved_regs = a0.bit() | a1.bit() | a2.bit() | a3.bit();
18093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ MultiPush(saved_regs);
18103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ PrepareCallCFunction(0, 2, scratch0());
1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ MovToFloatParameters(left, right);
18133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CallCFunction(
1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ExternalReference::mod_two_doubles_operation(isolate()),
18153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          0, 2);
18163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Move the result in the double result register.
1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ MovFromFloatResult(result);
18183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Restore saved register.
18203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ MultiPop(saved_regs);
18213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
18223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
18233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default:
18243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNREACHABLE();
18253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
18263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
18273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoArithmeticT(LArithmeticT* instr) {
1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(cp));
1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->left()).is(a1));
1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->right()).is(a0));
1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->result()).is(v0));
1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1836109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), instr->op()).code();
1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallCode(code, RelocInfo::CODE_TARGET, instr);
18383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Other arch use a nop here, to signal that there is no inlined
18393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // patchable code. Mips does not need the nop, since our marker
18403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // instruction (andi zero_reg) will never be used in normal code.
18413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class InstrType>
1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitBranch(InstrType instr,
1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          Condition condition,
1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          Register src1,
1848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          const Operand& src2) {
1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int left_block = instr->TrueDestination(chunk_);
1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int right_block = instr->FalseDestination(chunk_);
18513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int next_block = GetNextEmittedBlock();
1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (right_block == left_block || condition == al) {
18543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitGoto(left_block);
18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (left_block == next_block) {
18563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(chunk_->GetAssemblyLabel(right_block),
1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              NegateCondition(condition), src1, src2);
18583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (right_block == next_block) {
1859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(chunk_->GetAssemblyLabel(left_block), condition, src1, src2);
18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(chunk_->GetAssemblyLabel(left_block), condition, src1, src2);
18623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(chunk_->GetAssemblyLabel(right_block));
18633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
18643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class InstrType>
1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitBranchF(InstrType instr,
1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           Condition condition,
1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           FPURegister src1,
1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           FPURegister src2) {
1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int right_block = instr->FalseDestination(chunk_);
1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int left_block = instr->TrueDestination(chunk_);
1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int next_block = GetNextEmittedBlock();
18763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (right_block == left_block) {
18773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitGoto(left_block);
18783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (left_block == next_block) {
18793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ BranchF(chunk_->GetAssemblyLabel(right_block), NULL,
1880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch               NegateFpuCondition(condition), src1, src2);
18813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (right_block == next_block) {
1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL,
1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               condition, src1, src2);
18843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL,
1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               condition, src1, src2);
18873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(chunk_->GetAssemblyLabel(right_block));
18883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
18893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
18903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <class InstrType>
1893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LCodeGen::EmitTrueBranch(InstrType instr, Condition condition,
1894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              Register src1, const Operand& src2) {
1895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int true_block = instr->TrueDestination(chunk_);
1896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Branch(chunk_->GetAssemblyLabel(true_block), condition, src1, src2);
1897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <class InstrType>
1901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LCodeGen::EmitFalseBranch(InstrType instr, Condition condition,
1902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               Register src1, const Operand& src2) {
1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int false_block = instr->FalseDestination(chunk_);
1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(chunk_->GetAssemblyLabel(false_block), condition, src1, src2);
1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class InstrType>
1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitFalseBranchF(InstrType instr,
1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                Condition condition,
1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                FPURegister src1,
1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                FPURegister src2) {
1913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int false_block = instr->FalseDestination(chunk_);
1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ BranchF(chunk_->GetAssemblyLabel(false_block), NULL,
1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             condition, src1, src2);
1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
19173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDebugBreak(LDebugBreak* instr) {
1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ stop("LDebugBreak");
1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoBranch(LBranch* instr) {
19253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Representation r = instr->hydrogen()->value()->representation();
1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (r.IsInteger32() || r.IsSmi()) {
1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!info()->IsStub());
1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register reg = ToRegister(instr->value());
1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitBranch(instr, ne, reg, Operand(zero_reg));
19303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (r.IsDouble()) {
1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!info()->IsStub());
1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoubleRegister reg = ToDoubleRegister(instr->value());
19333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Test the double value. Zero and NaN are false.
1934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    EmitBranchF(instr, ogl, reg, kDoubleRegZero);
19353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(r.IsTagged());
1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register reg = ToRegister(instr->value());
19383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HType type = instr->hydrogen()->value()->type();
19393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (type.IsBoolean()) {
1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!info()->IsStub());
19413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(at, Heap::kTrueValueRootIndex);
1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitBranch(instr, eq, reg, Operand(at));
19433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (type.IsSmi()) {
1944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!info()->IsStub());
1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitBranch(instr, ne, reg, Operand(zero_reg));
1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (type.IsJSArray()) {
1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!info()->IsStub());
1948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitBranch(instr, al, zero_reg, Operand(zero_reg));
1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (type.IsHeapNumber()) {
1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!info()->IsStub());
1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DoubleRegister dbl_scratch = double_scratch0();
1952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Test the double value. Zero and NaN are false.
1954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      EmitBranchF(instr, ogl, dbl_scratch, kDoubleRegZero);
1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (type.IsString()) {
1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(!info()->IsStub());
1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lw(at, FieldMemOperand(reg, String::kLengthOffset));
1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitBranch(instr, ne, at, Operand(zero_reg));
19593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
1960c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      ToBooleanHints expected = instr->hydrogen()->expected_input_types();
19613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Avoid deopts in the case where we've never executed this path before.
1962c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny;
19633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1964c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kUndefined) {
19653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // undefined -> false.
19663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at));
19683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
1969c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kBoolean) {
19703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Boolean -> its value.
19713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(at, Heap::kTrueValueRootIndex);
1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Branch(instr->TrueLabel(chunk_), eq, reg, Operand(at));
19733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(at, Heap::kFalseValueRootIndex);
1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at));
19753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
1976c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kNull) {
19773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // 'null' -> false.
19783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(at, Heap::kNullValueRootIndex);
1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at));
19803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
19813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1982c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kSmallInteger) {
19833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Smis: 0 -> false, all other -> true.
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(zero_reg));
1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
1986c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      } else if (expected & ToBooleanHint::kNeedsMap) {
19873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // If we need a map later and have a Smi -> deopt.
1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ SmiTst(reg, at);
1989f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, at, Operand(zero_reg));
19903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
19913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      const Register map = scratch0();
1993c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kNeedsMap) {
19943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lw(map, FieldMemOperand(reg, HeapObject::kMapOffset));
1995c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        if (expected & ToBooleanHint::kCanBeUndetectable) {
19963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Undetectable -> false.
19973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset));
19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          __ And(at, at, Operand(1 << Map::kIsUndetectable));
1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          __ Branch(instr->FalseLabel(chunk_), ne, at, Operand(zero_reg));
20003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
20013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
20023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2003c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kReceiver) {
20043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // spec object -> true.
20053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Branch(instr->TrueLabel(chunk_),
2007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  ge, at, Operand(FIRST_JS_RECEIVER_TYPE));
20083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
20093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2010c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kString) {
20113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // String value -> false iff empty.
20123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label not_string;
20133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
20143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(&not_string, ge , at, Operand(FIRST_NONSTRING_TYPE));
20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lw(at, FieldMemOperand(reg, String::kLengthOffset));
2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Branch(instr->TrueLabel(chunk_), ne, at, Operand(zero_reg));
2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Branch(instr->FalseLabel(chunk_));
20183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&not_string);
20193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
20203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2021c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kSymbol) {
2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Symbol value -> true.
2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        const Register scratch = scratch1();
2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Branch(instr->TrueLabel(chunk_), eq, scratch, Operand(SYMBOL_TYPE));
2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2028c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected & ToBooleanHint::kHeapNumber) {
20293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // heap number -> false iff +0, -0, or NaN.
20303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        DoubleRegister dbl_scratch = double_scratch0();
20313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Label not_heap_number;
20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
20333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ Branch(&not_heap_number, ne, map, Operand(at));
20343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ ldc1(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ BranchF(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   ne, dbl_scratch, kDoubleRegZero);
20373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Falls through if dbl_scratch == 0.
2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Branch(instr->FalseLabel(chunk_));
20393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ bind(&not_heap_number);
20403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
20413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2042c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (expected != ToBooleanHint::kAny) {
2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // We've seen something for the first time -> deopt.
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // This can only happen if we are not generic already.
2045f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        DeoptimizeIf(al, instr, DeoptimizeReason::kUnexpectedObject, zero_reg,
2046958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                     Operand(zero_reg));
2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
20483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
20493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
20503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
20513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EmitGoto(int block) {
2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!IsNextEmittedBlock(block)) {
2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
20563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
20573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
20583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoGoto(LGoto* instr) {
20613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EmitGoto(instr->block_id());
20623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
20633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20653ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochCondition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
20663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition cond = kNoCondition;
20673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (op) {
20683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::EQ:
20693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::EQ_STRICT:
20703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cond = eq;
20713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::NE:
2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case Token::NE_STRICT:
2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      cond = ne;
2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
20763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::LT:
20773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cond = is_unsigned ? lo : lt;
20783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
20793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::GT:
20803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cond = is_unsigned ? hi : gt;
20813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
20823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::LTE:
20833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cond = is_unsigned ? ls : le;
20843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
20853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::GTE:
20863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      cond = is_unsigned ? hs : ge;
20873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
20883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::IN:
20893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::INSTANCEOF:
20903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default:
20913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNREACHABLE();
20923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
20933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return cond;
20943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
20953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* left = instr->left();
2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* right = instr->right();
2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_unsigned =
2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->hydrogen()->left()->CheckFlag(HInstruction::kUint32) ||
2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->hydrogen()->right()->CheckFlag(HInstruction::kUint32);
2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition cond = TokenToCondition(instr->op(), is_unsigned);
21043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (left->IsConstantOperand() && right->IsConstantOperand()) {
21063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We can statically evaluate the comparison.
21073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    double left_val = ToDouble(LConstantOperand::cast(left));
21083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    double right_val = ToDouble(LConstantOperand::cast(right));
2109109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int next_block = Token::EvalComparison(instr->op(), left_val, right_val)
2110109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                         ? instr->TrueDestination(chunk_)
2111109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                         : instr->FalseDestination(chunk_);
21123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitGoto(next_block);
21133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
21143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->is_double()) {
21153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Compare left and right as doubles and load the
21163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // resulting flags into the normal status register.
21173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FPURegister left_reg = ToDoubleRegister(left);
21183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FPURegister right_reg = ToDoubleRegister(right);
21193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // If a NaN is involved, i.e. the result is unordered,
21213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // jump to false block label.
2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ BranchF(NULL, instr->FalseLabel(chunk_), eq,
21233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 left_reg, right_reg);
21243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitBranchF(instr, cond, left_reg, right_reg);
21263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
21273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Register cmp_left;
21283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Operand cmp_right = Operand(0);
21293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (right->IsConstantOperand()) {
2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int32_t value = ToInteger32(LConstantOperand::cast(right));
2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (instr->hydrogen_value()->representation().IsSmi()) {
2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          cmp_left = ToRegister(left);
2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          cmp_right = Operand(Smi::FromInt(value));
2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          cmp_left = ToRegister(left);
2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          cmp_right = Operand(value);
2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
21393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (left->IsConstantOperand()) {
2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        int32_t value = ToInteger32(LConstantOperand::cast(left));
2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (instr->hydrogen_value()->representation().IsSmi()) {
2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           cmp_left = ToRegister(right);
2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           cmp_right = Operand(Smi::FromInt(value));
2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          cmp_left = ToRegister(right);
2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          cmp_right = Operand(value);
2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // We commuted the operands, so commute the condition.
2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        cond = CommuteCondition(cond);
21503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
21513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        cmp_left = ToRegister(left);
21523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        cmp_right = Operand(ToRegister(right));
21533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
21543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitBranch(instr, cond, cmp_left, cmp_right);
21563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
21573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
21583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register left = ToRegister(instr->left());
2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register right = ToRegister(instr->right());
21643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, eq, left, Operand(right));
21663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->representation().IsTagged()) {
2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register input_reg = ToRegister(instr->object());
2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ li(at, Operand(factory()->the_hole_value()));
2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitBranch(instr, eq, input_reg, Operand(at));
2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister input_reg = ToDoubleRegister(instr->object());
2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitFalseBranchF(instr, eq, input_reg, input_reg);
21793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ FmoveHigh(scratch, input_reg);
2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, eq, scratch, Operand(kHoleNanUpper32));
2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
21843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21863ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochCondition LCodeGen::EmitIsString(Register input,
21873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register temp1,
2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Label* is_not_string,
2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 SmiCheck check_needed = INLINE_SMI_CHECK) {
2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (check_needed == INLINE_SMI_CHECK) {
2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input, is_not_string);
2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
21933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(input, temp1, temp1);
21943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return lt;
21963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg = ToRegister(instr->value());
2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp1 = ToRegister(instr->temp());
22023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmiCheck check_needed =
2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->hydrogen()->value()->type().IsHeapObject()
2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
22063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition true_cond =
2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitIsString(reg, temp1, instr->FalseLabel(chunk_), check_needed);
22083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, true_cond, temp1,
22103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             Operand(FIRST_NONSTRING_TYPE));
22113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input_reg = EmitLoadRegister(instr->value(), at);
22163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, input_reg, kSmiTagMask);
2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, eq, at, Operand(zero_reg));
22183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp = ToRegister(instr->temp());
22243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(temp, FieldMemOperand(input, HeapObject::kMapOffset));
22293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lbu(temp, FieldMemOperand(temp, Map::kBitFieldOffset));
22303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, temp, Operand(1 << Map::kIsUndetectable));
2231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, ne, at, Operand(zero_reg));
22323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic Condition ComputeCompareCondition(Token::Value op) {
22363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (op) {
22373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::EQ_STRICT:
22383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::EQ:
22393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return eq;
22403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::LT:
22413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return lt;
22423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::GT:
22433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return gt;
22443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::LTE:
22453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return le;
22463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::GTE:
22473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ge;
22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default:
22493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNREACHABLE();
22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return kNoCondition;
22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(cp));
2257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(ToRegister(instr->left()).is(a1));
2258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(ToRegister(instr->right()).is(a0));
22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Handle<Code> code = CodeFactory::StringCompare(isolate(), instr->op()).code();
2261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallCode(code, RelocInfo::CODE_TARGET, instr);
22623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ LoadRoot(at, Heap::kTrueValueRootIndex);
22633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  EmitBranch(instr, eq, v0, Operand(at));
22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstanceType from = instr->from();
22693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstanceType to = instr->to();
22703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (from == FIRST_TYPE) return to;
2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(from == to || to == LAST_TYPE);
22723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return from;
22733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
22773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstanceType from = instr->from();
22783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstanceType to = instr->to();
22793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (from == to) return eq;
22803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (to == LAST_TYPE) return hs;
22813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (from == FIRST_TYPE) return ls;
22823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
22833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return eq;
22843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
22853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
22883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
22903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
22943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(input, scratch, scratch);
2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr,
22973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             BranchCondition(instr->hydrogen()),
22983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             scratch,
22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             Operand(TestType(instr->hydrogen())));
23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Branches to a label or falls through with the answer in flags.  Trashes
23033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// the temp registers, but not the input.
23043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EmitClassOfTest(Label* is_true,
23053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Label* is_false,
23063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Handle<String>class_name,
23073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register input,
23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register temp,
23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               Register temp2) {
2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input.is(temp));
2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input.is(temp2));
2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!temp.is(temp2));
23133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(input, is_false);
2315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ GetObjectType(input, temp, temp2);
23163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
23183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ Branch(is_true, hs, temp2, Operand(FIRST_FUNCTION_TYPE));
23193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
23203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ Branch(is_false, hs, temp2, Operand(FIRST_FUNCTION_TYPE));
23213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
23223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the constructor in the map is a function.
2324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register instance_type = scratch1();
2325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(!instance_type.is(temp));
2326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ GetMapConstructor(temp, temp, temp2, instance_type);
23273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Objects with a non-function constructor have class 'Object'.
2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (String::Equals(class_name, isolate()->factory()->Object_string())) {
2330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Branch(is_true, ne, instance_type, Operand(JS_FUNCTION_TYPE));
23313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Branch(is_false, ne, instance_type, Operand(JS_FUNCTION_TYPE));
23333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
23343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // temp now contains the constructor function. Grab the
23363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // instance class name from there.
23373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset));
23383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(temp, FieldMemOperand(temp,
23393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               SharedFunctionInfo::kInstanceClassNameOffset));
2340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The class name we are testing against is internalized since it's a literal.
2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The name in the constructor is internalized because of the way the context
2342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // is booted.  This routine isn't expected to work for random API-created
23433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // classes and it doesn't have to because you can't access it with natives
2344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // syntax.  Since both sides are internalized it is sufficient to use an
2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // identity comparison.
23463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // End with the address of this class_name instance in temp register.
23483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // On MIPS, the caller must do the comparison with Handle<String>class_name.
23493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
23543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp = scratch0();
2355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp2 = ToRegister(instr->temp());
23563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> class_name = instr->hydrogen()->class_name();
23573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
2359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  class_name, input, temp, temp2);
23603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, eq, temp, Operand(class_name));
23623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg = ToRegister(instr->value());
2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp = ToRegister(instr->temp());
23683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBranch(instr, eq, temp, Operand(instr->map()));
23713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
23723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LCodeGen::DoHasInPrototypeChainAndBranch(
2375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LHasInPrototypeChainAndBranch* instr) {
2376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register const object = ToRegister(instr->object());
2377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register const object_map = scratch0();
2378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register const object_instance_type = scratch1();
2379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register const object_prototype = object_map;
2380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register const prototype = ToRegister(instr->prototype());
23813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // The {object} must be a spec object.  It's sufficient to know that {object}
2383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // is not a smi, since all other non-spec objects have {null} prototypes and
2384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // will be ruled out below.
2385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (instr->hydrogen()->ObjectNeedsSmiCheck()) {
2386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ SmiTst(object, at);
2387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    EmitFalseBranch(instr, eq, at, Operand(zero_reg));
2388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
23893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Loop through the {object}s prototype chain looking for the {prototype}.
2391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ lw(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
2392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label loop;
2393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&loop);
23943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Deoptimize if the object needs to be access checked.
2396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ lbu(object_instance_type,
2397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         FieldMemOperand(object_map, Map::kBitFieldOffset));
2398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ And(object_instance_type, object_instance_type,
2399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         Operand(1 << Map::kIsAccessCheckNeeded));
2400f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(ne, instr, DeoptimizeReason::kAccessCheck, object_instance_type,
2401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch               Operand(zero_reg));
2402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Deoptimize for proxies.
2403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ lbu(object_instance_type,
2404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         FieldMemOperand(object_map, Map::kInstanceTypeOffset));
2405f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(eq, instr, DeoptimizeReason::kProxy, object_instance_type,
2406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch               Operand(JS_PROXY_TYPE));
24073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ lw(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset));
2409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(at, Heap::kNullValueRootIndex);
2410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  EmitFalseBranch(instr, eq, object_prototype, Operand(at));
241113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  EmitTrueBranch(instr, eq, object_prototype, Operand(prototype));
2412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Branch(USE_DELAY_SLOT, &loop);
2413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ lw(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset));
24143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
24153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCmpT(LCmpT* instr) {
2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(cp));
24193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Token::Value op = instr->op();
24203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2421109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
24223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(ic, RelocInfo::CODE_TARGET, instr);
24233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // On MIPS there is no need for a "no inlined smi code" marker (nop).
24243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition condition = ComputeCompareCondition(op);
24263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // A minor optimization that relies on LoadRoot always emitting one
24273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // instruction.
24283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm());
2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, check;
24303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(USE_DELAY_SLOT, &done, condition, v0, Operand(zero_reg));
2431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&check);
24323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
2433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(1, masm()->InstructionsGeneratedSince(&check));
24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
24353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
24363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
24373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoReturn(LReturn* instr) {
2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trace && info()->IsOptimizing()) {
24413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Push the return value on the stack as the parameter.
2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Runtime::TraceExit returns its parameter in v0. We're leaving the code
2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // managed by the register allocator and tearing down the frame, it's
2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // safe to write to the context register.
24453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(v0);
2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kTraceExit);
24483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info()->saves_caller_doubles()) {
2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RestoreCallerDoubles();
2451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (NeedsEagerFrame()) {
2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(sp, fp);
2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pop(ra, fp);
2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->has_constant_parameter_count()) {
2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int parameter_count = ToInteger32(instr->constant_parameter_count());
2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t sp_delta = (parameter_count + 1) * kPointerSize;
2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (sp_delta != 0) {
2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Addu(sp, sp, Operand(sp_delta));
2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(info()->IsStub());  // Functions would need to drop one more value.
2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register reg = ToRegister(instr->parameter_count());
2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The argument count parameter is a smi
2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiUntag(reg);
2467109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Lsa(sp, sp, reg, kPointerSizeLog2);
2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Jump(ra);
24713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
24723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
24753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register context = ToRegister(instr->context());
24763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
24773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ lw(result, ContextMemOperand(context, instr->slot_index()));
24793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->RequiresHoleCheck()) {
24803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
24813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->hydrogen()->DeoptimizesOnHole()) {
2483f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, result, Operand(at));
24843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
24853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label is_not_hole;
24863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&is_not_hole, ne, result, Operand(at));
24873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
24883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&is_not_hole);
24893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
24903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
24913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
24923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
24953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register context = ToRegister(instr->context());
24963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register value = ToRegister(instr->value());
24973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
2498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MemOperand target = ContextMemOperand(context, instr->slot_index());
24993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label skip_assignment;
25013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->RequiresHoleCheck()) {
25033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch, target);
25043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
25053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->hydrogen()->DeoptimizesOnHole()) {
2507f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, scratch, Operand(at));
25083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
25093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&skip_assignment, ne, scratch, Operand(at));
25103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
25123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sw(value, target);
25143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->NeedsWriteBarrier()) {
25153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmiCheck check_needed =
2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->hydrogen()->value()->type().IsHeapObject()
2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ RecordWriteContextSlot(context,
25193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              target.offset(),
25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              value,
25213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              scratch0(),
2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              GetRAState(),
25233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              kSaveFPRegs,
25243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              EMIT_REMEMBERED_SET,
25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              check_needed);
25263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
25273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&skip_assignment);
25293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
25303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HObjectAccess access = instr->hydrogen()->access();
2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = access.offset();
2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register object = ToRegister(instr->object());
2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (access.IsExternalMemory()) {
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register result = ToRegister(instr->result());
2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand operand = MemOperand(object, offset);
2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Load(result, operand, access.representation());
2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
25423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
25433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->representation().IsDouble()) {
2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoubleRegister result = ToDoubleRegister(instr->result());
2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldc1(result, FieldMemOperand(object, offset));
2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
25493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!access.IsInobject()) {
2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
2553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object = result;
25543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemOperand operand = FieldMemOperand(object, offset);
2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Load(result, operand, access.representation());
25573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
25583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
25613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
25623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register function = ToRegister(instr->function());
25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
25643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the prototype or initial map from the function.
25663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result,
25673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
25683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that the function has a prototype or an initial map.
25703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
2571f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, result, Operand(at));
25723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the function does not have an initial map, we're done.
25743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
25753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(result, scratch, scratch);
25763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&done, ne, scratch, Operand(MAP_TYPE));
25773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the prototype from the initial map.
25793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(result, Map::kPrototypeOffset));
25803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // All done.
25823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
25833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
25843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadRoot(LLoadRoot* instr) {
25873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(result, instr->index());
25893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
25933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register arguments = ToRegister(instr->arguments());
25943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // There are two words between the frame pointer and the last argument.
2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Subtracting from length accounts for one of them add one more.
2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->length()->IsConstantOperand()) {
2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->index()->IsConstantOperand()) {
2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int index = (const_length - const_index) + 1;
2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lw(result, MemOperand(arguments, index * kPointerSize));
2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register index = ToRegister(instr->index());
2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ li(at, Operand(const_length + 1));
2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Subu(result, at, index);
2607109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Lsa(at, arguments, result, kPointerSizeLog2);
2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lw(result, MemOperand(at));
2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (instr->index()->IsConstantOperand()) {
2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register length = ToRegister(instr->length());
2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int loc = const_index - 1;
2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (loc != 0) {
2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Subu(result, length, Operand(loc));
2616109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Lsa(at, arguments, result, kPointerSizeLog2);
2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lw(result, MemOperand(at));
2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2619109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Lsa(at, arguments, length, kPointerSizeLog2);
2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lw(result, MemOperand(at));
26213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
26223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register length = ToRegister(instr->length());
2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register index = ToRegister(instr->index());
2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Subu(result, length, index);
2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Addu(result, result, 1);
2627109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Lsa(at, arguments, result, kPointerSizeLog2);
2628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(result, MemOperand(at));
26293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
26303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
26313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register external_pointer = ToRegister(instr->elements());
26353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register key = no_reg;
26363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsKind elements_kind = instr->elements_kind();
26373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool key_is_constant = instr->key()->IsConstantOperand();
26383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int constant_key = 0;
26393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (key_is_constant) {
26403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
26413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (constant_key & 0xF0000000) {
2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Abort(kArrayIndexConstantValueTooBig);
26433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
26443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
26453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    key = ToRegister(instr->key());
26463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int element_size_shift = ElementsKindToShiftSize(elements_kind);
2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? (element_size_shift - kSmiTagSize) : element_size_shift;
2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int base_offset = instr->base_offset();
2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (elements_kind == FLOAT32_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) {
26533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FPURegister result = ToDoubleRegister(instr->result());
26543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (key_is_constant) {
2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Addu(scratch0(), external_pointer, constant_key << element_size_shift);
26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
26573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sll(scratch0(), key, shift_size);
26583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Addu(scratch0(), scratch0(), external_pointer);
26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (elements_kind == FLOAT32_ELEMENTS) {
2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lwc1(result, MemOperand(scratch0(), base_offset));
26623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cvt_d_s(result, result);
26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else  {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldc1(result, MemOperand(scratch0(), base_offset));
26653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
26663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
26673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register result = ToRegister(instr->result());
2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand mem_operand = PrepareKeyedOperand(
2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        key, external_pointer, key_is_constant, constant_key,
2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        element_size_shift, shift_size, base_offset);
26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (elements_kind) {
2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case INT8_ELEMENTS:
26733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lb(result, mem_operand);
26743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
2675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT8_ELEMENTS:
2676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT8_CLAMPED_ELEMENTS:
26773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lbu(result, mem_operand);
26783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case INT16_ELEMENTS:
26803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lh(result, mem_operand);
26813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT16_ELEMENTS:
26833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lhu(result, mem_operand);
26843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case INT32_ELEMENTS:
26863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lw(result, mem_operand);
26873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT32_ELEMENTS:
26893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ lw(result, mem_operand);
2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
2691f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          DeoptimizeIf(Ugreater_equal, instr, DeoptimizeReason::kNegativeValue,
2692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                       result, Operand(0x80000000));
2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
26943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FLOAT32_ELEMENTS:
2696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FLOAT64_ELEMENTS:
26973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_DOUBLE_ELEMENTS:
26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_ELEMENTS:
2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_SMI_ELEMENTS:
2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_HOLEY_DOUBLE_ELEMENTS:
2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_HOLEY_ELEMENTS:
2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_HOLEY_SMI_ELEMENTS:
27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case DICTIONARY_ELEMENTS:
2704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
2705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
2706109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case FAST_STRING_WRAPPER_ELEMENTS:
2707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case SLOW_STRING_WRAPPER_ELEMENTS:
2708109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case NO_ELEMENTS:
27093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        UNREACHABLE();
27103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
27113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
27123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
27143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
27153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register elements = ToRegister(instr->elements());
2718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool key_is_constant = instr->key()->IsConstantOperand();
2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register key = no_reg;
2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister result = ToDoubleRegister(instr->result());
2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = scratch0();
2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
2724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int base_offset = instr->base_offset();
2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (key_is_constant) {
2727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
2728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (constant_key & 0xF0000000) {
2729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Abort(kArrayIndexConstantValueTooBig);
2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    base_offset += constant_key * kDoubleSize;
2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(scratch, elements, Operand(base_offset));
2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!key_is_constant) {
2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    key = ToRegister(instr->key());
2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ? (element_size_shift - kSmiTagSize) : element_size_shift;
2739109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Lsa(scratch, scratch, key, shift_size);
2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldc1(result, MemOperand(scratch));
2743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->RequiresHoleCheck()) {
2745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(scratch, MemOperand(scratch, kHoleNanUpper32Offset));
2746f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, scratch,
2747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(kHoleNanUpper32));
2748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register elements = ToRegister(instr->elements());
2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = scratch0();
2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register store_base = scratch;
2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = instr->base_offset();
2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->key()->IsConstantOperand()) {
2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
2761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    offset += ToInteger32(const_operand) * kPointerSize;
2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    store_base = elements;
2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register key = ToRegister(instr->key());
2765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Even though the HLoadKeyed instruction forces the input
2766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // representation for the key to be an integer, the input gets replaced
2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // during bound check elimination with the index argument to the bounds
2768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // check, which can be tagged, so that case must be handled here, too.
2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->hydrogen()->key()->representation().IsSmi()) {
2770109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Lsa(scratch, elements, key, kPointerSizeLog2 - kSmiTagSize);
2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2772109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Lsa(scratch, elements, key, kPointerSizeLog2);
2773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lw(result, MemOperand(store_base, offset));
2776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check for the hole value.
2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->RequiresHoleCheck()) {
2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ SmiTst(result, scratch);
2781f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(ne, instr, DeoptimizeReason::kNotASmi, scratch,
2782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   Operand(zero_reg));
2783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
2785f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(eq, instr, DeoptimizeReason::kHole, result,
2786f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   Operand(scratch));
2787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (instr->hydrogen()->hole_mode() == CONVERT_HOLE_TO_UNDEFINED) {
2789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(instr->hydrogen()->elements_kind() == FAST_HOLEY_ELEMENTS);
2790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label done;
2791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
2792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Branch(&done, ne, result, Operand(scratch));
2793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (info()->IsStub()) {
2794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // A stub can safely convert the hole to undefined only if the array
2795c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // protector cell contains (Smi) Isolate::kProtectorValid. Otherwise
2796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // it needs to bail out.
2797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ LoadRoot(result, Heap::kArrayProtectorRootIndex);
279862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ lw(result, FieldMemOperand(result, PropertyCell::kValueOffset));
2799f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(ne, instr, DeoptimizeReason::kHole, result,
2800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                   Operand(Smi::FromInt(Isolate::kProtectorValid)));
2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
2803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&done);
2804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
2809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (instr->is_fixed_typed_array()) {
2810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoLoadKeyedExternalArray(instr);
2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (instr->hydrogen()->representation().IsDouble()) {
2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoLoadKeyedFixedDoubleArray(instr);
2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoLoadKeyedFixedArray(instr);
2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemOperand LCodeGen::PrepareKeyedOperand(Register key,
2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         Register base,
2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         bool key_is_constant,
2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         int constant_key,
2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         int element_size,
2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         int shift_size,
2825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                         int base_offset) {
2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (key_is_constant) {
2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return MemOperand(base, (constant_key << element_size) + base_offset);
2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (base_offset == 0) {
2831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (shift_size >= 0) {
2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ sll(scratch0(), key, shift_size);
2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Addu(scratch0(), base, scratch0());
2834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return MemOperand(scratch0());
2835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
2836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK_EQ(-1, shift_size);
2837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ srl(scratch0(), key, 1);
2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Addu(scratch0(), base, scratch0());
2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return MemOperand(scratch0());
2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (shift_size >= 0) {
2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sll(scratch0(), key, shift_size);
2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Addu(scratch0(), base, scratch0());
2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return MemOperand(scratch0(), base_offset);
2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(-1, shift_size);
2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sra(scratch0(), key, 1);
2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Addu(scratch0(), base, scratch0());
2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return MemOperand(scratch0(), base_offset);
2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
28563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
28573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
28583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register temp = scratch1();
28593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
28603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->from_inlined()) {
2862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Subu(result, sp, 2 * kPointerSize);
28633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else if (instr->hydrogen()->arguments_adaptor()) {
2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check if the calling frame is an arguments adaptor frame.
2865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done, adapted;
2866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
28673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ lw(result,
28683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          MemOperand(scratch, CommonFrameConstants::kContextOrFrameTypeOffset));
286962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Xor(temp, result,
287062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch           Operand(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR)));
2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Result is the frame pointer for the frame if not adapted and for the real
2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // frame below the adaptor frame if adapted.
2874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Movn(result, fp, temp);  // Move only if temp is not equal to zero (ne).
2875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Movz(result, scratch, temp);  // Move only if temp is equal to zero (eq).
28763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
28773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ mov(result, fp);
2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
28793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register elem = ToRegister(instr->elements());
28843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
28853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
28873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If no arguments adaptor frame the number of arguments is fixed.
28893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(result, zero_reg, Operand(scope()->num_parameters()));
28903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&done, eq, fp, Operand(elem));
28913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Arguments adaptor frame present. Get argument length from there.
28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
28943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result,
28953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset));
28963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiUntag(result);
28973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Argument length is in result register.
28993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
29003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
29013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
29043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register receiver = ToRegister(instr->receiver());
29053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register function = ToRegister(instr->function());
2906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
29073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
29083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the receiver is null or undefined, we have to pass the global
29103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // object as a receiver to normal functions. Values have to be
29113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // passed unchanged to builtins and strict-mode functions.
2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label global_object, result_in_receiver;
2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!instr->hydrogen()->known_function()) {
2915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Do not transform the receiver to object for strict mode
2916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // functions.
2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(scratch,
2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
2919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(scratch,
2920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Do not transform the receiver to object for builtins.
2923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t strict_mode_function_mask =
2924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        1 <<  (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize);
2925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t native_mask = 1 << (SharedFunctionInfo::kNative + kSmiTagSize);
2926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ And(scratch, scratch, Operand(strict_mode_function_mask | native_mask));
2927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&result_in_receiver, ne, scratch, Operand(zero_reg));
2928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
29293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Normal function. Replace undefined or null with global receiver.
29313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(scratch, Heap::kNullValueRootIndex);
29323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&global_object, eq, receiver, Operand(scratch));
29333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
29343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&global_object, eq, receiver, Operand(scratch));
29353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Deoptimize if the receiver is not a JS object.
2937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTst(receiver, scratch);
2938f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, scratch, Operand(zero_reg));
29393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(receiver, scratch, scratch);
2941f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(lt, instr, DeoptimizeReason::kNotAJavaScriptObject, scratch,
2942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch               Operand(FIRST_JS_RECEIVER_TYPE));
29433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(&result_in_receiver);
29453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&global_object);
2946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lw(result, FieldMemOperand(function, JSFunction::kContextOffset));
2947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ lw(result, ContextMemOperand(result, Context::NATIVE_CONTEXT_INDEX));
2948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ lw(result, ContextMemOperand(result, Context::GLOBAL_PROXY_INDEX));
2949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (result.is(receiver)) {
2951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&result_in_receiver);
2952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label result_ok;
2954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&result_ok);
2955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&result_in_receiver);
2956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(result, receiver);
2957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&result_ok);
2958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
29593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
29603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
29623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoApplyArguments(LApplyArguments* instr) {
29633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register receiver = ToRegister(instr->receiver());
29643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register function = ToRegister(instr->function());
29653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register length = ToRegister(instr->length());
29663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register elements = ToRegister(instr->elements());
29673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
2968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(receiver.is(a0));  // Used for parameter count.
2969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(function.is(a1));  // Required by InvokeFunction.
2970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->result()).is(v0));
29713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Copy the arguments to this function possibly from the
29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // adaptor frame below it.
29743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const uint32_t kArgumentsLimit = 1 * KB;
2975f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(hi, instr, DeoptimizeReason::kTooManyArguments, length,
2976958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               Operand(kArgumentsLimit));
29773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the receiver and use the register to keep the original
29793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // number of arguments.
29803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(receiver);
29813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(receiver, length);
29823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The arguments are at a one pointer size offset from elements.
29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(elements, elements, Operand(1 * kPointerSize));
29843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Loop through the arguments pushing them onto the execution
29863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // stack.
29873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label invoke, loop;
29883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // length is a small non-negative integer, due to the test above.
29893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(USE_DELAY_SLOT, &invoke, eq, length, Operand(zero_reg));
29903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sll(scratch, length, 2);
29913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&loop);
29923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(scratch, elements, scratch);
29933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch, MemOperand(scratch));
29943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(scratch);
29953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Subu(length, length, Operand(1));
29963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(USE_DELAY_SLOT, &loop, ne, length, Operand(zero_reg));
29973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sll(scratch, length, 2);
29983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&invoke);
30003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
30013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  InvokeFlag flag = CALL_FUNCTION;
30023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (instr->hydrogen()->tail_call_mode() == TailCallMode::kAllow) {
30033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!info()->saves_caller_doubles());
30043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // TODO(ishell): drop current frame before pushing arguments to the stack.
30053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    flag = JUMP_FUNCTION;
30063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ParameterCount actual(a0);
30073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // It is safe to use t0, t1 and t2 as scratch registers here given that
30083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // we are not going to return to caller function anyway.
30093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    PrepareForTailCall(actual, t0, t1, t2);
30103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
30113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->HasPointerMap());
30133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LPointerMap* pointers = instr->pointer_map();
30143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt);
30153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The number of arguments is stored in receiver which is a0, as expected
30163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // by InvokeFunction.
30173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ParameterCount actual(receiver);
30183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ InvokeFunction(function, no_reg, actual, flag, safepoint_generator);
30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoPushArgument(LPushArgument* instr) {
3023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* argument = instr->value();
30243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
3025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Abort(kDoPushArgumentNotImplementedForDoubleType);
30263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
30273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register argument_reg = EmitLoadRegister(argument, at);
30283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(argument_reg);
30293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDrop(LDrop* instr) {
3034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Drop(instr->count());
30353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoThisFunction(LThisFunction* instr) {
30393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
3040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lw(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
30413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoContext(LContext* instr) {
3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If there is a non-return use, the context must be moved to a register.
30463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
3047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info()->IsOptimizing()) {
3048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(result, MemOperand(fp, StandardFrameConstants::kContextOffset));
3049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If there is no frame, the context must be in cp.
3051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(result.is(cp));
3052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
3057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(cp));
305862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ li(scratch0(), instr->hydrogen()->declarations());
30593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(scratch1(), Operand(Smi::FromInt(instr->hydrogen()->flags())));
3060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Push(scratch0(), scratch1());
3061f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ li(scratch0(), instr->hydrogen()->feedback_vector());
3062f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ Push(scratch0());
3063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallRuntime(Runtime::kDeclareGlobals, instr);
30643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
30653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::CallKnownFunction(Handle<JSFunction> function,
3067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 int formal_parameter_count, int arity,
30683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                 bool is_tail_call, LInstruction* instr) {
3069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool dont_adapt_arguments =
3070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool can_invoke_directly =
3072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      dont_adapt_arguments || formal_parameter_count == arity;
30733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register function_reg = a1;
30753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LPointerMap* pointers = instr->pointer_map();
30763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (can_invoke_directly) {
3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Change context.
3079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ lw(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset));
3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Always initialize new target and number of actual arguments.
3082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
3083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(a0, Operand(arity));
30843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    bool is_self_call = function.is_identical_to(info()->closure());
30863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
30873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Invoke function.
30883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (is_self_call) {
30893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Handle<Code> self(reinterpret_cast<Code**>(__ CodeObject().location()));
30903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (is_tail_call) {
30913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        __ Jump(self, RelocInfo::CODE_TARGET);
30923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else {
30933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        __ Call(self, RelocInfo::CODE_TARGET);
30943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
30953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
30963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      __ lw(at, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset));
30973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (is_tail_call) {
30983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        __ Jump(at);
30993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else {
31003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        __ Call(at);
31013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
31023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
31033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (!is_tail_call) {
31053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      // Set up deoptimization.
31063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
31073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
31083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
31093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
31103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ParameterCount actual(arity);
3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ParameterCount expected(formal_parameter_count);
31123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION;
31133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ InvokeFunction(function_reg, expected, actual, flag, generator);
31143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
31153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
31163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->context() != NULL);
3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(cp));
3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
31223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
31233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
31243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Deoptimize if not a heap number.
31263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
31273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
3128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch,
3129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch               Operand(at));
31303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
31323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register exponent = scratch0();
31333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scratch = no_reg;
31343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
31353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check the sign of the argument. If the argument is positive, just
31363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // return it.
31373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(result, input);
31383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(at, exponent, Operand(HeapNumber::kSignMask));
31393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&done, eq, at, Operand(zero_reg));
31403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Input is negative. Reverse its sign.
31423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Preserve the value of all registers.
31433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PushSafepointRegistersScope scope(this);
31453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Registers were saved at the safepoint, so we can use
31473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // many scratch registers.
31483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register tmp1 = input.is(a1) ? a0 : a1;
31493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register tmp2 = input.is(a2) ? a0 : a2;
31503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register tmp3 = input.is(a3) ? a0 : a3;
31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register tmp4 = input.is(t0) ? a0 : t0;
31523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // exponent: floating point exponent value.
31543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label allocated, slow;
31563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(tmp4, Heap::kHeapNumberMapRootIndex);
31573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateHeapNumber(tmp1, tmp2, tmp3, tmp4, &slow);
31583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&allocated);
31593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Slow case: Call the runtime system to do the number allocation.
31613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&slow);
31623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr,
3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            instr->context());
31653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Set the pointer to the new heap number in tmp.
31663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!tmp1.is(v0))
31673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ mov(tmp1, v0);
31683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore input_reg after call to runtime.
31693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadFromSafepointRegisterSlot(input, input);
31703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
31713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&allocated);
31733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // exponent: floating point exponent value.
31743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // tmp1: allocated heap number.
31753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(exponent, exponent, Operand(~HeapNumber::kSignMask));
31763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
31773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
31783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
31793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ StoreToSafepointRegisterSlot(tmp1, result);
31813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
31823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
31843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
31853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
31863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
31893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
31903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
31913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
31923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg));
31933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(result, input);
31943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ subu(result, zero_reg, input);
31953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Overflow if result is still negative, i.e. 0x80000000.
3196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(lt, instr, DeoptimizeReason::kOverflow, result,
3197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch               Operand(zero_reg));
31983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
31993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathAbs(LMathAbs* instr) {
32033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Class for deferred case.
3204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredMathAbsTaggedHeapNumber final : public LDeferredCode {
32053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
3206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr)
32073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
3208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override {
32093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
32103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
3212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
32133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
3214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LMathAbs* instr_;
32153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
32163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Representation r = instr->hydrogen()->value()->representation();
32183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (r.IsDouble()) {
3219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FPURegister input = ToDoubleRegister(instr->value());
32203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FPURegister result = ToDoubleRegister(instr->result());
32213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ abs_d(result, input);
3222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (r.IsSmiOrInteger32()) {
32233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitIntegerMathAbs(instr);
32243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
32253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Representation is tagged.
32263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredMathAbsTaggedHeapNumber* deferred =
3227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr);
3228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register input = ToRegister(instr->value());
32293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Smi check.
32303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfNotSmi(input, deferred->entry());
32313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If smi, handle it directly.
32323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitIntegerMathAbs(instr);
32333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(deferred->exit());
32343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
32353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathFloor(LMathFloor* instr) {
3239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister input = ToDoubleRegister(instr->value());
32403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
32413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch1 = scratch0();
3242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register except_flag = ToRegister(instr->temp());
32433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ EmitFPUTruncate(kRoundToMinusInf,
3245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     result,
32463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     input,
32473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     scratch1,
3248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     double_scratch0(),
32493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     except_flag);
32503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Deopt if the operation did not succeed.
3252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecisionOrNaN, except_flag,
3253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               Operand(zero_reg));
32543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
32563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Test for -0.
32573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
32583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done, ne, result, Operand(zero_reg));
3259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Mfhc1(scratch1, input);
32603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
3261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch1,
3262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(zero_reg));
32633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&done);
32643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
32653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
32663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathRound(LMathRound* instr) {
3269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister input = ToDoubleRegister(instr->value());
32703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
3271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp());
32723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
32733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done, check_sign_on_zero;
32743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Extract exponent bits.
3276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mfhc1(result, input);
32773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Ext(scratch,
32783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         result,
32793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         HeapNumber::kExponentShift,
32803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         HeapNumber::kExponentBits);
32813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the number is in ]-0.5, +0.5[, the result is +/- 0.
32833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label skip1;
32843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&skip1, gt, scratch, Operand(HeapNumber::kExponentBias - 2));
32853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(result, zero_reg);
32863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
32873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&check_sign_on_zero);
32883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
32893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done);
32903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
32913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&skip1);
32923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The following conversion will not work with numbers
32943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // outside of ]-2^32, 2^32[.
3295f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(ge, instr, DeoptimizeReason::kOverflow, scratch,
3296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               Operand(HeapNumber::kExponentBias + 32));
32973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
32983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Save the original sign for later comparison.
32993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ And(scratch, result, Operand(HeapNumber::kSignMask));
33003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(double_scratch0(), 0.5);
33023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add_d(double_scratch0(), input, double_scratch0());
33033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check sign of the result: if the sign changed, the input
33053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // value was in ]0.5, 0[ and the result should be -0.
3306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Mfhc1(result, double_scratch0());
33073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Xor(result, result, Operand(scratch));
33083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
33093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ARM uses 'mi' here, which is 'lt'
3310f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(lt, instr, DeoptimizeReason::kMinusZero, result,
3311f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                 Operand(zero_reg));
33123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
33133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label skip2;
33143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ARM uses 'mi' here, which is 'lt'
33153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Negating it results in 'ge'
33163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&skip2, ge, result, Operand(zero_reg));
33173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mov(result, zero_reg);
33183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done);
33193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&skip2);
33203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
33213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register except_flag = scratch;
33233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ EmitFPUTruncate(kRoundToMinusInf,
33243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     result,
3325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     double_scratch0(),
3326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     at,
3327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     double_scratch1,
33283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     except_flag);
33293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3330f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecisionOrNaN, except_flag,
3331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               Operand(zero_reg));
33323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
33343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Test for -0.
33353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done, ne, result, Operand(zero_reg));
33363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&check_sign_on_zero);
3337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Mfhc1(scratch, input);
33383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(scratch, scratch, Operand(HeapNumber::kSignMask));
3339f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch,
3340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(zero_reg));
33413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
33423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
33433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathFround(LMathFround* instr) {
3347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister input = ToDoubleRegister(instr->value());
3348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister result = ToDoubleRegister(instr->result());
3349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cvt_s_d(result.low(), input);
3350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cvt_d_s(result, result.low());
3351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathSqrt(LMathSqrt* instr) {
3355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister input = ToDoubleRegister(instr->value());
33563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister result = ToDoubleRegister(instr->result());
33573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sqrt_d(result, input);
33583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
3362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister input = ToDoubleRegister(instr->value());
33633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister result = ToDoubleRegister(instr->result());
3364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister temp = ToDoubleRegister(instr->temp());
33653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input.is(result));
33673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Note that according to ECMA-262 15.8.2.13:
33693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Math.pow(-Infinity, 0.5) == Infinity
33703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Math.sqrt(-Infinity) == NaN
33713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
3372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Move(temp, static_cast<double>(-V8_INFINITY));
3373f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Set up Infinity.
3374f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ Neg_d(result, temp);
3375f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // result is overwritten if the branch is not taken.
3376f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ BranchF(&done, NULL, eq, temp, input);
33773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Add +0 to convert -0 to +0.
33793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add_d(result, input, kDoubleRegZero);
33803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sqrt_d(result, result);
33813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
33823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
33833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoPower(LPower* instr) {
33863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Representation exponent_type = instr->hydrogen()->right()->representation();
33873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Having marked this as a call, we can use any registers.
33883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Just make sure that the input/output registers are the expected ones.
3389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register tagged_exponent = MathPowTaggedDescriptor::exponent();
3390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!instr->right()->IsDoubleRegister() ||
3391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         ToDoubleRegister(instr->right()).is(f4));
3392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!instr->right()->IsRegister() ||
3393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         ToRegister(instr->right()).is(tagged_exponent));
3394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToDoubleRegister(instr->left()).is(f2));
3395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToDoubleRegister(instr->result()).is(f0));
3396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (exponent_type.IsSmi()) {
3398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MathPowStub stub(isolate(), MathPowStub::TAGGED);
3399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallStub(&stub);
3400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (exponent_type.IsTagged()) {
34013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label no_deopt;
3402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(tagged_exponent, &no_deopt);
3403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!t3.is(tagged_exponent));
3404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(t3, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset));
3405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
3406f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, t3, Operand(at));
34073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&no_deopt);
3408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MathPowStub stub(isolate(), MathPowStub::TAGGED);
34093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
34103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (exponent_type.IsInteger32()) {
3411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MathPowStub stub(isolate(), MathPowStub::INTEGER);
34123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
34133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
3414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(exponent_type.IsDouble());
3415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MathPowStub stub(isolate(), MathPowStub::DOUBLE);
34163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallStub(&stub);
34173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
34183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
34193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
342013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid LCodeGen::DoMathCos(LMathCos* instr) {
342113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ PrepareCallCFunction(0, 1, scratch0());
342213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
342313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 0, 1);
342413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
342513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
34263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
342713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid LCodeGen::DoMathSin(LMathSin* instr) {
342813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ PrepareCallCFunction(0, 1, scratch0());
342913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
343013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 0, 1);
343113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
343213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
34333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
343413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid LCodeGen::DoMathExp(LMathExp* instr) {
343513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ PrepareCallCFunction(0, 1, scratch0());
343613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
343713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 0, 1);
343813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
34393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
34403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathLog(LMathLog* instr) {
3443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PrepareCallCFunction(0, 1, scratch0());
3444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
344513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
3446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
34473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
34483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathClz32(LMathClz32* instr) {
3451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
3452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
3453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Clz(result, input);
34543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
34553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
34563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid LCodeGen::PrepareForTailCall(const ParameterCount& actual,
34573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                  Register scratch1, Register scratch2,
34583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                  Register scratch3) {
34593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#if DEBUG
34603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (actual.is_reg()) {
34613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(actual.reg(), scratch1, scratch2, scratch3));
34623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
34633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!AreAliased(scratch1, scratch2, scratch3));
34643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
34653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif
34663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (FLAG_code_comments) {
34673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (actual.is_reg()) {
346813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Comment(";;; PrepareForTailCall, actual: %s {",
346913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch              RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
347013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                  actual.reg().code()));
34713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else {
34723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
34733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
34743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
34753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
34763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Check if next frame is an arguments adaptor frame.
34773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Register caller_args_count_reg = scratch1;
34783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label no_arguments_adaptor, formal_parameter_count_loaded;
34793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ lw(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
34803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ lw(scratch3, MemOperand(scratch2, StandardFrameConstants::kContextOffset));
34813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Branch(&no_arguments_adaptor, ne, scratch3,
348262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Operand(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR)));
34833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
34843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Drop current frame and load arguments count from arguments adaptor frame.
34853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ mov(fp, scratch2);
34863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ lw(caller_args_count_reg,
34873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
34883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ SmiUntag(caller_args_count_reg);
34893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Branch(&formal_parameter_count_loaded);
34903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
34913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ bind(&no_arguments_adaptor);
34923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Load caller's formal parameter count
34933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ lw(scratch1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
34943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ lw(scratch1,
34953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        FieldMemOperand(scratch1, JSFunction::kSharedFunctionInfoOffset));
34963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ li(caller_args_count_reg, Operand(info()->literal()->parameter_count()));
34973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
34983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ bind(&formal_parameter_count_loaded);
34993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ PrepareForTailCall(actual, caller_args_count_reg, scratch2, scratch3);
35003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
35013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Comment(";;; }");
35023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
35033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
35053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HInvokeFunction* hinstr = instr->hydrogen();
3506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(cp));
3507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->function()).is(a1));
3508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->HasPointerMap());
3509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
35103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bool is_tail_call = hinstr->tail_call_mode() == TailCallMode::kAllow;
35113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
35123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (is_tail_call) {
35133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(!info()->saves_caller_doubles());
35143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ParameterCount actual(instr->arity());
35153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // It is safe to use t0, t1 and t2 as scratch registers here given that
35163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // we are not going to return to caller function anyway.
35173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    PrepareForTailCall(actual, t0, t1, t2);
35183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
35193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
35203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Handle<JSFunction> known_function = hinstr->known_function();
3521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (known_function.is_null()) {
3522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LPointerMap* pointers = instr->pointer_map();
3523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
35243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ParameterCount actual(instr->arity());
35253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION;
35263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ InvokeFunction(a1, no_reg, actual, flag, generator);
3527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
35283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    CallKnownFunction(known_function, hinstr->formal_parameter_count(),
35293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                      instr->arity(), is_tail_call, instr);
3530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
35313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
35323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
3535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->result()).is(v0));
3536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (instr->hydrogen()->IsTailCall()) {
3538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL);
3539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (instr->target()->IsConstantOperand()) {
3541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      LConstantOperand* target = LConstantOperand::cast(instr->target());
3542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Handle<Code> code = Handle<Code>::cast(ToHandle(target));
3543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ Jump(code, RelocInfo::CODE_TARGET);
3544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
3545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(instr->target()->IsRegister());
3546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Register target = ToRegister(instr->target());
3547958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ Addu(target, target, Operand(Code::kHeaderSize - kHeapObjectTag));
3548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ Jump(target);
3549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
3550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    LPointerMap* pointers = instr->pointer_map();
3552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (instr->target()->IsConstantOperand()) {
3555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      LConstantOperand* target = LConstantOperand::cast(instr->target());
3556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Handle<Code> code = Handle<Code>::cast(ToHandle(target));
3557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET));
3558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ Call(code, RelocInfo::CODE_TARGET);
3559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
3560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(instr->target()->IsRegister());
3561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Register target = ToRegister(instr->target());
3562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      generator.BeforeCall(__ CallSize(target));
3563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ Addu(target, target, Operand(Code::kHeaderSize - kHeapObjectTag));
3564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ Call(target);
3565958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
3566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    generator.AfterCall();
3567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
35683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
35693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCallNewArray(LCallNewArray* instr) {
3572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(cp));
3573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->constructor()).is(a1));
3574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->result()).is(v0));
35753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
35763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ li(a0, Operand(instr->arity()));
357713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ li(a2, instr->hydrogen()->site());
357813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
3579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ElementsKind kind = instr->hydrogen()->elements_kind();
3580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllocationSiteOverrideMode override_mode =
3581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
3582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ? DISABLE_ALLOCATION_SITES
3583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          : DONT_OVERRIDE;
3584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->arity() == 0) {
3586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ArrayNoArgumentConstructorStub stub(isolate(), kind, override_mode);
3587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (instr->arity() == 1) {
3589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
3590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsFastPackedElementsKind(kind)) {
3591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label packed_case;
3592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // We might need a change here,
3593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // look at the first argument.
3594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ lw(t1, MemOperand(sp, 0));
3595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Branch(&packed_case, eq, t1, Operand(zero_reg));
3596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ElementsKind holey_kind = GetHoleyElementsKind(kind);
3598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ArraySingleArgumentConstructorStub stub(isolate(),
3599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              holey_kind,
3600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              override_mode);
3601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&done);
3603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&packed_case);
3604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode);
3607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
3609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
361013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    ArrayNArgumentsConstructorStub stub(isolate());
3611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
36133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
36143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCallRuntime(LCallRuntime* instr) {
36173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntime(instr->function(), instr->arity(), instr);
36183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
36193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
3622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register function = ToRegister(instr->function());
3623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register code_object = ToRegister(instr->code_object());
3624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Addu(code_object, code_object,
3625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Operand(Code::kHeaderSize - kHeapObjectTag));
3626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(code_object,
3627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        FieldMemOperand(function, JSFunction::kCodeEntryOffset));
3628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
3632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
3633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register base = ToRegister(instr->base_object());
3634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->offset()->IsConstantOperand()) {
3635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LConstantOperand* offset = LConstantOperand::cast(instr->offset());
3636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Addu(result, base, Operand(ToInteger32(offset)));
3637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register offset = ToRegister(instr->offset());
3639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Addu(result, base, offset);
3640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
3645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Representation representation = instr->representation();
3646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = ToRegister(instr->object());
36483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
3649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HObjectAccess access = instr->hydrogen()->access();
3650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = access.offset();
3651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (access.IsExternalMemory()) {
3653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value = ToRegister(instr->value());
3654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand operand = MemOperand(object, offset);
3655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Store(value, operand, representation);
3656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
3657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
36583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AssertNotSmi(object);
3660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!representation.IsSmi() ||
3662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         !instr->value()->IsConstantOperand() ||
3663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         IsSmi(LConstantOperand::cast(instr->value())));
3664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (representation.IsDouble()) {
3665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(access.IsInobject());
3666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!instr->hydrogen()->has_transition());
3667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
3668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoubleRegister value = ToDoubleRegister(instr->value());
3669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sdc1(value, FieldMemOperand(object, offset));
3670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
3671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
36723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->has_transition()) {
3674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> transition = instr->hydrogen()->transition_map();
3675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AddDeprecationDependency(transition);
3676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ li(scratch, Operand(transition));
36773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
3678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
3679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Register temp = ToRegister(instr->temp());
3680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Update the write barrier for the map field.
3681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ RecordWriteForMap(object,
3682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           scratch,
3683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           temp,
3684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           GetRAState(),
3685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           kSaveFPRegs);
3686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
36873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
36883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do the store.
3690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value = ToRegister(instr->value());
3691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (access.IsInobject()) {
3692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand operand = FieldMemOperand(object, offset);
3693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Store(value, operand, representation);
36943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->hydrogen()->NeedsWriteBarrier()) {
36953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Update the write barrier for the object for in-object properties.
36963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWriteField(object,
36973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          offset,
36983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          value,
36993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          scratch,
3700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          GetRAState(),
37013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          kSaveFPRegs,
37023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          EMIT_REMEMBERED_SET,
3703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          instr->hydrogen()->SmiCheckForWriteBarrier(),
3704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          instr->hydrogen()->PointersToHereCheckForValue());
37053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
37063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
37073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset));
3708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand operand = FieldMemOperand(scratch, offset);
3709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Store(value, operand, representation);
37103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->hydrogen()->NeedsWriteBarrier()) {
37113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Update the write barrier for the properties array.
37123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // object is used as a scratch register.
37133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ RecordWriteField(scratch,
37143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          offset,
37153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          value,
37163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          object,
3717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          GetRAState(),
37183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          kSaveFPRegs,
37193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          EMIT_REMEMBERED_SET,
3720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          instr->hydrogen()->SmiCheckForWriteBarrier(),
3721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          instr->hydrogen()->PointersToHereCheckForValue());
37223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
37233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
37243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
37253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
3728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition cc = instr->hydrogen()->allow_equality() ? hi : hs;
3729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand operand(0);
3730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register reg;
3731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->index()->IsConstantOperand()) {
3732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    operand = ToOperand(instr->index());
3733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    reg = ToRegister(instr->length());
3734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cc = CommuteCondition(cc);
37353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
3736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    reg = ToRegister(instr->index());
3737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    operand = ToOperand(instr->length());
37383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
3740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
3741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&done, NegateCondition(cc), reg, operand);
3742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ stop("eliminated bounds check failed");
3743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
37443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
3745f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(cc, instr, DeoptimizeReason::kOutOfBounds, reg, operand);
37463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
37473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
37483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
3751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register external_pointer = ToRegister(instr->elements());
37523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register key = no_reg;
37533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsKind elements_kind = instr->elements_kind();
37543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool key_is_constant = instr->key()->IsConstantOperand();
37553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int constant_key = 0;
37563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (key_is_constant) {
37573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
37583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (constant_key & 0xF0000000) {
3759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Abort(kArrayIndexConstantValueTooBig);
37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
37613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
37623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    key = ToRegister(instr->key());
37633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int element_size_shift = ElementsKindToShiftSize(elements_kind);
3765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
3766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? (element_size_shift - kSmiTagSize) : element_size_shift;
3767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int base_offset = instr->base_offset();
3768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (elements_kind == FLOAT32_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) {
3770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register address = scratch0();
37713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FPURegister value(ToDoubleRegister(instr->value()));
37723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (key_is_constant) {
3773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (constant_key != 0) {
3774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Addu(address, external_pointer,
3775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                Operand(constant_key << element_size_shift));
3776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
3777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        address = external_pointer;
3778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
37793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
3780109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Lsa(address, external_pointer, key, shift_size);
37813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
37823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (elements_kind == FLOAT32_ELEMENTS) {
37843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ cvt_s_d(double_scratch0(), value);
3785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ swc1(double_scratch0(), MemOperand(address, base_offset));
3786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {  // Storing doubles, not floats.
3787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ sdc1(value, MemOperand(address, base_offset));
37883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
37893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
37903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register value(ToRegister(instr->value()));
3791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand mem_operand = PrepareKeyedOperand(
3792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        key, external_pointer, key_is_constant, constant_key,
3793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        element_size_shift, shift_size,
3794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        base_offset);
37953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (elements_kind) {
3796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT8_ELEMENTS:
3797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT8_CLAMPED_ELEMENTS:
3798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case INT8_ELEMENTS:
37993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sb(value, mem_operand);
38003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
3801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case INT16_ELEMENTS:
3802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT16_ELEMENTS:
38033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sh(value, mem_operand);
38043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
3805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case INT32_ELEMENTS:
3806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case UINT32_ELEMENTS:
38073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        __ sw(value, mem_operand);
38083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
3809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FLOAT32_ELEMENTS:
3810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FLOAT64_ELEMENTS:
38113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_DOUBLE_ELEMENTS:
38123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_ELEMENTS:
3813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_SMI_ELEMENTS:
3814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_HOLEY_DOUBLE_ELEMENTS:
3815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_HOLEY_ELEMENTS:
3816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case FAST_HOLEY_SMI_ELEMENTS:
38173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case DICTIONARY_ELEMENTS:
3818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
3819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
3820109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case FAST_STRING_WRAPPER_ELEMENTS:
3821109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case SLOW_STRING_WRAPPER_ELEMENTS:
3822109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      case NO_ELEMENTS:
38233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        UNREACHABLE();
38243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
38253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
38263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
38273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
38283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
3831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister value = ToDoubleRegister(instr->value());
3832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register elements = ToRegister(instr->elements());
3833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = scratch0();
3834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register scratch_1 = scratch1();
3835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister double_scratch = double_scratch0();
3836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool key_is_constant = instr->key()->IsConstantOperand();
3837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int base_offset = instr->base_offset();
3838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label not_nan, done;
3839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate the effective address of the slot in the array to store the
3841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // double value.
3842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
3843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (key_is_constant) {
3844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
3845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (constant_key & 0xF0000000) {
3846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Abort(kArrayIndexConstantValueTooBig);
3847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Addu(scratch, elements,
3849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           Operand((constant_key << element_size_shift) + base_offset));
3850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
3852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ? (element_size_shift - kSmiTagSize) : element_size_shift;
3853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Addu(scratch, elements, Operand(base_offset));
3854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sll(at, ToRegister(instr->key()), shift_size);
3855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Addu(scratch, scratch, at);
3856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->NeedsCanonicalization()) {
3859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label is_nan;
3860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check for NaN. All NaNs must be canonicalized.
3861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ BranchF(NULL, &is_nan, eq, value, value);
3862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&not_nan);
3863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Only load canonical NaN if the comparison above set the overflow.
3865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&is_nan);
3866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadRoot(scratch_1, Heap::kNanValueRootIndex);
3867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ldc1(double_scratch,
3868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            FieldMemOperand(scratch_1, HeapNumber::kValueOffset));
3869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sdc1(double_scratch, MemOperand(scratch, 0));
3870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&done);
3871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&not_nan);
3874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sdc1(value, MemOperand(scratch, 0));
3875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
3876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
3880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register value = ToRegister(instr->value());
3881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register elements = ToRegister(instr->elements());
3882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register key = instr->key()->IsRegister() ? ToRegister(instr->key())
3883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : no_reg;
3884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = scratch0();
3885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register store_base = scratch;
3886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int offset = instr->base_offset();
3887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Do the store.
3889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->key()->IsConstantOperand()) {
3890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
3891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
3892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    offset += ToInteger32(const_operand) * kPointerSize;
3893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    store_base = elements;
3894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Even though the HLoadKeyed instruction forces the input
3896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // representation for the key to be an integer, the input gets replaced
3897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // during bound check elimination with the index argument to the bounds
3898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // check, which can be tagged, so that case must be handled here, too.
3899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->hydrogen()->key()->representation().IsSmi()) {
3900109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Lsa(scratch, elements, key, kPointerSizeLog2 - kSmiTagSize);
3901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
3902109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Lsa(scratch, elements, key, kPointerSizeLog2);
3903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
3904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sw(value, MemOperand(store_base, offset));
3906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->NeedsWriteBarrier()) {
3908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SmiCheck check_needed =
3909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->hydrogen()->value()->type().IsHeapObject()
3910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Compute address of modified element and store it into key register.
3912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Addu(key, store_base, Operand(offset));
3913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RecordWrite(elements,
3914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   key,
3915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   value,
3916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   GetRAState(),
3917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   kSaveFPRegs,
3918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   EMIT_REMEMBERED_SET,
3919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   check_needed,
3920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   instr->hydrogen()->PointersToHereCheckForValue());
3921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
3926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // By cases: external, fast double
3927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (instr->is_fixed_typed_array()) {
3928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoStoreKeyedExternalArray(instr);
3929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (instr->hydrogen()->value()->representation().IsDouble()) {
3930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoStoreKeyedFixedDoubleArray(instr);
3931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
3932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DoStoreKeyedFixedArray(instr);
3933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LCodeGen::DoMaybeGrowElements(LMaybeGrowElements* instr) {
3938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredMaybeGrowElements final : public LDeferredCode {
3939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch   public:
3940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DeferredMaybeGrowElements(LCodeGen* codegen, LMaybeGrowElements* instr)
3941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        : LDeferredCode(codegen), instr_(instr) {}
3942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override { codegen()->DoDeferredMaybeGrowElements(instr_); }
3943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
3944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch   private:
3946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LMaybeGrowElements* instr_;
3947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  };
3948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register result = v0;
3950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DeferredMaybeGrowElements* deferred =
3951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      new (zone()) DeferredMaybeGrowElements(this, instr);
3952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LOperand* key = instr->key();
3953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LOperand* current_capacity = instr->current_capacity();
3954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(instr->hydrogen()->key()->representation().IsInteger32());
3956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(instr->hydrogen()->current_capacity()->representation().IsInteger32());
3957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(key->IsConstantOperand() || key->IsRegister());
3958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(current_capacity->IsConstantOperand() ||
3959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch         current_capacity->IsRegister());
3960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (key->IsConstantOperand() && current_capacity->IsConstantOperand()) {
3962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int32_t constant_key = ToInteger32(LConstantOperand::cast(key));
3963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int32_t constant_capacity =
3964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ToInteger32(LConstantOperand::cast(current_capacity));
3965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (constant_key >= constant_capacity) {
3966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Deferred case.
3967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ jmp(deferred->entry());
3968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
3969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (key->IsConstantOperand()) {
3970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int32_t constant_key = ToInteger32(LConstantOperand::cast(key));
3971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Branch(deferred->entry(), le, ToRegister(current_capacity),
3972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              Operand(constant_key));
3973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else if (current_capacity->IsConstantOperand()) {
3974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int32_t constant_capacity =
3975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ToInteger32(LConstantOperand::cast(current_capacity));
3976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Branch(deferred->entry(), ge, ToRegister(key),
3977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              Operand(constant_capacity));
3978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Branch(deferred->entry(), ge, ToRegister(key),
3980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              Operand(ToRegister(current_capacity)));
3981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (instr->elements()->IsRegister()) {
3984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(result, ToRegister(instr->elements()));
3985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ lw(result, ToMemOperand(instr->elements()));
3987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(deferred->exit());
3990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LCodeGen::DoDeferredMaybeGrowElements(LMaybeGrowElements* instr) {
3994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // TODO(3095996): Get rid of this. For now, we need to make the
3995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // result register contain a valid pointer because it is already
3996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // contained in the register pointer map.
3997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register result = v0;
3998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(result, zero_reg);
3999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // We have to call a stub.
4001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
4002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    PushSafepointRegistersScope scope(this);
4003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (instr->object()->IsRegister()) {
4004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ mov(result, ToRegister(instr->object()));
4005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
4006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ lw(result, ToMemOperand(instr->object()));
4007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LOperand* key = instr->key();
4010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (key->IsConstantOperand()) {
4011bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      LConstantOperand* constant_key = LConstantOperand::cast(key);
4012bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      int32_t int_key = ToInteger32(constant_key);
4013bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      if (Smi::IsValid(int_key)) {
4014bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        __ li(a3, Operand(Smi::FromInt(int_key)));
4015bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      } else {
401662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Abort(kArrayIndexConstantValueTooBig);
4017bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
4018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
401962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Label is_smi;
402062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ SmiTagCheckOverflow(a3, ToRegister(key), at);
402162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Deopt if the key is outside Smi range. The stub expects Smi and would
402262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // bump the elements into dictionary mode (and trigger a deopt) anyways.
402362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ BranchOnNoOverflow(&is_smi, at);
402462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      RestoreRegistersStateStub stub(isolate());
402562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ push(ra);
402662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ CallStub(&stub);
402762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      DeoptimizeIf(al, instr, DeoptimizeReason::kOverflow);
402862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ bind(&is_smi);
4029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
4030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4031f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    GrowArrayElementsStub stub(isolate(), instr->hydrogen()->kind());
4032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(a0, result);
4033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallStub(&stub);
4034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    RecordSafepointWithLazyDeopt(
4035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
4036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ StoreToSafepointRegisterSlot(result, result);
4037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
4038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Deopt on smi, which means the elements array changed to dictionary mode.
4040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ SmiTst(result, at);
4041f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, at, Operand(zero_reg));
4042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
40453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
40463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object_reg = ToRegister(instr->object());
40473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
40483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Map> from_map = instr->original_map();
40503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Map> to_map = instr->transitioned_map();
4051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ElementsKind from_kind = instr->from_kind();
4052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ElementsKind to_kind = instr->to_kind();
40533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label not_applicable;
40553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset));
40563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&not_applicable, ne, scratch, Operand(from_map));
40573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
4059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register new_map_reg = ToRegister(instr->new_map_temp());
4060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ li(new_map_reg, Operand(to_map));
40613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ sw(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset));
40623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Write barrier.
4063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RecordWriteForMap(object_reg,
4064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         new_map_reg,
4065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         scratch,
4066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         GetRAState(),
4067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         kDontSaveFPRegs);
40683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
4069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(object_reg.is(a0));
4070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(ToRegister(instr->context()).is(cp));
4071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PushSafepointRegistersScope scope(this);
4072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ li(a1, Operand(to_map));
407313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    TransitionElementsKindStub stub(isolate(), from_kind, to_kind);
4074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallStub(&stub);
4075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordSafepointWithRegisters(
4076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->pointer_map(), 0, Safepoint::kLazyDeopt);
40773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
40783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&not_applicable);
40793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
40803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register object = ToRegister(instr->object());
4084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp = ToRegister(instr->temp());
4085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_memento_found;
40863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeoptimizeIf(al, instr);
4088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&no_memento_found);
4089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
40923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStringAdd(LStringAdd* instr) {
4093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->context()).is(cp));
4094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->left()).is(a1));
4095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->right()).is(a0));
4096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StringAddStub stub(isolate(),
4097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     instr->hydrogen()->flags(),
4098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     instr->hydrogen()->pretenure_flag());
40993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
41003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
41013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
4104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredStringCharCodeAt final : public LDeferredCode {
41053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
41063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
41073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
4108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override { codegen()->DoDeferredStringCharCodeAt(instr_); }
4109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
41113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
41123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LStringCharCodeAt* instr_;
41133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
41143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeferredStringCharCodeAt* deferred =
4116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new(zone()) DeferredStringCharCodeAt(this, instr);
41173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharLoadGenerator::Generate(masm(),
41183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    ToRegister(instr->string()),
41193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    ToRegister(instr->index()),
41203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    ToRegister(instr->result()),
41213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    deferred->entry());
41223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(deferred->exit());
41233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
41243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
41273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register string = ToRegister(instr->string());
41283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
41293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
41303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(3095996): Get rid of this. For now, we need to make the
41323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // result register contain a valid pointer because it is already
41333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // contained in the register pointer map.
41343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(result, zero_reg);
41353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushSafepointRegistersScope scope(this);
41373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(string);
41383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Push the index as a smi. This is safe because of the checks in
41393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // DoStringCharCodeAt above.
41403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->index()->IsConstantOperand()) {
41413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
41423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Addu(scratch, zero_reg, Operand(Smi::FromInt(const_index)));
41433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(scratch);
41443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
41453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register index = ToRegister(instr->index());
41463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiTag(index);
41473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ push(index);
41483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallRuntimeFromDeferred(Runtime::kStringCharCodeAtRT, 2, instr,
4150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          instr->context());
4151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AssertSmi(v0);
41523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiUntag(v0);
41533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreToSafepointRegisterSlot(v0, result);
41543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
41553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
4158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredStringCharFromCode final : public LDeferredCode {
41593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
41603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
41613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
4162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override {
4163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen()->DoDeferredStringCharFromCode(instr_);
4164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
41673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
41683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LStringCharFromCode* instr_;
41693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
41703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeferredStringCharFromCode* deferred =
4172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new(zone()) DeferredStringCharFromCode(this, instr);
41733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->hydrogen()->value()->representation().IsInteger32());
41753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register char_code = ToRegister(instr->char_code());
41763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
41773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
4178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!char_code.is(result));
41793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(deferred->entry(), hi,
4181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            char_code, Operand(String::kMaxOneByteCharCode));
41823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
4183109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Lsa(result, result, char_code, kPointerSizeLog2);
41843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(result, FixedArray::kHeaderSize));
41853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
41863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(deferred->entry(), eq, result, Operand(scratch));
41873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(deferred->exit());
41883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
41893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
41923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register char_code = ToRegister(instr->char_code());
41933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
41943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(3095996): Get rid of this. For now, we need to make the
41963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // result register contain a valid pointer because it is already
41973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // contained in the register pointer map.
41983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(result, zero_reg);
41993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushSafepointRegistersScope scope(this);
42013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiTag(char_code);
42023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(char_code);
4203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallRuntimeFromDeferred(Runtime::kStringCharFromCode, 1, instr,
4204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          instr->context());
42053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreToSafepointRegisterSlot(v0, result);
42063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
4210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input->IsRegister() || input->IsStackSlot());
42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* output = instr->result();
4213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(output->IsDoubleRegister());
42143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FPURegister single_scratch = double_scratch0().low();
42153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (input->IsStackSlot()) {
42163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register scratch = scratch0();
42173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(scratch, ToMemOperand(input));
42183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mtc1(scratch, single_scratch);
42193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
42203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ mtc1(ToRegister(input), single_scratch);
42213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
42223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cvt_d_w(ToDoubleRegister(output), single_scratch);
42233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
4227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* output = instr->result();
4229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Cvt_d_uw(ToDoubleRegister(output), ToRegister(input), f22);
4231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
42343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoNumberTagI(LNumberTagI* instr) {
4235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredNumberTagI final : public LDeferredCode {
42363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
42373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr)
42383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
4239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override {
4240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen()->DoDeferredNumberTagIU(instr_,
4241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       instr_->value(),
4242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       instr_->temp1(),
4243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       instr_->temp2(),
4244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       SIGNED_INT32);
4245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
42483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
42493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LNumberTagI* instr_;
42503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
42513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register src = ToRegister(instr->value());
42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register dst = ToRegister(instr->result());
42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register overflow = scratch0();
42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr);
42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiTagCheckOverflow(dst, src, overflow);
42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ BranchOnOverflow(deferred->entry(), overflow);
42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(deferred->exit());
42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoNumberTagU(LNumberTagU* instr) {
4264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredNumberTagU final : public LDeferredCode {
4265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
4266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr)
4267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
4268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override {
4269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen()->DoDeferredNumberTagIU(instr_,
4270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       instr_->value(),
4271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       instr_->temp1(),
4272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       instr_->temp2(),
4273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       UNSIGNED_INT32);
4274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
4278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LNumberTagU* instr_;
4279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
4282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result = ToRegister(instr->result());
42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr);
4285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(deferred->entry(), hi, input, Operand(Smi::kMaxValue));
4286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTag(result, input);
4287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(deferred->exit());
4288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
4292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     LOperand* value,
4293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     LOperand* temp1,
4294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     LOperand* temp2,
4295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     IntegerSignedness signedness) {
4296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, slow;
4297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register src = ToRegister(value);
4298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dst = ToRegister(instr->result());
4299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register tmp1 = scratch0();
4300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register tmp2 = ToRegister(temp1);
4301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register tmp3 = ToRegister(temp2);
4302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister dbl_scratch = double_scratch0();
4303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (signedness == SIGNED_INT32) {
4305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // There was overflow, so bits 30 and 31 of the original integer
4306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // disagree. Try to allocate a heap number in new space and store
4307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the value in there. If that fails, call the runtime system.
4308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (dst.is(src)) {
4309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ SmiUntag(src, dst);
4310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Xor(src, src, Operand(0x80000000));
4311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mtc1(src, dbl_scratch);
4313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cvt_d_w(dbl_scratch, dbl_scratch);
4314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Cvt_d_uw(dbl_scratch, src, f22);
43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
43183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_inline_new) {
4319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex);
4320bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow);
43213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done);
43223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Slow case: Call the runtime system to do the number allocation.
43253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&slow);
4326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // TODO(3095996): Put a valid pointer value in the stack slot where the
4328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // result register is stored, as this register is in the pointer map, but
4329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // contains an integer value.
4330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(dst, zero_reg);
4331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Preserve the value of all registers.
4333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PushSafepointRegistersScope scope(this);
4334f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Reset the context register.
4335f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (!dst.is(cp)) {
4336f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      __ mov(cp, zero_reg);
4337f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
4338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordSafepointWithRegisters(
4340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ StoreToSafepointRegisterSlot(v0, dst);
4342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
43433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Done. Put the value in dbl_scratch into the value of the allocated heap
43453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // number.
43463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
4347bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ sdc1(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset));
43483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
43493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoNumberTagD(LNumberTagD* instr) {
4352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredNumberTagD final : public LDeferredCode {
43533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
43543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
43553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
4356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override { codegen()->DoDeferredNumberTagD(instr_); }
4357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
43593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
43603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LNumberTagD* instr_;
43613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
43623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister input_reg = ToDoubleRegister(instr->value());
43643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
43653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = ToRegister(instr->result());
4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp1 = ToRegister(instr->temp());
4367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp2 = ToRegister(instr->temp2());
43683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr);
43703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_inline_new) {
43713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
4372bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry());
43733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
43743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(deferred->entry());
43753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(deferred->exit());
4377bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ sdc1(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset));
4378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Now that we have finished with the object's real address tag it
43793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
43803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
43833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(3095996): Get rid of this. For now, we need to make the
43843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // result register contain a valid pointer because it is already
43853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // contained in the register pointer map.
43863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = ToRegister(instr->result());
43873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(reg, zero_reg);
43883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushSafepointRegistersScope scope(this);
4390f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Reset the context register.
4391f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!reg.is(cp)) {
4392f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    __ mov(cp, zero_reg);
4393f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
4394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordSafepointWithRegisters(
4396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
43973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreToSafepointRegisterSlot(v0, reg);
43983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
43993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoSmiTag(LSmiTag* instr) {
4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HChange* hchange = instr->hydrogen();
4403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
4404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register output = ToRegister(instr->result());
4405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hchange->CheckFlag(HValue::kCanOverflow) &&
4406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      hchange->value()->CheckFlag(HValue::kUint32)) {
4407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ And(at, input, Operand(0xc0000000));
4408f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kOverflow, at, Operand(zero_reg));
4409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (hchange->CheckFlag(HValue::kCanOverflow) &&
4411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      !hchange->value()->CheckFlag(HValue::kUint32)) {
4412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiTagCheckOverflow(output, input, at);
4413f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(lt, instr, DeoptimizeReason::kOverflow, at, Operand(zero_reg));
4414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiTag(output, input);
4416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
44173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
44183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoSmiUntag(LSmiUntag* instr) {
44213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
4422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
44233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
44243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->needs_check()) {
44253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    STATIC_ASSERT(kHeapObjectTag == 1);
44263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If the input is a HeapObject, value of scratch won't be zero.
44273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(scratch, input, Operand(kHeapObjectTag));
44283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiUntag(result, input);
4429f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kNotASmi, scratch,
4430f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                 Operand(zero_reg));
44313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
44323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiUntag(result, input);
44333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
44343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
44353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
44383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                DoubleRegister result_reg,
4439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                NumberUntagDMode mode) {
4440c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  bool can_convert_undefined_to_nan = instr->truncating();
4441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
44423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = scratch0();
4444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label convert, load_smi, done;
4445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
4446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Smi check.
4447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
4448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Heap number map check.
4449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
4450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
4451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (can_convert_undefined_to_nan) {
4452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Branch(&convert, ne, scratch, Operand(at));
4453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4454f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch,
4455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   Operand(at));
4456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load heap number.
4458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
4459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (deoptimize_on_minus_zero) {
4460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ mfc1(at, result_reg.low());
4461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Branch(&done, ne, at, Operand(zero_reg));
4462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Mfhc1(scratch, result_reg);
4463f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(eq, instr, DeoptimizeReason::kMinusZero, scratch,
4464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   Operand(HeapNumber::kSignMask));
4465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
44663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done);
4467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (can_convert_undefined_to_nan) {
4468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&convert);
4469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Convert undefined (and hole) to NaN.
4470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
4471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefined,
4472f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   input_reg, Operand(at));
4473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(scratch, Heap::kNanValueRootIndex);
4474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset));
4475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Branch(&done);
4476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiUntag(scratch, input_reg);
4479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
44803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
44813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Smi to double register conversion
44823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&load_smi);
44833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // scratch: untagged value of input_reg
44843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mtc1(scratch, result_reg);
44853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cvt_d_w(result_reg, result_reg);
44863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
44873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
44883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
4491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input_reg = ToRegister(instr->value());
44923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch1 = scratch0();
4493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch2 = ToRegister(instr->temp());
44943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister double_scratch = double_scratch0();
4495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp2());
44963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch1.is(input_reg) && !scratch1.is(scratch2));
4498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch2.is(input_reg) && !scratch2.is(scratch1));
44993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label done;
45013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The input is a tagged HeapObject.
45033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Heap number map check.
45043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
45053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
45063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This 'at' value and scratch1 map value are used for tests in both clauses
45073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // of the if.
45083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->truncating()) {
4510c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Label truncate;
4511c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    __ Branch(USE_DELAY_SLOT, &truncate, eq, scratch1, Operand(at));
4512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(scratch2, input_reg);  // In delay slot.
4513c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
4514c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kNotANumberOrOddball, scratch1,
4515c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                 Operand(ODDBALL_TYPE));
4516c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    __ bind(&truncate);
4517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ TruncateHeapNumberToI(input_reg, scratch2);
45183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
4519f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch1,
4520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 Operand(at));
45213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Load the double value.
45233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ldc1(double_scratch,
45243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            FieldMemOperand(input_reg, HeapNumber::kValueOffset));
45253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register except_flag = scratch2;
45273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ EmitFPUTruncate(kRoundToZero,
4528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       input_reg,
45293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       double_scratch,
45303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       scratch1,
4531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       double_scratch2,
45323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       except_flag,
45333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       kCheckForInexactConversion);
45343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4535f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecisionOrNaN, except_flag,
4536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 Operand(zero_reg));
45373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
45393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ Branch(&done, ne, input_reg, Operand(zero_reg));
45403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Mfhc1(scratch1, double_scratch);
45423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
4543f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch1,
4544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   Operand(zero_reg));
45453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
45463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
45473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
45483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
45493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoTaggedToI(LTaggedToI* instr) {
4552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredTaggedToI final : public LDeferredCode {
45533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
45543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
45553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
4556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override { codegen()->DoDeferredTaggedToI(instr_); }
4557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
45593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
45603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LTaggedToI* instr_;
45613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
45623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input->IsRegister());
4565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input->Equals(instr->result()));
45663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input_reg = ToRegister(input);
45683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->value()->representation().IsSmi()) {
4570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiUntag(input_reg);
4571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr);
45733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Let the deferred code handle the HeapObject case.
4575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfNotSmi(input_reg, deferred->entry());
45763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Smi to int32 conversion.
4578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiUntag(input_reg);
4579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(deferred->exit());
4580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
45813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
45823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
4585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input->IsRegister());
45873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LOperand* result = instr->result();
4588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(result->IsDoubleRegister());
45893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input_reg = ToRegister(input);
45913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister result_reg = ToDoubleRegister(result);
45923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HValue* value = instr->hydrogen()->value();
4594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NumberUntagDMode mode = value->representation().IsSmi()
4595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
4596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitNumberUntagD(instr, input_reg, result_reg, mode);
45983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
45993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDoubleToI(LDoubleToI* instr) {
46023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result_reg = ToRegister(instr->result());
46033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch1 = scratch0();
4604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister double_input = ToDoubleRegister(instr->value());
46053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->truncating()) {
4607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ TruncateDoubleToI(result_reg, double_input);
46083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
4609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register except_flag = LCodeGen::scratch1();
4610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ EmitFPUTruncate(kRoundToMinusInf,
4612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       result_reg,
4613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       double_input,
4614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       scratch1,
4615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       double_scratch0(),
4616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       except_flag,
4617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       kCheckForInexactConversion);
4618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Deopt if the operation did not succeed (except_flag != 0).
4620f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecisionOrNaN, except_flag,
4621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 Operand(zero_reg));
4622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
4624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label done;
4625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Branch(&done, ne, result_reg, Operand(zero_reg));
4626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Mfhc1(scratch1, double_input);
4627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
4628f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch1,
4629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   Operand(zero_reg));
4630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&done);
4631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
4637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register result_reg = ToRegister(instr->result());
4638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch1 = LCodeGen::scratch0();
4639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister double_input = ToDoubleRegister(instr->value());
4640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->truncating()) {
4642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ TruncateDoubleToI(result_reg, double_input);
4643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register except_flag = LCodeGen::scratch1();
46453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ EmitFPUTruncate(kRoundToMinusInf,
4647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       result_reg,
46483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       double_input,
46493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       scratch1,
4650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                       double_scratch0(),
46513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       except_flag,
46523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       kCheckForInexactConversion);
46533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Deopt if the operation did not succeed (except_flag != 0).
4655f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kLostPrecisionOrNaN, except_flag,
4656958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                 Operand(zero_reg));
46573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
4659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label done;
4660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Branch(&done, ne, result_reg, Operand(zero_reg));
4661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Mfhc1(scratch1, double_input);
4662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
4663f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(ne, instr, DeoptimizeReason::kMinusZero, scratch1,
4664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   Operand(zero_reg));
4665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&done);
4666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
46673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTagCheckOverflow(result_reg, result_reg, scratch1);
4669f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(lt, instr, DeoptimizeReason::kOverflow, scratch1,
4670f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch               Operand(zero_reg));
46713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
46723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckSmi(LCheckSmi* instr) {
4675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTst(ToRegister(input), at);
4677f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(ne, instr, DeoptimizeReason::kNotASmi, at, Operand(zero_reg));
46783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
46793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
4682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
4683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LOperand* input = instr->value();
4684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiTst(ToRegister(input), at);
4685f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(eq, instr, DeoptimizeReason::kSmi, at, Operand(zero_reg));
4686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
46873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
46883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LCodeGen::DoCheckArrayBufferNotNeutered(
4691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LCheckArrayBufferNotNeutered* instr) {
4692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register view = ToRegister(instr->view());
4693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register scratch = scratch0();
4694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ lw(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset));
4696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ lw(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset));
4697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ And(at, scratch, 1 << JSArrayBuffer::WasNeutered::kShift);
4698f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(ne, instr, DeoptimizeReason::kOutOfBounds, at,
4699f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch               Operand(zero_reg));
4700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
4701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
47033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
4704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
47053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
47063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetObjectType(input, scratch, scratch);
47083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->is_interval_check()) {
47103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InstanceType first;
47113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InstanceType last;
47123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    instr->hydrogen()->GetCheckInterval(&first, &last);
47133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // If there is only one type in the interval check for equality.
47153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (first == last) {
4716f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongInstanceType, scratch,
4717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   Operand(first));
47183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
4719f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(lo, instr, DeoptimizeReason::kWrongInstanceType, scratch,
4720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   Operand(first));
47213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Omit check for the last type.
47223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (last != LAST_TYPE) {
4723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        DeoptimizeIf(hi, instr, DeoptimizeReason::kWrongInstanceType, scratch,
4724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     Operand(last));
47253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
47263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
47273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
47283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint8_t mask;
47293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint8_t tag;
47303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
47313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (base::bits::IsPowerOfTwo32(mask)) {
4733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
47343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ And(at, scratch, mask);
4735f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(tag == 0 ? ne : eq, instr,
4736f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                   DeoptimizeReason::kWrongInstanceType, at, Operand(zero_reg));
47373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
47383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ And(scratch, scratch, Operand(mask));
4739f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongInstanceType, scratch,
4740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   Operand(tag));
47413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
47423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
47433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
47443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCheckValue(LCheckValue* instr) {
47473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = ToRegister(instr->value());
4748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<HeapObject> object = instr->hydrogen()->object().handle();
4749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowDeferredHandleDereference smi_check;
4750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (isolate()->heap()->InNewSpace(*object)) {
47513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Register reg = ToRegister(instr->value());
4752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Cell> cell = isolate()->factory()->NewCell(object);
4753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(at, Operand(cell));
4754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ lw(at, FieldMemOperand(at, Cell::kValueOffset));
4755f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kValueMismatch, reg, Operand(at));
47563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
4757f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kValueMismatch, reg,
4758f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                 Operand(object));
47593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
47603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
47613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
476462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label deopt, done;
476562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // If the map is not deprecated the migration attempt does not make sense.
476662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ lw(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
476762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ lw(scratch0(), FieldMemOperand(scratch0(), Map::kBitField3Offset));
476862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ And(at, scratch0(), Operand(Map::Deprecated::kMask));
476962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Branch(&deopt, eq, at, Operand(zero_reg));
477062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
4771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
4772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PushSafepointRegistersScope scope(this);
4773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(object);
4774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(cp, zero_reg);
4775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
4776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RecordSafepointWithRegisters(
4777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
4778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ StoreToSafepointRegisterSlot(v0, scratch0());
4779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiTst(scratch0(), at);
478162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Branch(&done, ne, at, Operand(zero_reg));
478262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
478362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ bind(&deopt);
478462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // In case of "al" condition the operands are not used so just pass zero_reg
478562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // there.
478662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DeoptimizeIf(al, instr, DeoptimizeReason::kInstanceMigrationFailed, zero_reg,
4787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch               Operand(zero_reg));
478862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
478962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ bind(&done);
47903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
47913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
47923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCheckMaps(LCheckMaps* instr) {
4794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredCheckMaps final : public LDeferredCode {
4795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
4796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
4797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : LDeferredCode(codegen), instr_(instr), object_(object) {
4798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetExit(check_maps());
4799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override {
4801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen()->DoDeferredInstanceMigration(instr_, object_);
4802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* check_maps() { return &check_maps_; }
4804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
4807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LCheckMaps* instr_;
4808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label check_maps_;
4809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object_;
4810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
4811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->IsStabilityCheck()) {
4813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const UniqueSet<Map>* maps = instr->hydrogen()->maps();
4814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < maps->size(); ++i) {
4815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AddStabilityDependency(maps->at(i).handle());
4816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
4818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register map_reg = scratch0();
4821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOperand* input = instr->value();
4822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(input->IsRegister());
48233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register reg = ToRegister(input);
4824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
4825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeferredCheckMaps* deferred = NULL;
4827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->HasMigrationTarget()) {
4828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    deferred = new(zone()) DeferredCheckMaps(this, instr, reg);
4829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(deferred->check_maps());
4830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const UniqueSet<Map>* maps = instr->hydrogen()->maps();
4833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label success;
4834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < maps->size() - 1; i++) {
4835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> map = maps->at(i).handle();
4836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareMapAndBranch(map_reg, map, &success, eq, &success);
4837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Map> map = maps->at(maps->size() - 1).handle();
4839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Do the CompareMap() directly within the Branch() and DeoptimizeIf().
4840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->HasMigrationTarget()) {
4841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(deferred->entry(), ne, map_reg, Operand(map));
4842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4843f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongMap, map_reg, Operand(map));
4844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&success);
48473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
48483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
48513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoubleRegister value_reg = ToDoubleRegister(instr->unclamped());
48523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result_reg = ToRegister(instr->result());
4853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister temp_reg = ToDoubleRegister(instr->temp());
48543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ClampDoubleToUint8(result_reg, value_reg, temp_reg);
48553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
48563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
48593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register unclamped_reg = ToRegister(instr->unclamped());
48603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result_reg = ToRegister(instr->result());
48613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ClampUint8(result_reg, unclamped_reg);
48623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
48633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
48663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
48673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register input_reg = ToRegister(instr->unclamped());
48683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result_reg = ToRegister(instr->result());
4869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DoubleRegister temp_reg = ToDoubleRegister(instr->temp());
48703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label is_smi, done, heap_number;
48713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Both smi and heap number cases are handled.
48733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi);
48743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for heap number
48763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
48773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map()));
48783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for undefined. Undefined is converted to zero for clamping
48803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // conversions.
4881f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefined, input_reg,
4882958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               Operand(factory()->undefined_value()));
48833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(result_reg, zero_reg);
48843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&done);
48853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Heap number
48873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&heap_number);
48883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldc1(double_scratch0(), FieldMemOperand(input_reg,
48893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             HeapNumber::kValueOffset));
48903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg);
48913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&done);
48923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&is_smi);
48943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ClampUint8(result_reg, scratch);
48953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
48973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
48983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoAllocate(LAllocate* instr) {
4901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredAllocate final : public LDeferredCode {
49023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
4903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
49043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
4905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override { codegen()->DoDeferredAllocate(instr_); }
4906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
4907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
49083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
4909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LAllocate* instr_;
49103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
49113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeferredAllocate* deferred =
4913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new(zone()) DeferredAllocate(this, instr);
49143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
4916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = ToRegister(instr->temp1());
4917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch2 = ToRegister(instr->temp2());
4918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate memory for the object.
4920bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  AllocationFlags flags = NO_ALLOCATION_FLAGS;
4921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
4922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
4923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (instr->hydrogen()->IsOldSpaceAllocation()) {
4925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
4926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    flags = static_cast<AllocationFlags>(flags | PRETENURE);
4927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4928bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4929bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
4930bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    flags = static_cast<AllocationFlags>(flags | ALLOCATION_FOLDING_DOMINATOR);
4931bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
4932bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!instr->hydrogen()->IsAllocationFolded());
4933bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
4934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->size()->IsConstantOperand()) {
4935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
4936f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    CHECK(size <= kMaxRegularHeapObjectSize);
4937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
4938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register size = ToRegister(instr->size());
4940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
49413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
49423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(deferred->exit());
4944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->hydrogen()->MustPrefillWithFiller()) {
4946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kHeapObjectTag == 1);
4947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (instr->size()->IsConstantOperand()) {
4948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
4949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ li(scratch, Operand(size - kHeapObjectTag));
4950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
4951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Subu(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag));
4952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
4954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label loop;
4955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&loop);
4956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Subu(scratch, scratch, Operand(kPointerSize));
4957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Addu(at, result, Operand(scratch));
4958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sw(scratch2, MemOperand(at));
4959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(&loop, ge, scratch, Operand(zero_reg));
4960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
49613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
49623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredAllocate(LAllocate* instr) {
49653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
49663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
49673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(3095996): Get rid of this. For now, we need to make the
49683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // result register contain a valid pointer because it is already
49693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // contained in the register pointer map.
49703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mov(result, zero_reg);
49713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushSafepointRegistersScope scope(this);
4973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (instr->size()->IsRegister()) {
4974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register size = ToRegister(instr->size());
4975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!size.is(result));
4976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiTag(size);
4977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ push(size);
49783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
4979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
4980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (size >= 0 && size <= Smi::kMaxValue) {
4981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(Smi::FromInt(size));
49823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
4983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // We should never get here at runtime => abort
4984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ stop("invalid allocation size");
4985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
49863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
49873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
49883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int flags = AllocateDoubleAlignFlag::encode(
4990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      instr->hydrogen()->MustAllocateDoubleAligned());
4991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (instr->hydrogen()->IsOldSpaceAllocation()) {
4992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
4993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    flags = AllocateTargetSpace::update(flags, OLD_SPACE);
49943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
4995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    flags = AllocateTargetSpace::update(flags, NEW_SPACE);
49963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Smi::FromInt(flags));
4998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallRuntimeFromDeferred(
5000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
5001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ StoreToSafepointRegisterSlot(v0, result);
5002bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5003bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
5004bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    AllocationFlags allocation_flags = NO_ALLOCATION_FLAGS;
5005bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (instr->hydrogen()->IsOldSpaceAllocation()) {
5006bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5007bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE);
5008bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
5009bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // If the allocation folding dominator allocate triggered a GC, allocation
5010bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // happend in the runtime. We have to reset the top pointer to virtually
5011bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // undo the allocation.
5012bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    ExternalReference allocation_top =
5013bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags);
5014bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Register top_address = scratch0();
5015bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    __ Subu(v0, v0, Operand(kHeapObjectTag));
5016bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    __ li(top_address, Operand(allocation_top));
5017bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    __ sw(v0, MemOperand(top_address));
5018bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    __ Addu(v0, v0, Operand(kHeapObjectTag));
5019bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
5020bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
5021bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5022bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid LCodeGen::DoFastAllocate(LFastAllocate* instr) {
5023bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(instr->hydrogen()->IsAllocationFolded());
5024bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator());
5025bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register result = ToRegister(instr->result());
5026bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register scratch1 = ToRegister(instr->temp1());
5027bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register scratch2 = ToRegister(instr->temp2());
5028bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5029bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  AllocationFlags flags = ALLOCATION_FOLDED;
5030bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
5031bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
5032bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
5033bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (instr->hydrogen()->IsOldSpaceAllocation()) {
5034bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5035bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    flags = static_cast<AllocationFlags>(flags | PRETENURE);
5036bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
5037bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (instr->size()->IsConstantOperand()) {
5038bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5039f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    CHECK(size <= kMaxRegularHeapObjectSize);
5040bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    __ FastAllocate(size, result, scratch1, scratch2, flags);
5041bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
5042bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Register size = ToRegister(instr->size());
5043bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    __ FastAllocate(size, result, scratch1, scratch2, flags);
5044bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
50453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
50463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoTypeof(LTypeof* instr) {
5049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(ToRegister(instr->value()).is(a3));
5050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ToRegister(instr->result()).is(v0));
5051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label end, do_call;
5052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register value_register = ToRegister(instr->value());
5053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ JumpIfNotSmi(value_register, &do_call);
5054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ li(v0, Operand(isolate()->factory()->number_string()));
5055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ jmp(&end);
5056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&do_call);
5057f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Callable callable = CodeFactory::Typeof(isolate());
5058f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CallCode(callable.code(), RelocInfo::CODE_TARGET, instr);
5059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&end);
50603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
50613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
5064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register input = ToRegister(instr->value());
50653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register cmp1 = no_reg;
50673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Operand cmp2 = Operand(no_reg);
50683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition final_branch_condition = EmitTypeofIs(instr->TrueLabel(chunk_),
5070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  instr->FalseLabel(chunk_),
50713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  input,
50723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                  instr->type_literal(),
5073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  &cmp1,
5074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  &cmp2);
50753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cmp1.is_valid());
5077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!cmp2.is_reg() || cmp2.rm().is_valid());
50783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (final_branch_condition != kNoCondition) {
5080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitBranch(instr, final_branch_condition, cmp1, cmp2);
50813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
50823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
50833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
50853ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochCondition LCodeGen::EmitTypeofIs(Label* true_label,
50863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Label* false_label,
50873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Register input,
50883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Handle<String> type_name,
5089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Register* cmp1,
5090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 Operand* cmp2) {
50913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This function utilizes the delay slot heavily. This is used to load
50923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // values that are always usable without depending on the type of the input
50933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // register.
50943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition final_branch_condition = kNoCondition;
50953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
5096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
5097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (String::Equals(type_name, factory->number_string())) {
50983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(input, true_label);
50993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(input, FieldMemOperand(input, HeapObject::kMapOffset));
51003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
5101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *cmp1 = input;
5102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *cmp2 = Operand(at);
51033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    final_branch_condition = eq;
51043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(type_name, factory->string_string())) {
51063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(input, false_label);
51073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ GetObjectType(input, input, scratch);
5108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    *cmp1 = scratch;
5109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    *cmp2 = Operand(FIRST_NONSTRING_TYPE);
5110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    final_branch_condition = lt;
5111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(type_name, factory->symbol_string())) {
5113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input, false_label);
5114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ GetObjectType(input, input, scratch);
5115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *cmp1 = scratch;
5116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *cmp2 = Operand(SYMBOL_TYPE);
51173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    final_branch_condition = eq;
51183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(type_name, factory->boolean_string())) {
51203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kTrueValueRootIndex);
51213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
51223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kFalseValueRootIndex);
5123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *cmp1 = at;
5124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *cmp2 = Operand(input);
51253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    final_branch_condition = eq;
51263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(type_name, factory->undefined_string())) {
5128109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadRoot(at, Heap::kNullValueRootIndex);
5129109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Branch(USE_DELAY_SLOT, false_label, eq, at, Operand(input));
51303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The first instruction of JumpIfSmi is an And - it is safe in the delay
51313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // slot.
51323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(input, false_label);
51333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for undetectable objects => true.
51343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lw(input, FieldMemOperand(input, HeapObject::kMapOffset));
51353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ lbu(at, FieldMemOperand(input, Map::kBitFieldOffset));
51363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ And(at, at, 1 << Map::kIsUndetectable);
5137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *cmp1 = at;
5138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *cmp2 = Operand(zero_reg);
51393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    final_branch_condition = ne;
51403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(type_name, factory->function_string())) {
51423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(input, false_label);
5143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
5144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ lbu(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
5145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ And(scratch, scratch,
5146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
5147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    *cmp1 = scratch;
5148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    *cmp2 = Operand(1 << Map::kIsCallable);
51493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    final_branch_condition = eq;
51503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (String::Equals(type_name, factory->object_string())) {
51523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(input, false_label);
5153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(at, Heap::kNullValueRootIndex);
5154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
5155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
5156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ GetObjectType(input, scratch, scratch1());
5157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Branch(false_label, lt, scratch1(), Operand(FIRST_JS_RECEIVER_TYPE));
5158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Check for callable or undetectable objects => false.
5159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ lbu(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
5160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ And(at, scratch,
5161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
5162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *cmp1 = at;
5163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *cmp2 = Operand(zero_reg);
51643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    final_branch_condition = eq;
51653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
5167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *cmp1 = at;
5168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *cmp2 = Operand(zero_reg);  // Set to valid regs, to avoid caller assertion.
51693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(false_label);
51703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
51713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return final_branch_condition;
51733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
51743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
5177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (info()->ShouldEnsureSpaceForLazyDeopt()) {
5178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Ensure that we have enough space after the previous lazy-bailout
5179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // instruction for patching the code here.
5180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int current_pc = masm()->pc_offset();
5181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (current_pc < last_lazy_deopt_pc_ + space_needed) {
5182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
5183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK_EQ(0, padding_size % Assembler::kInstrSize);
5184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      while (padding_size > 0) {
5185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ nop();
5186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        padding_size -= Assembler::kInstrSize;
5187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
51883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
51893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
51903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  last_lazy_deopt_pc_ = masm()->pc_offset();
51913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
51923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLazyBailout(LLazyBailout* instr) {
5195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  last_lazy_deopt_pc_ = masm()->pc_offset();
5196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->HasEnvironment());
51973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LEnvironment* env = instr->environment();
51983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
51993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
52003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
52013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeoptimize(LDeoptimize* instr) {
5204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Deoptimizer::BailoutType type = instr->hydrogen()->type();
5205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
5206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // needed return address), even though the implementation of LAZY and EAGER is
5207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // now identical. When LAZY is eventually completely folded into EAGER, remove
5208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the special case below.
5209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info()->IsStub() && type == Deoptimizer::EAGER) {
5210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    type = Deoptimizer::LAZY;
5211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DeoptimizeIf(al, instr, instr->hydrogen()->reason(), type, zero_reg,
5214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               Operand(zero_reg));
52153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
52163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDummy(LDummy* instr) {
5219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Nothing to see here, move on!
52203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
52213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDummyUse(LDummyUse* instr) {
5224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Nothing to see here, move on!
52253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
52263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
5229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushSafepointRegistersScope scope(this);
5230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadContextFromDeferred(instr->context());
52313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
52323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RecordSafepointWithLazyDeopt(
52333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
5234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->HasEnvironment());
52353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LEnvironment* env = instr->environment();
52363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
52373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
52383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStackCheck(LStackCheck* instr) {
5241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredStackCheck final : public LDeferredCode {
52423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   public:
52433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
52443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : LDeferredCode(codegen), instr_(instr) { }
5245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override { codegen()->DoDeferredStackCheck(instr_); }
5246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
5247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
52483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch   private:
52493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LStackCheck* instr_;
52503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
52513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(instr->HasEnvironment());
52533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LEnvironment* env = instr->environment();
52543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // There is no LLazyBailout instruction for stack-checks. We have to
52553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // prepare for lazy deoptimization explicitly here.
52563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (instr->hydrogen()->is_function_entry()) {
52573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Perform stack overflow check.
52583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label done;
52593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kStackLimitRootIndex);
52603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(&done, hs, sp, Operand(at));
5261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(instr->context()->IsRegister());
5262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(ToRegister(instr->context()).is(cp));
5263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CallCode(isolate()->builtins()->StackCheck(),
5264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             RelocInfo::CODE_TARGET,
5265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             instr);
52663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&done);
52673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
5268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(instr->hydrogen()->is_backwards_branch());
52693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Perform stack overflow check if this goto needs it before jumping.
52703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DeferredStackCheck* deferred_stack_check =
5271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new(zone()) DeferredStackCheck(this, instr);
52723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ LoadRoot(at, Heap::kStackLimitRootIndex);
52733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ Branch(deferred_stack_check->entry(), lo, sp, Operand(at));
5274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
52753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(instr->done_label());
52763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    deferred_stack_check->SetExit(instr->done_label());
52773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
52783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Don't record a deoptimization index for the safepoint here.
52793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // This will be done explicitly when emitting call and the safepoint in
52803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // the deferred code.
52813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
52823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
52833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoOsrEntry(LOsrEntry* instr) {
52863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This is a pseudo-instruction that ensures that the environment here is
52873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // properly registered for deoptimization and records the assembler's PC
52883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // offset.
52893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LEnvironment* environment = instr->environment();
52903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the environment were already registered, we would have no way of
52923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // backpatching it with the spill slot operands.
5293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!environment->HasBeenRegistered());
52943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
5295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateOsrPrologue();
52973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
52983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
53013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
53023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = ToRegister(instr->object());
53033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label use_cache, call_runtime;
5305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(object.is(a0));
5306109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CheckEnumCache(&call_runtime);
53073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(object, HeapObject::kMapOffset));
53093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&use_cache);
53103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the set of properties to enumerate.
53123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&call_runtime);
53133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(object);
5314109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CallRuntime(Runtime::kForInEnumerate, instr);
53153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&use_cache);
53163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
53173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
53203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register map = ToRegister(instr->map());
53213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
5322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label load_cache, done;
5323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ EnumLength(result, map);
5324c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Branch(&load_cache, ne, result, Operand(Smi::kZero));
5325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ li(result, Operand(isolate()->factory()->empty_fixed_array()));
5326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done);
5327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&load_cache);
53293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ LoadInstanceDescriptors(map, result);
53303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result,
5331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        FieldMemOperand(result, DescriptorArray::kEnumCacheOffset));
53323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result,
53333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
5334f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(eq, instr, DeoptimizeReason::kNoCache, result,
5335f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch               Operand(zero_reg));
5336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
53383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
53393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
53423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = ToRegister(instr->value());
53433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register map = ToRegister(instr->map());
53443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
5345f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeoptimizeIf(ne, instr, DeoptimizeReason::kWrongMap, map,
5346f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch               Operand(scratch0()));
5347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
5348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
5351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register result,
5352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register object,
5353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register index) {
5354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PushSafepointRegistersScope scope(this);
5355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(object, index);
5356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(cp, zero_reg);
5357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble);
5358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RecordSafepointWithRegisters(
5359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch     instr->pointer_map(), 2, Safepoint::kNoLazyDeopt);
5360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ StoreToSafepointRegisterSlot(v0, result);
53613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
53623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
5365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class DeferredLoadMutableDouble final : public LDeferredCode {
5366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   public:
5367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeferredLoadMutableDouble(LCodeGen* codegen,
5368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              LLoadFieldByIndex* instr,
5369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register result,
5370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register object,
5371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              Register index)
5372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : LDeferredCode(codegen),
5373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          instr_(instr),
5374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          result_(result),
5375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          object_(object),
5376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          index_(index) {
5377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void Generate() override {
5379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      codegen()->DoDeferredLoadMutableDouble(instr_, result_, object_, index_);
5380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
5381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    LInstruction* instr() override { return instr_; }
5382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch   private:
5384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LLoadFieldByIndex* instr_;
5385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register result_;
5386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register object_;
5387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register index_;
5388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
5389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
53903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register object = ToRegister(instr->object());
53913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register index = ToRegister(instr->index());
53923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register result = ToRegister(instr->result());
53933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register scratch = scratch0();
53943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DeferredLoadMutableDouble* deferred;
5396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  deferred = new(zone()) DeferredLoadMutableDouble(
5397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      this, instr, result, object, index);
5398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
53993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label out_of_object, done;
5400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ And(scratch, index, Operand(Smi::FromInt(1)));
5402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Branch(deferred->entry(), ne, scratch, Operand(zero_reg));
5403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sra(index, index, 1);
5404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
54053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(USE_DELAY_SLOT, &out_of_object, lt, index, Operand(zero_reg));
54063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sll(scratch, index, kPointerSizeLog2 - kSmiTagSize);  // In delay slot.
54073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
54083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kPointerSizeLog2 > kSmiTagSize);
54093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Addu(scratch, object, scratch);
54103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(scratch, JSObject::kHeaderSize));
54113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
54123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Branch(&done);
54133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
54143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&out_of_object);
54153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
54163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Index is equal to negated out of object property index plus 1.
54173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Subu(scratch, result, scratch);
54183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ lw(result, FieldMemOperand(scratch,
54193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                FixedArray::kHeaderSize - kPointerSize));
5420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(deferred->exit());
54213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
54223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
54233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
54243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef __
54253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
5427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
5428