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(÷nd_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(÷nd_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(¬_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(¬_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(¬_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(¬_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(¬_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(¬_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(¬_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(¬_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