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