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#include "src/v8.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X87 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/deoptimizer.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/hydrogen-osr.h" 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/stub-cache.h" 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/x87/lithium-codegen-x87.h" 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 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. 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen 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 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void BeforeCall(int call_size) const OVERRIDE {} 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual 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 support_aligned_spilled_doubles_ = info()->IsOptimizing(); 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dynamic_frame_alignment_ = info()->IsOptimizing() && 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ((chunk()->num_double_slots() > 2 && 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !chunk()->graph()->is_recursive()) || 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !info()->osr_ast_id().IsNone()); 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GeneratePrologue() && 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateBody() && 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDeferredCode() && 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateJumpTable() && 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateSafepointTable(); 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::FinishCode(Handle<Code> code) { 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_done()); 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code->set_stack_slots(GetStackSlotCount()); 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code); 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PopulateDeoptimizationData(code); 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!info()->IsStub()) { 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code); 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef _MSC_VER 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::MakeSureStackPagesMapped(int offset) { 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kPageSize = 4 * KB; 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (offset -= kPageSize; offset > 0; offset -= kPageSize) { 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, offset), eax); 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::GeneratePrologue() { 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_generating()); 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info()->IsOptimizing()) { 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm_); 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (strlen(FLAG_stop_at) > 0 && 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ int3(); 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Sloppy mode functions and builtins need to replace the receiver with the 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // global proxy when called as functions (without an explicit receiver 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // object). 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info_->this_has_uses() && 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info_->strict_mode() == SLOPPY && 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !info_->is_native()) { 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // +1 for return address. 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, Operand(esp, receiver_offset)); 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ecx, isolate()->factory()->undefined_value()); 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &ok, Label::kNear); 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, GlobalObjectOperand()); 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalProxyOffset)); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, receiver_offset), ecx); 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok); 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move state of dynamic frame alignment into edx. 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(edx, Immediate(kNoAlignmentPadding)); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label do_not_pad, align_loop; 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kDoubleSize == 2 * kPointerSize); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Align esp + 4 to a multiple of 2 * kPointerSize. 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(esp, Immediate(kPointerSize)); 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &do_not_pad, Label::kNear); 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(0)); 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, esp); 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(edx, Immediate(kAlignmentPaddingPushed)); 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy arguments, receiver, and return address. 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, Immediate(scope()->num_parameters() + 2)); 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&align_loop); 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Operand(ebx, 1 * kPointerSize)); 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(ebx, 0), eax); 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(Operand(ebx), Immediate(kPointerSize)); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ dec(ecx); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &align_loop, Label::kNear); 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(ebx, 0), Immediate(kAlignmentZapValue)); 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&do_not_pad); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info()->set_prologue_offset(masm_->pc_offset()); 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (NeedsEagerFrame()) { 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!frame_is_built_); 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch frame_is_built_ = true; 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info()->IsStub()) { 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StubPrologue(); 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Prologue(info()->IsCodePreAgingActive()); 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info()->AddNoFrameRange(0, masm_->pc_offset()); 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info()->IsOptimizing() && 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dynamic_frame_alignment_ && 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FLAG_debug_code) { 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(esp, Immediate(kPointerSize)); 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(zero, kFrameIsExpectedToBeAligned); 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Reserve space for the stack slots needed by the code. 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int slots = GetStackSlotCount(); 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(slots != 0 || !info()->IsOptimizing()); 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (slots > 0) { 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (slots == 1) { 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (dynamic_frame_alignment_) { 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(edx); 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(kNoAlignmentPadding)); 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(Operand(esp), Immediate(slots * kPointerSize)); 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef _MSC_VER 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MakeSureStackPagesMapped(slots * kPointerSize); 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(eax); 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(eax), Immediate(slots)); 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop; 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop); 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(MemOperand(esp, eax, times_4, 0), 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(kSlotsZapValue)); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ dec(eax); 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &loop); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(eax); 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(Operand(esp), Immediate(slots * kPointerSize)); 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef _MSC_VER 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MakeSureStackPagesMapped(slots * kPointerSize); 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (support_aligned_spilled_doubles_) { 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment(";;; Store dynamic frame alignment tag for spilled doubles"); 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store dynamic frame alignment state in the first local. 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = JavaScriptFrameConstants::kDynamicAlignmentStateOffset; 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (dynamic_frame_alignment_) { 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(ebp, offset), edx); 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(ebp, offset), Immediate(kNoAlignmentPadding)); 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Possibly allocate a local context. 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (heap_slots > 0) { 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment(";;; Allocate local context"); 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool need_write_barrier = true; 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Argument to NewContext is the function, which is still in edi. 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (heap_slots <= FastNewContextStub::kMaximumSlots) { 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastNewContextStub stub(isolate(), heap_slots); 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Result of FastNewContextStub is always in new space. 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch need_write_barrier = false; 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(edi); 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kNewFunctionContext, 1); 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepoint(Safepoint::kNoLazyDeopt); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Context is returned in eax. It replaces the context passed to us. 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It's saved in the stack and kept live in esi. 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, eax); 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax); 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy parameters into context if necessary. 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int num_parameters = scope()->num_parameters(); 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < num_parameters; i++) { 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var = scope()->parameter(i); 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsContextSlot()) { 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parameter_offset = StandardFrameConstants::kCallerSPOffset + 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (num_parameters - 1 - i) * kPointerSize; 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load parameter from stack. 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Operand(ebp, parameter_offset)); 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store it in the context. 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int context_offset = Context::SlotOffset(var->index()); 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esi, context_offset), eax); 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier. This clobbers eax and ebx. 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (need_write_barrier) { 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot(esi, context_offset, eax, ebx, 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs); 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (FLAG_debug_code) { 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfInNewSpace(esi, eax, &done, Label::kNear); 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kExpectedNewSpaceObject); 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment(";;; End allocate local context"); 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initailize FPU state. 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fninit(); 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Trace the call. 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_trace && info()->IsOptimizing()) { 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have not executed any compiled code yet, so esi still holds the 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // incoming context. 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kTraceEnter, 0); 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return !is_aborted(); 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::GenerateOsrPrologue() { 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate the OSR entry prologue at the first unknown OSR value, or if there 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // are none, at the OSR entrypoint instruction. 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (osr_pc_offset_ >= 0) return; 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch osr_pc_offset_ = masm()->pc_offset(); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move state of dynamic frame alignment into edx. 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(edx, Immediate(kNoAlignmentPadding)); 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label do_not_pad, align_loop; 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Align ebp + 4 to a multiple of 2 * kPointerSize. 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(ebp, Immediate(kPointerSize)); 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &do_not_pad, Label::kNear); 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(0)); 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, esp); 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(edx, Immediate(kAlignmentPaddingPushed)); 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move all parts of the frame over one word. The frame consists of: 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // unoptimized frame slots, alignment state, context, frame pointer, return 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // address, receiver, and the arguments. 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, Immediate(scope()->num_parameters() + 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5 + graph()->osr()->UnoptimizedFrameSlots())); 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&align_loop); 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Operand(ebx, 1 * kPointerSize)); 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(ebx, 0), eax); 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(Operand(ebx), Immediate(kPointerSize)); 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ dec(ecx); 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &align_loop, Label::kNear); 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(ebx, 0), Immediate(kAlignmentZapValue)); 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(Operand(ebp), Immediate(kPointerSize)); 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&do_not_pad); 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save the first local, which is overwritten by the alignment state. 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand alignment_loc = MemOperand(ebp, -3 * kPointerSize); 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(alignment_loc); 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set the dynamic frame alignment state. 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(alignment_loc, edx); 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Adjust the frame size, subsuming the unoptimized frame into the 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // optimized frame. 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(slots >= 1); 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(esp, Immediate((slots - 1) * kPointerSize)); 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initailize FPU state. 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fninit(); 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->IsCall()) { 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!instr->IsLazyBailout() && !instr->IsGap()) { 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch safepoints_.BumpLastLazySafepointIndex(); 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlushX87StackIfNecessary(instr); 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) { 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // When return from function call, FPU should be initialized again. 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->IsCall() && instr->ClobbersDoubleRegisters(isolate())) { 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool double_result = instr->HasDoubleRegisterResult(); 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (double_result) { 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(esp, Operand(esp, -kDoubleSize)); 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp_d(Operand(esp, 0)); 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fninit(); 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (double_result) { 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(Operand(esp, 0)); 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(esp, Operand(esp, kDoubleSize)); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->IsGoto()) { 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.LeavingBlock(current_block_, LGoto::cast(instr), this); 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (FLAG_debug_code && FLAG_enable_slow_asserts && 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !instr->IsGap() && !instr->IsReturn()) { 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->ClobbersDoubleRegisters(isolate())) { 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->HasDoubleRegisterResult()) { 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(1, x87_stack_.depth()); 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0, x87_stack_.depth()); 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ VerifyX87StackDepth(x87_stack_.depth()); 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::GenerateJumpTable() { 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label needs_frame; 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (jump_table_.length() > 0) { 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment(";;; -------------------- Jump table --------------------"); 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < jump_table_.length(); i++) { 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Deoptimizer::JumpTableEntry* table_entry = &jump_table_[i]; 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&table_entry->label); 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address entry = table_entry->address; 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptComment(table_entry->reason); 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (table_entry->needs_frame) { 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!info()->saves_caller_doubles()); 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(ExternalReference::ForDeoptEntry(entry))); 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (needs_frame.is_bound()) { 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&needs_frame); 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&needs_frame); 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(MemOperand(ebp, StandardFrameConstants::kContextOffset)); 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This variant of deopt can only be used with stubs. Since we don't 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // have a function pointer to install in the stack frame that we're 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // building, install a special marker there instead. 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(info()->IsStub()); 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(Smi::FromInt(StackFrame::STUB))); 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push a PC inside the function so that the deopt code can find where 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the deopt comes from. It doesn't have to be the precise return 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // address of a "calling" LAZY deopt, it only has to be somewhere 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // inside the code body. 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label push_approx_pc; 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(&push_approx_pc); 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&push_approx_pc); 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the continuation which was stashed were the ebp should 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // be. Replace it with the saved ebp. 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(MemOperand(esp, 3 * kPointerSize)); 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(MemOperand(esp, 4 * kPointerSize), ebp); 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(ebp, MemOperand(esp, 4 * kPointerSize)); 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); // Call the continuation without clobbering registers. 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(entry, RelocInfo::RUNTIME_ENTRY); 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return !is_aborted(); 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::GenerateDeferredCode() { 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_generating()); 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (deferred_.length() > 0) { 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LDeferredCode* code = deferred_[i]; 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Stack copy(code->x87_stack()); 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_ = copy; 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HValue* value = 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instructions_->at(code->instruction_index())->hydrogen_value(); 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordAndWritePosition( 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk()->graph()->SourcePositionToScriptPosition(value->position())); 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment(";;; <@%d,#%d> " 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "-------------------- Deferred %s --------------------", 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code->instruction_index(), 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code->instr()->hydrogen_value()->id(), 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code->instr()->Mnemonic()); 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(code->entry()); 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (NeedsDeferredFrame()) { 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment(";;; Build frame"); 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!frame_is_built_); 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(info()->IsStub()); 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch frame_is_built_ = true; 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Build the frame in such a way that esi isn't trashed. 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ebp); // Caller's frame pointer. 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Operand(ebp, StandardFrameConstants::kContextOffset)); 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(Smi::FromInt(StackFrame::STUB))); 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(ebp, Operand(esp, 2 * kPointerSize)); 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment(";;; Deferred code"); 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code->Generate(); 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (NeedsDeferredFrame()) { 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(code->done()); 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment(";;; Destroy frame"); 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(frame_is_built_); 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch frame_is_built_ = false; 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esp, ebp); 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(ebp); 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(code->exit()); 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Deferred code is the last part of the instruction sequence. Mark 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the generated code as done unless we bailed out. 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!is_aborted()) status_ = DONE; 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return !is_aborted(); 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::GenerateSafepointTable() { 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_done()); 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!info()->IsStub()) { 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For lazy deoptimization we need space to patch a call after every call. 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Ensure there is always space for such patching, even if the code ends 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // in a call. 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int target_offset = masm()->pc_offset() + Deoptimizer::patch_size(); 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (masm()->pc_offset() < target_offset) { 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm()->nop(); 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch safepoints_.Emit(masm(), GetStackSlotCount()); 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return !is_aborted(); 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister LCodeGen::ToRegister(int index) const { 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register::FromAllocationIndex(index); 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochX87Register LCodeGen::ToX87Register(int index) const { 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return X87Register::FromAllocationIndex(index); 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87LoadForUsage(X87Register reg) { 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(x87_stack_.Contains(reg)); 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.Fxch(reg); 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.pop(); 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87LoadForUsage(X87Register reg1, X87Register reg2) { 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(x87_stack_.Contains(reg1)); 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(x87_stack_.Contains(reg2)); 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (reg1.is(reg2) && x87_stack_.depth() == 1) { 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(x87_stack_.st(reg1)); 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.push(reg1); 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.pop(); 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.pop(); 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.Fxch(reg1, 1); 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.Fxch(reg2); 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.pop(); 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.pop(); 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint LCodeGen::X87Stack::GetLayout() { 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int layout = stack_depth_; 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < stack_depth_; i++) { 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch layout |= (stack_[stack_depth_ - 1 - i].code() << ((i + 1) * 3)); 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return layout; 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) { 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_mutable_); 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Contains(reg) && stack_depth_ > other_slot); 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int i = ArrayIndex(reg); 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int st = st2idx(i); 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (st != other_slot) { 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int other_i = st2idx(other_slot); 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register other = stack_[other_i]; 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stack_[other_i] = reg; 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stack_[i] = other; 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (st == 0) { 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fxch(other_slot); 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (other_slot == 0) { 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fxch(st); 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fxch(st); 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fxch(other_slot); 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fxch(st); 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint LCodeGen::X87Stack::st2idx(int pos) { 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return stack_depth_ - pos - 1; 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint LCodeGen::X87Stack::ArrayIndex(X87Register reg) { 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < stack_depth_; i++) { 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stack_[i].is(reg)) return i; 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return -1; 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::X87Stack::Contains(X87Register reg) { 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < stack_depth_; i++) { 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stack_[i].is(reg)) return true; 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Stack::Free(X87Register reg) { 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_mutable_); 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Contains(reg)); 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int i = ArrayIndex(reg); 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int st = st2idx(i); 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (st > 0) { 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // keep track of how fstp(i) changes the order of elements 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int tos_i = st2idx(0); 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stack_[i] = stack_[tos_i]; 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pop(); 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp(st); 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) { 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (x87_stack_.Contains(dst)) { 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.Fxch(dst); 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp(0); 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.push(dst); 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fld(src, opts); 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Mov(X87Register dst, X87Register src, X87OperandType opts) { 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (x87_stack_.Contains(dst)) { 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.Fxch(dst); 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp(0); 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.pop(); 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push ST(i) onto the FPU register stack 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(x87_stack_.st(src)); 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.push(dst); 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push ST(i) onto the FPU register stack 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(x87_stack_.st(src)); 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.push(dst); 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Fld(Operand src, X87OperandType opts) { 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!src.is_reg_only()); 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (opts) { 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kX87DoubleOperand: 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(src); 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kX87FloatOperand: 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_s(src); 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kX87IntOperand: 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fild_s(src); 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Mov(Operand dst, X87Register src, X87OperandType opts) { 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!dst.is_reg_only()); 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.Fxch(src); 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (opts) { 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kX87DoubleOperand: 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fst_d(dst); 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kX87FloatOperand: 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fst_s(dst); 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kX87IntOperand: 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fist_s(dst); 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Stack::PrepareToWrite(X87Register reg) { 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_mutable_); 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Contains(reg)) { 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Free(reg); 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Mark this register as the next register to write to 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stack_[stack_depth_] = reg; 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Stack::CommitWrite(X87Register reg) { 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_mutable_); 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assert the reg is prepared to write, but not on the virtual stack yet 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!Contains(reg) && stack_[stack_depth_].is(reg) && 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stack_depth_ < X87Register::kMaxNumAllocatableRegisters); 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stack_depth_++; 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87PrepareBinaryOp( 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register left, X87Register right, X87Register result) { 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // You need to use DefineSameAsFirst for x87 instructions 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result.is(left)); 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.Fxch(right, 1); 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.Fxch(left); 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) { 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stack_depth_ > 0 && instr->ClobbersDoubleRegisters(isolate())) { 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool double_inputs = instr->HasDoubleRegisterInput(); 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Flush stack from tos down, since FreeX87() will mess with tos 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = stack_depth_-1; i >= 0; i--) { 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register reg = stack_[i]; 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Skip registers which contain the inputs for the next instruction 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // when flushing the stack 694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (double_inputs && instr->IsDoubleInput(reg, cgen)) { 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Free(reg); 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (i < stack_depth_-1) i++; 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->IsReturn()) { 702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (stack_depth_ > 0) { 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp(0); 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stack_depth_--; 705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code && FLAG_enable_slow_asserts) __ VerifyX87StackDepth(0); 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::X87Stack::LeavingBlock(int current_block_id, LGoto* goto_instr, 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LCodeGen* cgen) { 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For going to a joined block, an explicit LClobberDoubles is inserted before 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // LGoto. Because all used x87 registers are spilled to stack slots. The 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ResolvePhis phase of register allocator could guarantee the two input's x87 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stacks have the same layout. So don't check stack_depth_ <= 1 here. 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int goto_block_id = goto_instr->block_id(); 718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_block_id + 1 != goto_block_id) { 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we have a value on the x87 stack on leaving a block, it must be a 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // phi input. If the next block we compile is not the join block, we have 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to discard the stack state. 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Before discarding the stack state, we need to save it if the "goto block" 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // has unreachable last predecessor when FLAG_unreachable_code_elimination. 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_unreachable_code_elimination) { 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int length = goto_instr->block()->predecessors()->length(); 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool has_unreachable_last_predecessor = false; 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < length; i++) { 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HBasicBlock* block = goto_instr->block()->predecessors()->at(i); 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (block->IsUnreachable() && 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (block->block_id() + 1) == goto_block_id) { 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch has_unreachable_last_predecessor = true; 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (has_unreachable_last_predecessor) { 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cgen->x87_stack_map_.find(goto_block_id) == 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cgen->x87_stack_map_.end()) { 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Stack* stack = new (cgen->zone()) X87Stack(*this); 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cgen->x87_stack_map_.insert(std::make_pair(goto_block_id, stack)); 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Discard the stack state. 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stack_depth_ = 0; 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitFlushX87ForDeopt() { 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The deoptimizer does not support X87 Registers. But as long as we 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // deopt from a stub its not a problem, since we will re-materialize the 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // original stub inputs, which can't be double registers. 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // DCHECK(info()->IsStub()); 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code && FLAG_enable_slow_asserts) { 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushfd(); 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ VerifyX87StackDepth(x87_stack_.depth()); 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popfd(); 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Flush X87 stack in the deoptimizer entry. 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister LCodeGen::ToRegister(LOperand* op) const { 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(op->IsRegister()); 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ToRegister(op->index()); 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochX87Register LCodeGen::ToX87Register(LOperand* op) const { 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(op->IsDoubleRegister()); 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ToX87Register(op->index()); 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint32_t LCodeGen::ToInteger32(LConstantOperand* op) const { 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ToRepresentation(op, Representation::Integer32()); 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint32_t LCodeGen::ToRepresentation(LConstantOperand* op, 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Representation& r) const { 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HConstant* constant = chunk_->LookupConstant(op); 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t value = constant->Integer32Value(); 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (r.IsInteger32()) return value; 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(r.IsSmiOrTagged()); 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reinterpret_cast<int32_t>(Smi::FromInt(value)); 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HConstant* constant = chunk_->LookupConstant(op); 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return constant->handle(isolate()); 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble LCodeGen::ToDouble(LConstantOperand* op) const { 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HConstant* constant = chunk_->LookupConstant(op); 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(constant->HasDoubleValue()); 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return constant->DoubleValue(); 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochExternalReference LCodeGen::ToExternalReference(LConstantOperand* op) const { 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HConstant* constant = chunk_->LookupConstant(op); 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(constant->HasExternalReferenceValue()); 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return constant->ExternalReferenceValue(); 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::IsInteger32(LConstantOperand* op) const { 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool LCodeGen::IsSmi(LConstantOperand* op) const { 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return chunk_->LookupLiteralRepresentation(op).IsSmi(); 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int ArgumentsOffsetWithoutFrame(int index) { 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(index < 0); 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return -(index + 1) * kPointerSize + kPCOnStackSize; 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOperand LCodeGen::ToOperand(LOperand* op) const { 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (op->IsRegister()) return Operand(ToRegister(op)); 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!op->IsDoubleRegister()); 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (NeedsEagerFrame()) { 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Operand(ebp, StackSlotOffset(op->index())); 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Retrieve parameter without eager stack-frame relative to the 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stack-pointer. 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Operand(esp, ArgumentsOffsetWithoutFrame(op->index())); 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOperand LCodeGen::HighOperand(LOperand* op) { 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(op->IsDoubleStackSlot()); 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (NeedsEagerFrame()) { 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Operand(ebp, StackSlotOffset(op->index()) + kPointerSize); 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Retrieve parameter without eager stack-frame relative to the 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stack-pointer. 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Operand( 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch esp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize); 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::WriteTranslation(LEnvironment* environment, 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Translation* translation) { 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (environment == NULL) return; 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The translation includes one command per value in the environment. 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int translation_size = environment->translation_size(); 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The output frame height does not include the parameters. 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int height = translation_size - environment->parameter_count(); 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WriteTranslation(environment->outer(), translation); 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool has_closure_id = !info()->closure().is_null() && 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !info()->closure().is_identical_to(environment->closure()); 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int closure_id = has_closure_id 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? DefineDeoptimizationLiteral(environment->closure()) 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Translation::kSelfLiteralId; 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (environment->frame_type()) { 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case JS_FUNCTION: 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->BeginJSFrame(environment->ast_id(), closure_id, height); 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case JS_CONSTRUCT: 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->BeginConstructStubFrame(closure_id, translation_size); 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case JS_GETTER: 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(translation_size == 1); 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(height == 0); 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->BeginGetterStubFrame(closure_id); 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case JS_SETTER: 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(translation_size == 2); 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(height == 0); 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->BeginSetterStubFrame(closure_id); 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ARGUMENTS_ADAPTOR: 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case STUB: 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->BeginCompiledStubFrame(); 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int object_index = 0; 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int dematerialized_index = 0; 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < translation_size; ++i) { 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* value = environment->values()->at(i); 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddToTranslation(environment, 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation, 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value, 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch environment->HasTaggedValueAt(i), 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch environment->HasUint32ValueAt(i), 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &object_index, 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &dematerialized_index); 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::AddToTranslation(LEnvironment* environment, 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Translation* translation, 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* op, 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_tagged, 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_uint32, 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int* object_index_pointer, 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int* dematerialized_index_pointer) { 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (op == LEnvironment::materialization_marker()) { 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int object_index = (*object_index_pointer)++; 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (environment->ObjectIsDuplicateAt(object_index)) { 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int dupe_of = environment->ObjectDuplicateOfAt(object_index); 923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->DuplicateObject(dupe_of); 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int object_length = environment->ObjectLengthAt(object_index); 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (environment->ObjectIsArgumentsAt(object_index)) { 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->BeginArgumentsObject(object_length); 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->BeginCapturedObject(object_length); 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int dematerialized_index = *dematerialized_index_pointer; 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int env_offset = environment->translation_size() + dematerialized_index; 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *dematerialized_index_pointer += object_length; 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < object_length; ++i) { 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* value = environment->values()->at(env_offset + i); 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddToTranslation(environment, 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation, 939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value, 940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch environment->HasTaggedValueAt(env_offset + i), 941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch environment->HasUint32ValueAt(env_offset + i), 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch object_index_pointer, 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dematerialized_index_pointer); 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (op->IsStackSlot()) { 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_tagged) { 950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->StoreStackSlot(op->index()); 951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (is_uint32) { 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->StoreUint32StackSlot(op->index()); 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->StoreInt32StackSlot(op->index()); 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (op->IsDoubleStackSlot()) { 957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->StoreDoubleStackSlot(op->index()); 958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (op->IsRegister()) { 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(op); 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_tagged) { 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->StoreRegister(reg); 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (is_uint32) { 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->StoreUint32Register(reg); 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->StoreInt32Register(reg); 966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (op->IsDoubleRegister()) { 968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register reg = ToX87Register(op); 969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->StoreDoubleRegister(reg); 970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (op->IsConstantOperand()) { 971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op)); 972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int src_index = DefineDeoptimizationLiteral(constant->handle(isolate())); 973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation->StoreLiteral(src_index); 974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::CallCodeGeneric(Handle<Code> code, 981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::Mode mode, 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstruction* instr, 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SafepointMode safepoint_mode) { 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr != NULL); 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(code, mode); 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithLazyDeopt(instr, safepoint_mode); 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Signal that we don't inline smi code before these stubs in the 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // optimizing code generator. 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (code->kind() == Code::BINARY_OP_IC || 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code->kind() == Code::COMPARE_IC) { 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ nop(); 993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::CallCode(Handle<Code> code, 998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::Mode mode, 999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstruction* instr) { 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::CallRuntime(const Runtime::Function* fun, int argc, 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstruction* instr, SaveFPRegsMode save_doubles) { 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr != NULL); 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->HasPointerMap()); 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(fun, argc, save_doubles); 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(info()->is_calling()); 1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::LoadContextFromDeferred(LOperand* context) { 1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (context->IsRegister()) { 1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!ToRegister(context).is(esi)) { 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, ToRegister(context)); 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (context->IsStackSlot()) { 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, ToOperand(context)); 1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (context->IsConstantOperand()) { 1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HConstant* constant = 1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_->LookupConstant(LConstantOperand::cast(context)); 1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadObject(esi, Handle<Object>::cast(constant->handle(isolate()))); 1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, 1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int argc, 1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstruction* instr, 1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* context) { 1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadContextFromDeferred(context); 1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntimeSaveDoubles(id); 1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithRegisters( 1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); 1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(info()->is_calling()); 1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::RegisterEnvironmentForDeoptimization( 1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LEnvironment* environment, Safepoint::DeoptMode mode) { 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch environment->set_has_been_used(); 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!environment->HasBeenRegistered()) { 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Physical stack frame layout: 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -x ............. -4 0 ..................................... y 1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // [incoming arguments] [spill slots] [pushed outgoing arguments] 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Layout of the environment: 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0 ..................................................... size-1 1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // [parameters] [locals] [expression stack including arguments] 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Layout of the translation: 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0 ........................................................ size - 1 + 4 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // [expression stack including arguments] [locals] [4 words] [parameters] 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // |>------------ translation_size ------------<| 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int frame_count = 0; 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int jsframe_count = 0; 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (LEnvironment* e = environment; e != NULL; e = e->outer()) { 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++frame_count; 1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (e->frame_type() == JS_FUNCTION) { 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++jsframe_count; 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Translation translation(&translations_, frame_count, jsframe_count, zone()); 1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WriteTranslation(environment, &translation); 1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int deoptimization_index = deoptimizations_.length(); 1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int pc_offset = masm()->pc_offset(); 1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch environment->Register(deoptimization_index, 1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translation.index(), 1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); 1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch deoptimizations_.Add(environment, zone()); 1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr, 1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* detail, 1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Deoptimizer::BailoutType bailout_type) { 1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LEnvironment* environment = instr->environment(); 1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(environment->HasBeenRegistered()); 1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int id = environment->deoptimization_index(); 1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(info()->IsOptimizing() || info()->IsStub()); 1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address entry = 1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); 1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry == NULL) { 1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Abort(kBailoutWasNotPrepared); 1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (DeoptEveryNTimes()) { 1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference count = ExternalReference::stress_deopt_count(isolate()); 1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_deopt; 1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushfd(); 1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(eax); 1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Operand::StaticVariable(count)); 1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(eax, Immediate(1)); 1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &no_deopt, Label::kNear); 1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_trap_on_deopt) __ int3(); 1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Immediate(FLAG_deopt_every_n_times)); 1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand::StaticVariable(count), eax); 1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(eax); 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popfd(); 1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(frame_is_built_); 1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put the x87 stack layout in TOS. 1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (x87_stack_.depth() > 0) EmitFlushX87ForDeopt(); 1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(x87_stack_.GetLayout())); 1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fild_s(MemOperand(esp, 0)); 1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Don't touch eflags. 1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(esp, Operand(esp, kPointerSize)); 1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(entry, RelocInfo::RUNTIME_ENTRY); 1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_deopt); 1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand::StaticVariable(count), eax); 1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(eax); 1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popfd(); 1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put the x87 stack layout in TOS, so that we can save x87 fp registers in 1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the correct location. 1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear); 1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (x87_stack_.depth() > 0) EmitFlushX87ForDeopt(); 1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int x87_stack_layout = x87_stack_.GetLayout(); 1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(x87_stack_layout)); 1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fild_s(MemOperand(esp, 0)); 1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Don't touch eflags. 1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(esp, Operand(esp, kPointerSize)); 1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info()->ShouldTrapOnDeopt()) { 1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear); 1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ int3(); 1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(), 1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->Mnemonic(), detail); 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(info()->IsStub() || frame_is_built_); 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cc == no_condition && frame_is_built_) { 1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptComment(reason); 1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(entry, RelocInfo::RUNTIME_ENTRY); 1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type, 1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !frame_is_built_); 1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We often have several deopts to the same entry, reuse the last 1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // jump entry if this is the case. 1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (jump_table_.is_empty() || 1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !table_entry.IsEquivalentTo(jump_table_.last())) { 1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch jump_table_.Add(table_entry, zone()); 1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cc == no_condition) { 1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&jump_table_.last().label); 1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(cc, &jump_table_.last().label); 1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr, 1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* detail) { 1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Deoptimizer::BailoutType bailout_type = info()->IsStub() 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? Deoptimizer::LAZY 1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Deoptimizer::EAGER; 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(cc, instr, detail, bailout_type); 1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { 1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int length = deoptimizations_.length(); 1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (length == 0) return; 1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<DeoptimizationInputData> data = 1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizationInputData::New(isolate(), length, TENURED); 1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<ByteArray> translations = 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch translations_.CreateByteArray(isolate()->factory()); 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data->SetTranslationByteArray(*translations); 1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); 1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data->SetOptimizationId(Smi::FromInt(info_->optimization_id())); 1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info_->IsOptimizing()) { 1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Reference to shared function info does not change between phases. 1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllowDeferredHandleDereference allow_handle_dereference; 1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data->SetSharedFunctionInfo(*info_->shared_info()); 1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data->SetSharedFunctionInfo(Smi::FromInt(0)); 1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<FixedArray> literals = 1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); 1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { AllowDeferredHandleDereference copy_handles; 1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < deoptimization_literals_.length(); i++) { 1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch literals->set(i, *deoptimization_literals_[i]); 1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data->SetLiteralArray(*literals); 1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id().ToInt())); 1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_)); 1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Populate the deoptimization entries. 1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < length; i++) { 1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LEnvironment* env = deoptimizations_[i]; 1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data->SetAstId(i, env->ast_id()); 1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data->SetTranslationIndex(i, Smi::FromInt(env->translation_index())); 1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data->SetArgumentsStackHeight(i, 1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(env->arguments_stack_height())); 1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data->SetPc(i, Smi::FromInt(env->pc_offset())); 1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code->set_deoptimization_data(*data); 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) { 1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int result = deoptimization_literals_.length(); 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < deoptimization_literals_.length(); ++i) { 1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (deoptimization_literals_[i].is_identical_to(literal)) return i; 1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch deoptimization_literals_.Add(literal, zone()); 1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() { 1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(deoptimization_literals_.length() == 0); 1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const ZoneList<Handle<JSFunction> >* inlined_closures = 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk()->inlined_closures(); 1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0, length = inlined_closures->length(); 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch i < length; 1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch i++) { 1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DefineDeoptimizationLiteral(inlined_closures->at(i)); 1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inlined_function_count_ = deoptimization_literals_.length(); 1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::RecordSafepointWithLazyDeopt( 1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstruction* instr, SafepointMode safepoint_mode) { 1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { 1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt); 1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); 1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithRegisters( 1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->pointer_map(), 0, Safepoint::kLazyDeopt); 1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::RecordSafepoint( 1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LPointerMap* pointers, 1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Safepoint::Kind kind, 1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arguments, 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Safepoint::DeoptMode deopt_mode) { 1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(kind == expected_safepoint_kind_); 1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands(); 1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Safepoint safepoint = 1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch safepoints_.DefineSafepoint(masm(), kind, arguments, deopt_mode); 1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < operands->length(); i++) { 1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* pointer = operands->at(i); 1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (pointer->IsStackSlot()) { 1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch safepoint.DefinePointerSlot(pointer->index(), zone()); 1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch safepoint.DefinePointerRegister(ToRegister(pointer), zone()); 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::RecordSafepoint(LPointerMap* pointers, 1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Safepoint::DeoptMode mode) { 1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepoint(pointers, Safepoint::kSimple, 0, mode); 1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::RecordSafepoint(Safepoint::DeoptMode mode) { 1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LPointerMap empty_pointers(zone()); 1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepoint(&empty_pointers, mode); 1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, 1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arguments, 1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Safepoint::DeoptMode mode) { 1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, mode); 1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::RecordAndWritePosition(int position) { 1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (position == RelocInfo::kNoPosition) return; 1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm()->positions_recorder()->RecordPosition(position); 1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm()->positions_recorder()->WriteRecordedPositions(); 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const char* LabelType(LLabel* label) { 1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (label->is_loop_header()) return " (loop header)"; 1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (label->is_osr_entry()) return " (OSR entry)"; 1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ""; 1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLabel(LLabel* label) { 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------", 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current_instruction_, 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch label->hydrogen_value()->id(), 1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch label->block_id(), 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LabelType(label)); 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(label->label()); 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current_block_ = label->block_id(); 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (label->block()->predecessors()->length() > 1) { 1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // A join block's x87 stack is that of its last visited predecessor. 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the last visited predecessor block is unreachable, the stack state 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // will be wrong. In such case, use the x87 stack of reachable predecessor. 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87StackMap::const_iterator it = x87_stack_map_.find(current_block_); 1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore x87 stack. 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (it != x87_stack_map_.end()) { 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_ = *(it->second); 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DoGap(label); 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoParallelMove(LParallelMove* move) { 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch resolver_.Resolve(move); 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoGap(LGap* gap) { 1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = LGap::FIRST_INNER_POSITION; 1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch i <= LGap::LAST_INNER_POSITION; 1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch i++) { 1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); 1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LParallelMove* move = gap->GetParallelMove(inner_pos); 1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (move != NULL) DoParallelMove(move); 1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoInstructionGap(LInstructionGap* instr) { 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DoGap(instr); 1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoParameter(LParameter* instr) { 1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Nothing to do. 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCallStub(LCallStub* instr) { 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->result()).is(eax)); 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (instr->hydrogen()->major_key()) { 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CodeStub::RegExpExec: { 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegExpExecStub stub(isolate()); 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CodeStub::SubString: { 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SubStringStub stub(isolate()); 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CodeStub::StringCompare: { 1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringCompareStub stub(isolate()); 1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateOsrPrologue(); 1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) { 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dividend = ToRegister(instr->dividend()); 1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t divisor = instr->divisor(); 1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(dividend.is(ToRegister(instr->result()))); 1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Theoretically, a variation of the branch-free code for integer division by 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a power of 2 (calculating the remainder via an additional multiplication 1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (which gets simplified to an 'and') and subtraction) should be faster, and 1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to 1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // indicate that positive dividends are heavily favored, so the branching 1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // version performs better. 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HMod* hmod = instr->hydrogen(); 1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label dividend_is_not_negative, done; 1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(dividend, dividend); 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_sign, ÷nd_is_not_negative, Label::kNear); 1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Note that this is correct even for kMinInt operands. 1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ neg(dividend); 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(dividend, mask); 1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ neg(dividend); 1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "minus zero"); 1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(÷nd_is_not_negative); 1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(dividend, mask); 1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoModByConstI(LModByConstI* instr) { 1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dividend = ToRegister(instr->dividend()); 1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t divisor = instr->divisor(); 1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->result()).is(eax)); 1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (divisor == 0) { 1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(no_condition, instr, "division by zero"); 1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TruncatingDiv(dividend, Abs(divisor)); 1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ imul(edx, edx, Abs(divisor)); 1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, dividend); 1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(eax, edx); 1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for negative zero. 1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HMod* hmod = instr->hydrogen(); 1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label remainder_not_zero; 1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &remainder_not_zero, Label::kNear); 1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(dividend, Immediate(0)); 1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(less, instr, "minus zero"); 1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&remainder_not_zero); 1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoModI(LModI* instr) { 1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HMod* hmod = instr->hydrogen(); 1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register left_reg = ToRegister(instr->left()); 1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(left_reg.is(eax)); 1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register right_reg = ToRegister(instr->right()); 1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!right_reg.is(eax)); 1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!right_reg.is(edx)); 1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result_reg = ToRegister(instr->result()); 1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result_reg.is(edx)); 1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for x % 0, idiv would signal a divide error. We have to 1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // deopt in this case because we can't return a NaN. 1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { 1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(right_reg, Operand(right_reg)); 1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "division by zero"); 1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for kMinInt % -1, idiv would signal a divide error. We 1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // have to deopt if we care about -0, because we can't return that. 1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hmod->CheckFlag(HValue::kCanOverflow)) { 1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_overflow_possible; 1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(left_reg, kMinInt); 1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &no_overflow_possible, Label::kNear); 1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(right_reg, -1); 1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "minus zero"); 1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &no_overflow_possible, Label::kNear); 1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(result_reg, Immediate(0)); 1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_overflow_possible); 1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Sign extend dividend in eax into edx:eax. 1491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cdq(); 1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we care about -0, test if the dividend is <0 and the result is 0. 1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label positive_left; 1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(left_reg, Operand(left_reg)); 1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_sign, &positive_left, Label::kNear); 1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ idiv(right_reg); 1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(result_reg, Operand(result_reg)); 1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "minus zero"); 1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&positive_left); 1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ idiv(right_reg); 1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { 1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dividend = ToRegister(instr->dividend()); 1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t divisor = instr->divisor(); 1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); 1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result.is(dividend)); 1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for (0 / -x) that will produce negative zero. 1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HDiv* hdiv = instr->hydrogen(); 1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(dividend, dividend); 1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "minus zero"); 1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for (kMinInt / -1). 1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { 1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(dividend, kMinInt); 1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "overflow"); 1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Deoptimize if remainder will not be 0. 1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && 1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch divisor != 1 && divisor != -1) { 1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(dividend, Immediate(mask)); 1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_zero, instr, "lost precision"); 1533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(result, dividend); 1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t shift = WhichPowerOf2Abs(divisor); 1536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (shift > 0) { 1537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The arithmetic shift is always OK, the 'if' is an optimization only. 1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (shift > 1) __ sar(result, 31); 1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shr(result, 32 - shift); 1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(result, dividend); 1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sar(result, shift); 1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (divisor < 0) __ neg(result); 1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDivByConstI(LDivByConstI* instr) { 1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dividend = ToRegister(instr->dividend()); 1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t divisor = instr->divisor(); 1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->result()).is(edx)); 1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (divisor == 0) { 1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(no_condition, instr, "division by zero"); 1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for (0 / -x) that will produce negative zero. 1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HDiv* hdiv = instr->hydrogen(); 1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(dividend, dividend); 1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "minus zero"); 1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TruncatingDiv(dividend, Abs(divisor)); 1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (divisor < 0) __ neg(edx); 1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { 1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, edx); 1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ imul(eax, eax, divisor); 1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(eax, dividend); 1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "lost precision"); 1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. 1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDivI(LDivI* instr) { 1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HBinaryOperation* hdiv = instr->hydrogen(); 1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dividend = ToRegister(instr->dividend()); 1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register divisor = ToRegister(instr->divisor()); 1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register remainder = ToRegister(instr->temp()); 1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(dividend.is(eax)); 1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(remainder.is(edx)); 1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->result()).is(eax)); 1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!divisor.is(eax)); 1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!divisor.is(edx)); 1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for x / 0. 1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(divisor, divisor); 1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "division by zero"); 1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for (0 / -x) that will produce negative zero. 1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label dividend_not_zero; 1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(dividend, dividend); 1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, ÷nd_not_zero, Label::kNear); 1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(divisor, divisor); 1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(sign, instr, "minus zero"); 1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(÷nd_not_zero); 1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for (kMinInt / -1). 1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hdiv->CheckFlag(HValue::kCanOverflow)) { 1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label dividend_not_min_int; 1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(dividend, kMinInt); 1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, ÷nd_not_min_int, Label::kNear); 1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(divisor, -1); 1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "overflow"); 1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(÷nd_not_min_int); 1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Sign extend to edx (= remainder). 1615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cdq(); 1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ idiv(divisor); 1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Deoptimize if remainder is not 0. 1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(remainder, remainder); 1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_zero, instr, "lost precision"); 1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { 1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dividend = ToRegister(instr->dividend()); 1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t divisor = instr->divisor(); 1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(dividend.is(ToRegister(instr->result()))); 1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the divisor is positive, things are easy: There can be no deopts and we 1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // can simply do an arithmetic right shift. 1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (divisor == 1) return; 1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t shift = WhichPowerOf2Abs(divisor); 1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (divisor > 1) { 1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sar(dividend, shift); 1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the divisor is negative, we have to negate and handle edge cases. 1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ neg(dividend); 1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "minus zero"); 1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Dividing by -1 is basically negation, unless we overflow. 1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (divisor == -1) { 1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(overflow, instr, "overflow"); 1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the negation could not overflow, simply shifting is OK. 1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sar(dividend, shift); 1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label not_kmin_int, done; 1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(no_overflow, ¬_kmin_int, Label::kNear); 1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(dividend, Immediate(kMinInt / divisor)); 1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_kmin_int); 1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sar(dividend, shift); 1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { 1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dividend = ToRegister(instr->dividend()); 1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t divisor = instr->divisor(); 1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->result()).is(edx)); 1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (divisor == 0) { 1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(no_condition, instr, "division by zero"); 1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for (0 / -x) that will produce negative zero. 1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HMathFloorOfDiv* hdiv = instr->hydrogen(); 1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(dividend, dividend); 1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "minus zero"); 1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Easy case: We need no dynamic check for the dividend and the flooring 1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // division is the same as the truncating division. 1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || 1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { 1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TruncatingDiv(dividend, Abs(divisor)); 1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (divisor < 0) __ neg(edx); 1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In the general case we may need to adjust before and after the truncating 1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // division to get a flooring division. 1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp3()); 1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!temp.is(dividend) && !temp.is(eax) && !temp.is(edx)); 1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label needs_adjustment, done; 1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(dividend, Immediate(0)); 1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(divisor > 0 ? less : greater, &needs_adjustment, Label::kNear); 1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TruncatingDiv(dividend, Abs(divisor)); 1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (divisor < 0) __ neg(edx); 1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&needs_adjustment); 1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(temp, Operand(dividend, divisor > 0 ? 1 : -1)); 1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TruncatingDiv(temp, Abs(divisor)); 1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (divisor < 0) __ neg(edx); 1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ dec(edx); 1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(svenpanne) Refactor this to avoid code duplication with DoDivI. 1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { 1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HBinaryOperation* hdiv = instr->hydrogen(); 1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dividend = ToRegister(instr->dividend()); 1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register divisor = ToRegister(instr->divisor()); 1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register remainder = ToRegister(instr->temp()); 1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(dividend.is(eax)); 1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(remainder.is(edx)); 1724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result.is(eax)); 1725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!divisor.is(eax)); 1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!divisor.is(edx)); 1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for x / 0. 1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(divisor, divisor); 1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "division by zero"); 1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for (0 / -x) that will produce negative zero. 1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label dividend_not_zero; 1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(dividend, dividend); 1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, ÷nd_not_zero, Label::kNear); 1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(divisor, divisor); 1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(sign, instr, "minus zero"); 1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(÷nd_not_zero); 1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for (kMinInt / -1). 1745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hdiv->CheckFlag(HValue::kCanOverflow)) { 1746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label dividend_not_min_int; 1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(dividend, kMinInt); 1748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, ÷nd_not_min_int, Label::kNear); 1749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(divisor, -1); 1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "overflow"); 1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(÷nd_not_min_int); 1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Sign extend to edx (= remainder). 1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cdq(); 1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ idiv(divisor); 1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(remainder, remainder); 1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &done, Label::kNear); 1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xor_(remainder, divisor); 1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sar(remainder, 31); 1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(result, remainder); 1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMulI(LMulI* instr) { 1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register left = ToRegister(instr->left()); 1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* right = instr->right(); 1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ToRegister(instr->temp()), left); 1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (right->IsConstantOperand()) { 1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Try strength reductions on the multiplication. 1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // All replacement instructions are at most as long as the imul 1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and have better latency. 1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int constant = ToInteger32(LConstantOperand::cast(right)); 1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (constant == -1) { 1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ neg(left); 1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (constant == 0) { 1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xor_(left, Operand(left)); 1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (constant == 2) { 1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(left, Operand(left)); 1787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (!instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we know that the multiplication can't overflow, it's safe to 1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // use instructions that don't set the overflow flag for the 1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // multiplication. 1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (constant) { 1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 1: 1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do nothing. 1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 3: 1796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(left, Operand(left, left, times_2, 0)); 1797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 4: 1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shl(left, 2); 1800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 5: 1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(left, Operand(left, left, times_4, 0)); 1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 8: 1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shl(left, 3); 1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 9: 1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(left, Operand(left, left, times_8, 0)); 1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 16: 1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shl(left, 4); 1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ imul(left, left, constant); 1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ imul(left, left, constant); 1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->representation().IsSmi()) { 1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(left); 1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ imul(left, ToOperand(right)); 1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(overflow, instr, "overflow"); 1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bail out if the result is supposed to be negative zero. 1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(left, Operand(left)); 1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &done); 1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (right->IsConstantOperand()) { 1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ToInteger32(LConstantOperand::cast(right)) < 0) { 1838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(no_condition, instr, "minus zero"); 1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { 1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ToRegister(instr->temp()), Immediate(0)); 1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(less, instr, "minus zero"); 1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Test the non-zero operand for negative sign. 1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ or_(ToRegister(instr->temp()), ToOperand(right)); 1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(sign, instr, "minus zero"); 1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoBitI(LBitI* instr) { 1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* left = instr->left(); 1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* right = instr->right(); 1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(left->Equals(instr->result())); 1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(left->IsRegister()); 1858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (right->IsConstantOperand()) { 1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t right_operand = 1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToRepresentation(LConstantOperand::cast(right), 1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->representation()); 1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (instr->op()) { 1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::BIT_AND: 1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(ToRegister(left), right_operand); 1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::BIT_OR: 1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ or_(ToRegister(left), right_operand); 1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::BIT_XOR: 1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (right_operand == int32_t(~0)) { 1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ not_(ToRegister(left)); 1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xor_(ToRegister(left), right_operand); 1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (instr->op()) { 1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::BIT_AND: 1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(ToRegister(left), ToOperand(right)); 1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::BIT_OR: 1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ or_(ToRegister(left), ToOperand(right)); 1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::BIT_XOR: 1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xor_(ToRegister(left), ToOperand(right)); 1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoShiftI(LShiftI* instr) { 1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* left = instr->left(); 1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* right = instr->right(); 1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(left->Equals(instr->result())); 1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(left->IsRegister()); 1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (right->IsRegister()) { 1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(right).is(ecx)); 1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (instr->op()) { 1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::ROR: 1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ror_cl(ToRegister(left)); 1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SAR: 1913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sar_cl(ToRegister(left)); 1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SHR: 1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shr_cl(ToRegister(left)); 1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->can_deopt()) { 1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(ToRegister(left), ToRegister(left)); 1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(sign, instr, "negative value"); 1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SHL: 1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shl_cl(ToRegister(left)); 1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int value = ToInteger32(LConstantOperand::cast(right)); 1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); 1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (instr->op()) { 1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::ROR: 1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (shift_count == 0 && instr->can_deopt()) { 1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(ToRegister(left), ToRegister(left)); 1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(sign, instr, "negative value"); 1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ror(ToRegister(left), shift_count); 1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SAR: 1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (shift_count != 0) { 1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sar(ToRegister(left), shift_count); 1944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SHR: 1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (shift_count != 0) { 1948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shr(ToRegister(left), shift_count); 1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (instr->can_deopt()) { 1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(ToRegister(left), ToRegister(left)); 1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(sign, instr, "negative value"); 1952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SHL: 1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (shift_count != 0) { 1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen_value()->representation().IsSmi() && 1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->can_deopt()) { 1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (shift_count != 1) { 1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shl(ToRegister(left), shift_count - 1); 1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(ToRegister(left)); 1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(overflow, instr, "overflow"); 1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shl(ToRegister(left), shift_count); 1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoSubI(LSubI* instr) { 1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* left = instr->left(); 1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* right = instr->right(); 1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(left->Equals(instr->result())); 1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (right->IsConstantOperand()) { 1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(ToOperand(left), 1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToImmediate(right, instr->hydrogen()->representation())); 1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(ToRegister(left), ToOperand(right)); 1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(overflow, instr, "overflow"); 1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoConstantI(LConstantI* instr) { 1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(ToRegister(instr->result()), Immediate(instr->value())); 1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoConstantS(LConstantS* instr) { 1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(ToRegister(instr->result()), Immediate(instr->value())); 2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoConstantD(LConstantD* instr) { 2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double v = instr->value(); 2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t int_val = bit_cast<uint64_t, double>(v); 2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t lower = static_cast<int32_t>(int_val); 2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); 2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->result()->IsDoubleRegister()); 2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(upper)); 2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(lower)); 2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register reg = ToX87Register(instr->result()); 2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Mov(reg, Operand(esp, 0)); 2014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(Operand(esp), Immediate(kDoubleSize)); 2015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoConstantE(LConstantE* instr) { 2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value())); 2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoConstantT(LConstantT* instr) { 2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(instr->result()); 2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> object = instr->value(isolate()); 2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllowDeferredHandleDereference smi_check; 2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadObject(reg, object); 2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { 2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map = ToRegister(instr->value()); 2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EnumLength(result, map); 2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDateField(LDateField* instr) { 2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object = ToRegister(instr->date()); 2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = ToRegister(instr->temp()); 2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi* index = instr->index(); 2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label runtime, done; 2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(object.is(result)); 2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(object.is(eax)); 2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(object, Immediate(kSmiTagMask)); 2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "Smi"); 2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(object, JS_DATE_TYPE, scratch); 2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "not a date object"); 2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (index->value() == 0) { 2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, FieldOperand(object, JSDate::kValueOffset)); 2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (index->value() < JSDate::kFirstUncachedField) { 2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch, Operand::StaticVariable(stamp)); 2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); 2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &runtime, Label::kNear); 2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, FieldOperand(object, JSDate::kValueOffset + 2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointerSize * index->value())); 2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&runtime); 2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PrepareCallCFunction(2, scratch); 2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 0), object); 2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 1 * kPointerSize), Immediate(index)); 2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOperand LCodeGen::BuildSeqStringOperand(Register string, 2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* index, 2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String::Encoding encoding) { 2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (index->IsConstantOperand()) { 2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = ToRepresentation(LConstantOperand::cast(index), 2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation::Integer32()); 2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (encoding == String::TWO_BYTE_ENCODING) { 2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset *= kUC16Size; 2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kCharSize == 1); 2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return FieldOperand(string, SeqString::kHeaderSize + offset); 2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return FieldOperand( 2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch string, ToRegister(index), 2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch encoding == String::ONE_BYTE_ENCODING ? times_1 : times_2, 2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SeqString::kHeaderSize); 2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) { 2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String::Encoding encoding = instr->hydrogen()->encoding(); 2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register string = ToRegister(instr->string()); 2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(string); 2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(string, FieldOperand(string, HeapObject::kMapOffset)); 2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset)); 2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(string, Immediate(kStringRepresentationMask | kStringEncodingMask)); 2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; 2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(string, Immediate(encoding == String::ONE_BYTE_ENCODING 2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? one_byte_seq_type : two_byte_seq_type)); 2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(equal, kUnexpectedStringType); 2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(string); 2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); 2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (encoding == String::ONE_BYTE_ENCODING) { 2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzx_b(result, operand); 2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzx_w(result, operand); 2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { 2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String::Encoding encoding = instr->hydrogen()->encoding(); 2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register string = ToRegister(instr->string()); 2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = ToRegister(instr->value()); 2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index = ToRegister(instr->index()); 2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; 2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int encoding_mask = 2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING 2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? one_byte_seq_type : two_byte_seq_type; 2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask); 2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); 2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->value()->IsConstantOperand()) { 2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int value = ToRepresentation(LConstantOperand::cast(instr->value()), 2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation::Integer32()); 2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_LE(0, value); 2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (encoding == String::ONE_BYTE_ENCODING) { 2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_LE(value, String::kMaxOneByteCharCode); 2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov_b(operand, static_cast<int8_t>(value)); 2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_LE(value, String::kMaxUtf16CodeUnit); 2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov_w(operand, static_cast<int16_t>(value)); 2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = ToRegister(instr->value()); 2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (encoding == String::ONE_BYTE_ENCODING) { 2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov_b(operand, value); 2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov_w(operand, value); 2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoAddI(LAddI* instr) { 2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* left = instr->left(); 2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* right = instr->right(); 2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { 2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (right->IsConstantOperand()) { 2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t offset = ToRepresentation(LConstantOperand::cast(right), 2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->representation()); 2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(ToRegister(instr->result()), MemOperand(ToRegister(left), offset)); 2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand address(ToRegister(left), ToRegister(right), times_1, 0); 2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(ToRegister(instr->result()), address); 2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (right->IsConstantOperand()) { 2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(ToOperand(left), 2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToImmediate(right, instr->hydrogen()->representation())); 2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(ToRegister(left), ToOperand(right)); 2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(overflow, instr, "overflow"); 2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathMinMax(LMathMinMax* instr) { 2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* left = instr->left(); 2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* right = instr->right(); 2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(left->Equals(instr->result())); 2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HMathMinMax::Operation operation = instr->hydrogen()->operation(); 2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->representation().IsSmiOrInteger32()) { 2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label return_left; 2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition condition = (operation == HMathMinMax::kMathMin) 2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? less_equal 2195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : greater_equal; 2196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (right->IsConstantOperand()) { 2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand left_op = ToOperand(left); 2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate immediate = ToImmediate(LConstantOperand::cast(instr->right()), 2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->representation()); 2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(left_op, immediate); 2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(condition, &return_left, Label::kNear); 2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(left_op, immediate); 2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register left_reg = ToRegister(left); 2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand right_op = ToOperand(right); 2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(left_reg, right_op); 2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(condition, &return_left, Label::kNear); 2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(left_reg, right_op); 2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&return_left); 2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->hydrogen()->representation().IsDouble()); 2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label check_nan_left, check_zero, return_left, return_right; 2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition condition = (operation == HMathMinMax::kMathMin) ? below : above; 2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register left_reg = ToX87Register(left); 2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register right_reg = ToX87Register(right); 2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87PrepareBinaryOp(left_reg, right_reg, ToX87Register(instr->result())); 2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(1); 2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(1); 2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN. 2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &check_zero, Label::kNear); // left == right. 2224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(condition, &return_left, Label::kNear); 2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&return_right, Label::kNear); 2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_zero); 2228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(0); 2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fldz(); 2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 2231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &return_left, Label::kNear); // left == right != 0. 2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // At this point, both left and right are either 0 or -0. 2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (operation == HMathMinMax::kMathMin) { 2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push st0 and st1 to stack, then pop them to temp registers and OR them, 2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // load it to left. 2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch_reg = ToRegister(instr->temp()); 2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(1); 2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(1); 2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(esp, Immediate(2 * kPointerSize)); 2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp_s(MemOperand(esp, 0)); 2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp_s(MemOperand(esp, kPointerSize)); 2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(scratch_reg); 2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xor_(MemOperand(esp, 0), scratch_reg); 2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Mov(left_reg, MemOperand(esp, 0), kX87FloatOperand); 2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(scratch_reg); // restore esp 2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Since we operate on +0 and/or -0, addsd and andsd have the same effect. 2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fxch(left_reg); 2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fadd(1); 2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&return_left, Label::kNear); 2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_nan_left); 2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(0); 2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(0); 2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); // NaN check. 2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(parity_even, &return_left, Label::kNear); // left == NaN. 2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&return_right); 2260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fxch(left_reg); 2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Mov(left_reg, right_reg); 2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&return_left); 2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoArithmeticD(LArithmeticD* instr) { 2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register left = ToX87Register(instr->left()); 2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register right = ToX87Register(instr->right()); 2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register result = ToX87Register(instr->result()); 2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->op() != Token::MOD) { 2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87PrepareBinaryOp(left, right, result); 2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set the precision control to double-precision. 2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ X87SetFPUCW(0x027F); 2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (instr->op()) { 2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::ADD: 2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fadd_i(1); 2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::SUB: 2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fsub_i(1); 2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::MUL: 2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fmul_i(1); 2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::DIV: 2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fdiv_i(1); 2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::MOD: { 2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pass two doubles as arguments on the stack. 2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PrepareCallCFunction(4, eax); 2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Mov(Operand(esp, 1 * kDoubleSize), right); 2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Mov(Operand(esp, 0), left); 2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Free(right); 2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(left.is(result)); 2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87PrepareToWrite(result); 2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallCFunction( 2299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::mod_two_doubles_operation(isolate()), 2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4); 2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return value is in st(0) on ia32. 2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87CommitWrite(result); 2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore the default value of control word. 2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ X87SetFPUCW(0x037F); 2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoArithmeticT(LArithmeticT* instr) { 2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->left()).is(edx)); 2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->right()).is(eax)); 2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->result()).is(eax)); 2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> code = 2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeFactory::BinaryOpIC(isolate(), instr->op(), NO_OVERWRITE).code(); 2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(code, RelocInfo::CODE_TARGET, instr); 2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class InstrType> 2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitBranch(InstrType instr, Condition cc) { 2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int left_block = instr->TrueDestination(chunk_); 2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int right_block = instr->FalseDestination(chunk_); 2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int next_block = GetNextEmittedBlock(); 2334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (right_block == left_block || cc == no_condition) { 2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitGoto(left_block); 2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (left_block == next_block) { 2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); 2339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (right_block == next_block) { 2340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(cc, chunk_->GetAssemblyLabel(left_block)); 2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(cc, chunk_->GetAssemblyLabel(left_block)); 2343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(chunk_->GetAssemblyLabel(right_block)); 2344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class InstrType> 2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) { 2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int false_block = instr->FalseDestination(chunk_); 2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cc == no_condition) { 2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(chunk_->GetAssemblyLabel(false_block)); 2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(cc, chunk_->GetAssemblyLabel(false_block)); 2355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoBranch(LBranch* instr) { 2360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation r = instr->hydrogen()->value()->representation(); 2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (r.IsSmiOrInteger32()) { 2362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(instr->value()); 2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(reg, Operand(reg)); 2364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, not_zero); 2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (r.IsDouble()) { 2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register reg = ToX87Register(instr->value()); 2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87LoadForUsage(reg); 2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fldz(); 2369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, not_zero); 2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(r.IsTagged()); 2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(instr->value()); 2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HType type = instr->hydrogen()->value()->type(); 2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (type.IsBoolean()) { 2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!info()->IsStub()); 2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(reg, factory()->true_value()); 2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, equal); 2379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (type.IsSmi()) { 2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!info()->IsStub()); 2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(reg, Operand(reg)); 2382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, not_equal); 2383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (type.IsJSArray()) { 2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!info()->IsStub()); 2385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, no_condition); 2386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (type.IsHeapNumber()) { 2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (type.IsString()) { 2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!info()->IsStub()); 2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); 2391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, not_equal); 2392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); 2394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); 2395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expected.Contains(ToBooleanStub::UNDEFINED)) { 2397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // undefined -> false. 2398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(reg, factory()->undefined_value()); 2399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, instr->FalseLabel(chunk_)); 2400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expected.Contains(ToBooleanStub::BOOLEAN)) { 2402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // true -> true. 2403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(reg, factory()->true_value()); 2404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, instr->TrueLabel(chunk_)); 2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // false -> false. 2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(reg, factory()->false_value()); 2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, instr->FalseLabel(chunk_)); 2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expected.Contains(ToBooleanStub::NULL_TYPE)) { 2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 'null' -> false. 2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(reg, factory()->null_value()); 2412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, instr->FalseLabel(chunk_)); 2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expected.Contains(ToBooleanStub::SMI)) { 2416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Smis: 0 -> false, all other -> true. 2417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(reg, Operand(reg)); 2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, instr->FalseLabel(chunk_)); 2419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); 2420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (expected.NeedsMap()) { 2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we need a map later and have a Smi -> deopt. 2422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(reg, Immediate(kSmiTagMask)); 2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "Smi"); 2424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map = no_reg; // Keep the compiler happy. 2427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expected.NeedsMap()) { 2428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch map = ToRegister(instr->temp()); 2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!map.is(reg)); 2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); 2431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expected.CanBeUndetectable()) { 2433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Undetectable -> false. 2434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test_b(FieldOperand(map, Map::kBitFieldOffset), 2435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1 << Map::kIsUndetectable); 2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, instr->FalseLabel(chunk_)); 2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { 2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // spec object -> true. 2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); 2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above_equal, instr->TrueLabel(chunk_)); 2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expected.Contains(ToBooleanStub::STRING)) { 2447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // String value -> false iff empty. 2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label not_string; 2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); 2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above_equal, ¬_string, Label::kNear); 2451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); 2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, instr->TrueLabel(chunk_)); 2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(instr->FalseLabel(chunk_)); 2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_string); 2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expected.Contains(ToBooleanStub::SYMBOL)) { 2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Symbol value -> true. 2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpInstanceType(map, SYMBOL_TYPE); 2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, instr->TrueLabel(chunk_)); 2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { 2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // heap number -> false iff +0, -0, or NaN. 2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label not_heap_number; 2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch factory()->heap_number_map()); 2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, ¬_heap_number, Label::kNear); 2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fldz(); 2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); 2471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 2472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, instr->FalseLabel(chunk_)); 2473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(instr->TrueLabel(chunk_)); 2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_heap_number); 2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!expected.IsGeneric()) { 2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We've seen something for the first time -> deopt. 2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This can only happen if we are not generic already. 2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(no_condition, instr, "unexpected object"); 2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitGoto(int block) { 2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!IsNextEmittedBlock(block)) { 2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); 2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoClobberDoubles(LClobberDoubles* instr) { 2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoGoto(LGoto* instr) { 2499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitGoto(instr->block_id()); 2500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { 2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = no_condition; 2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (op) { 2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::EQ: 2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::EQ_STRICT: 2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cond = equal; 2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::NE: 2511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::NE_STRICT: 2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cond = not_equal; 2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::LT: 2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cond = is_unsigned ? below : less; 2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::GT: 2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cond = is_unsigned ? above : greater; 2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::LTE: 2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cond = is_unsigned ? below_equal : less_equal; 2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::GTE: 2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cond = is_unsigned ? above_equal : greater_equal; 2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::IN: 2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::INSTANCEOF: 2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 2530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return cond; 2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) { 2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* left = instr->left(); 2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* right = instr->right(); 2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_unsigned = 2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->is_double() || 2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->left()->CheckFlag(HInstruction::kUint32) || 2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->right()->CheckFlag(HInstruction::kUint32); 2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cc = TokenToCondition(instr->op(), is_unsigned); 2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (left->IsConstantOperand() && right->IsConstantOperand()) { 2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We can statically evaluate the comparison. 2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double left_val = ToDouble(LConstantOperand::cast(left)); 2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double right_val = ToDouble(LConstantOperand::cast(right)); 2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int next_block = EvalComparison(instr->op(), left_val, right_val) ? 2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); 2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitGoto(next_block); 2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->is_double()) { 2553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87LoadForUsage(ToX87Register(right), ToX87Register(left)); 2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Don't base result on EFLAGS when a NaN is involved. Instead 2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // jump to the false block. 2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(parity_even, instr->FalseLabel(chunk_)); 2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (right->IsConstantOperand()) { 2560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ToOperand(left), 2561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToImmediate(right, instr->hydrogen()->representation())); 2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (left->IsConstantOperand()) { 2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ToOperand(right), 2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToImmediate(left, instr->hydrogen()->representation())); 2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We commuted the operands, so commute the condition. 2566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cc = CommuteCondition(cc); 2567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ToRegister(left), ToOperand(right)); 2569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, cc); 2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { 2577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register left = ToRegister(instr->left()); 2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->right()->IsConstantOperand()) { 2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); 2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObject(left, right); 2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand right = ToOperand(instr->right()); 2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(left, right); 2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, equal); 2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { 2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->representation().IsTagged()) { 2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_reg = ToRegister(instr->object()); 2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(input_reg, factory()->the_hole_value()); 2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, equal); 2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put the value to the top of stack 2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register src = ToX87Register(instr->object()); 2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87LoadForUsage(src); 2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(0); 2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(0); 2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(parity_even, &ok, Label::kNear); 2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp(0); 2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitFalseBranch(instr, no_condition); 2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok); 2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(esp, Immediate(kDoubleSize)); 2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp_d(MemOperand(esp, 0)); 2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(esp, Immediate(kDoubleSize)); 2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = sizeof(kHoleNanUpper32); 2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32)); 2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, equal); 2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { 2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation rep = instr->hydrogen()->value()->representation(); 2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!rep.IsInteger32()); 2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (rep.IsDouble()) { 2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register input = ToX87Register(instr->value()); 2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87LoadForUsage(input); 2628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FXamMinusZero(); 2629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, equal); 2630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = ToRegister(instr->value()); 2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); 2633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK); 2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(value, HeapNumber::kExponentOffset), 2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(0x1)); 2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitFalseBranch(instr, no_overflow); 2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(value, HeapNumber::kMantissaOffset), 2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(0x00000000)); 2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, equal); 2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition LCodeGen::EmitIsObject(Register input, 2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp1, 2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* is_not_object, 2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* is_object) { 2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(input, is_not_object); 2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(input, isolate()->factory()->null_value()); 2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, is_object); 2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset)); 2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Undetectable objects behave like undefined. 2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test_b(FieldOperand(temp1, Map::kBitFieldOffset), 2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1 << Map::kIsUndetectable); 2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, is_not_object); 2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzx_b(temp1, FieldOperand(temp1, Map::kInstanceTypeOffset)); 2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(temp1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); 2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below, is_not_object); 2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return below_equal; 2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { 2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(instr->value()); 2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp()); 2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition true_cond = EmitIsObject( 2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg, temp, instr->FalseLabel(chunk_), instr->TrueLabel(chunk_)); 2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, true_cond); 2675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition LCodeGen::EmitIsString(Register input, 2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp1, 2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* is_not_string, 2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck check_needed = INLINE_SMI_CHECK) { 2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (check_needed == INLINE_SMI_CHECK) { 2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(input, is_not_string); 2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond = masm_->IsObjectStringType(input, temp1, temp1); 2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return cond; 2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { 2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(instr->value()); 2694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp()); 2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck check_needed = 2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->value()->type().IsHeapObject() 2698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition true_cond = EmitIsString( 2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg, temp, instr->FalseLabel(chunk_), check_needed); 2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, true_cond); 2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 2708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand input = ToOperand(instr->value()); 2709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(input, Immediate(kSmiTagMask)); 2711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, zero); 2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { 2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input = ToRegister(instr->value()); 2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp()); 2718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!instr->hydrogen()->value()->type().IsHeapObject()) { 2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(input, instr->FalseLabel(chunk_)); 2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 2724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test_b(FieldOperand(temp, Map::kBitFieldOffset), 2725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1 << Map::kIsUndetectable); 2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, not_zero); 2727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Condition ComputeCompareCondition(Token::Value op) { 2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (op) { 2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::EQ_STRICT: 2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::EQ: 2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return equal; 2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::LT: 2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return less; 2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::GT: 2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return greater; 2739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::LTE: 2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return less_equal; 2741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::GTE: 2742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return greater_equal; 2743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 2745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return no_condition; 2746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { 2751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Token::Value op = instr->op(); 2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); 2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition condition = ComputeCompareCondition(op); 2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(eax, Operand(eax)); 2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, condition); 2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic InstanceType TestType(HHasInstanceTypeAndBranch* instr) { 2764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstanceType from = instr->from(); 2765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstanceType to = instr->to(); 2766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (from == FIRST_TYPE) return to; 2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(from == to || to == LAST_TYPE); 2768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return from; 2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { 2773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstanceType from = instr->from(); 2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstanceType to = instr->to(); 2775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (from == to) return equal; 2776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (to == LAST_TYPE) return above_equal; 2777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (from == FIRST_TYPE) return below_equal; 2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return equal; 2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 2784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input = ToRegister(instr->value()); 2785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp()); 2786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!instr->hydrogen()->value()->type().IsHeapObject()) { 2788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(input, instr->FalseLabel(chunk_)); 2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(input, TestType(instr->hydrogen()), temp); 2792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, BranchCondition(instr->hydrogen())); 2793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { 2797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input = ToRegister(instr->value()); 2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 2799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertString(input); 2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, FieldOperand(input, String::kHashFieldOffset)); 2803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IndexFromHash(result, result); 2804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoHasCachedArrayIndexAndBranch( 2808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LHasCachedArrayIndexAndBranch* instr) { 2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input = ToRegister(instr->value()); 2810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(FieldOperand(input, String::kHashFieldOffset), 2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(String::kContainsCachedArrayIndexMask)); 2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, equal); 2814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Branches to a label or falls through with the answer in the z flag. Trashes 2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the temp registers, but not the input. 2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitClassOfTest(Label* is_true, 2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* is_false, 2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String>class_name, 2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input, 2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp, 2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp2) { 2825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!input.is(temp)); 2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!input.is(temp2)); 2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!temp.is(temp2)); 2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(input, is_false); 2829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (String::Equals(isolate()->factory()->Function_string(), class_name)) { 2831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assuming the following assertions, we can use the same compares to test 2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // for both being a function type and being in the object type range. 2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 2834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == 2835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FIRST_SPEC_OBJECT_TYPE + 1); 2836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == 2837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LAST_SPEC_OBJECT_TYPE - 1); 2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp); 2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below, is_false); 2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, is_true); 2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE); 2843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, is_true); 2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Faster code path to avoid two compares: subtract lower bound from the 2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // actual type and do a signed compare with the width of the type range. 2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 2848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzx_b(temp2, FieldOperand(temp, Map::kInstanceTypeOffset)); 2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(Operand(temp2), Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(Operand(temp2), Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - 2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above, is_false); 2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. 2856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if the constructor in the map is a function. 2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp, FieldOperand(temp, Map::kConstructorOffset)); 2858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Objects with a non-function constructor have class 'Object'. 2859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(temp, JS_FUNCTION_TYPE, temp2); 2860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (String::Equals(class_name, isolate()->factory()->Object_string())) { 2861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, is_true); 2862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, is_false); 2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // temp now contains the constructor function. Grab the 2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instance class name from there. 2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset)); 2869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp, FieldOperand(temp, 2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kInstanceClassNameOffset)); 2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The class name we are testing against is internalized since it's a literal. 2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The name in the constructor is internalized because of the way the context 2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is booted. This routine isn't expected to work for random API-created 2874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // classes and it doesn't have to because you can't access it with natives 2875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // syntax. Since both sides are internalized it is sufficient to use an 2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // identity comparison. 2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(temp, class_name); 2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // End with the answer in the z flag. 2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input = ToRegister(instr->value()); 2884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp()); 2885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp2 = ToRegister(instr->temp2()); 2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> class_name = instr->hydrogen()->class_name(); 2888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), 2890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class_name, input, temp, temp2); 2891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, equal); 2893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { 2897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(instr->value()); 2898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); 2899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, equal); 2900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoInstanceOf(LInstanceOf* instr) { 2904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Object and function are in fixed registers defined by the stub. 2905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 2906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters); 2907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 2908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label true_value, done; 2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(eax, Operand(eax)); 2911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &true_value, Label::kNear); 2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ToRegister(instr->result()), factory()->false_value()); 2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&true_value); 2915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ToRegister(instr->result()), factory()->true_value()); 2916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class DeferredInstanceOfKnownGlobal FINAL : public LDeferredCode { 2922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 2923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredInstanceOfKnownGlobal(LCodeGen* codegen, 2924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstanceOfKnownGlobal* instr, 2925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const X87Stack& x87_stack) 2926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : LDeferredCode(codegen, x87_stack), instr_(instr) { } 2927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Generate() OVERRIDE { 2928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); 2929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual LInstruction* instr() OVERRIDE { return instr_; } 2931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* map_check() { return &map_check_; } 2932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 2933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstanceOfKnownGlobal* instr_; 2934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label map_check_; 2935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 2936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredInstanceOfKnownGlobal* deferred; 2938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr, x87_stack_); 2939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, false_result; 2941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object = ToRegister(instr->value()); 2942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp()); 2943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // A Smi is not an instance of anything. 2945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(object, &false_result, Label::kNear); 2946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is the inlined call site instanceof cache. The two occurences of the 2948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // hole value will be patched to the last map/result pair generated by the 2949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instanceof stub. 2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label cache_miss; 2951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map = ToRegister(instr->temp()); 2952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); 2953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(deferred->map_check()); // Label for calculating code patching. 2954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value()); 2955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(map, Operand::ForCell(cache_cell)); // Patched to cached map. 2956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &cache_miss, Label::kNear); 2957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. 2958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 2959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The inlined call site cache did not match. Check for null and string 2961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // before calling the deferred code. 2962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&cache_miss); 2963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Null is not an instance of anything. 2964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(object, factory()->null_value()); 2965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &false_result, Label::kNear); 2966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // String values are not instances of anything. 2968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition is_string = masm_->IsObjectStringType(object, temp, temp); 2969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(is_string, &false_result, Label::kNear); 2970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Go to the deferred code. 2972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(deferred->entry()); 2973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&false_result); 2975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ToRegister(instr->result()), factory()->false_value()); 2976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Here result has either true or false. Deferred code also produces true or 2978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // false object. 2979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(deferred->exit()); 2980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 2981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, 2985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* map_check) { 2986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 2987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstanceofStub::Flags flags = InstanceofStub::kNoFlags; 2989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags = static_cast<InstanceofStub::Flags>( 2990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags | InstanceofStub::kArgsInRegisters); 2991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags = static_cast<InstanceofStub::Flags>( 2992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags | InstanceofStub::kCallSiteInlineCheck); 2993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags = static_cast<InstanceofStub::Flags>( 2994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags | InstanceofStub::kReturnTrueFalseObject); 2995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstanceofStub stub(isolate(), flags); 2996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the temp register reserved by the instruction. This needs to be a 2998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // register which is pushed last by PushSafepointRegisters as top of the 2999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stack is used to pass the offset to the location of the map check to 3000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the stub. 3001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp()); 3002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(MacroAssembler::SafepointRegisterStackIndex(temp) == 0); 3003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadHeapObject(InstanceofStub::right(), instr->function()); 3004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kAdditionalDelta = 13; 3005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; 3006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp, Immediate(delta)); 3007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreToSafepointRegisterSlot(temp, temp); 3008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCodeGeneric(stub.GetCode(), 3009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::CODE_TARGET, 3010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr, 3011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); 3012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the deoptimization index of the LLazyBailout-environment that 3013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // corresponds to this instruction. 3014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); 3015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 3016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put the result value into the eax slot and restore all registers. 3018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreToSafepointRegisterSlot(eax, eax); 3019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCmpT(LCmpT* instr) { 3023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Token::Value op = instr->op(); 3024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); 3026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 3027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition condition = ComputeCompareCondition(op); 3029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label true_value, done; 3030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(eax, Operand(eax)); 3031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(condition, &true_value, Label::kNear); 3032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ToRegister(instr->result()), factory()->false_value()); 3033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 3034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&true_value); 3035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ToRegister(instr->result()), factory()->true_value()); 3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 3037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitReturn(LReturn* instr, bool dynamic_frame_alignment) { 3041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int extra_value_count = dynamic_frame_alignment ? 2 : 1; 3042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->has_constant_parameter_count()) { 3044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parameter_count = ToInteger32(instr->constant_parameter_count()); 3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (dynamic_frame_alignment && FLAG_debug_code) { 3046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(Operand(esp, 3047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (parameter_count + extra_value_count) * kPointerSize), 3048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(kAlignmentZapValue)); 3049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(equal, kExpectedAlignmentMarker); 3050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret((parameter_count + extra_value_count) * kPointerSize, ecx); 3052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(instr->parameter_count()); 3054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The argument count parameter is a smi 3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(reg); 3056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register return_addr_reg = reg.is(ecx) ? ebx : ecx; 3057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (dynamic_frame_alignment && FLAG_debug_code) { 3058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(extra_value_count == 2); 3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(Operand(esp, reg, times_pointer_size, 3060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extra_value_count * kPointerSize), 3061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(kAlignmentZapValue)); 3062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(equal, kExpectedAlignmentMarker); 3063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // emit code to restore stack based on instr->parameter_count() 3066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(return_addr_reg); // save return address 3067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (dynamic_frame_alignment) { 3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ inc(reg); // 1 more for alignment 3069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shl(reg, kPointerSizeLog2); 3071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(esp, reg); 3072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(return_addr_reg); 3073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoReturn(LReturn* instr) { 3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_trace && info()->IsOptimizing()) { 3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the return value on the stack and rely on the runtime call 3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to return the value in the same register. We're leaving the code 3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // managed by the register allocator and tearing down the frame, it's 3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // safe to write to the context register. 3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(eax); 3084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kTraceExit, 1); 3086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (dynamic_frame_alignment_) { 3088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fetch the state of the dynamic frame alignment. 3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(edx, Operand(ebp, 3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JavaScriptFrameConstants::kDynamicAlignmentStateOffset)); 3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int no_frame_start = -1; 3093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (NeedsEagerFrame()) { 3094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esp, ebp); 3095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(ebp); 3096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch no_frame_start = masm_->pc_offset(); 3097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (dynamic_frame_alignment_) { 3099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_padding; 3100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(edx, Immediate(kNoAlignmentPadding)); 3101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &no_padding, Label::kNear); 3102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitReturn(instr, true); 3104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_padding); 3105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitReturn(instr, false); 3108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (no_frame_start != -1) { 3109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info()->AddNoFrameRange(no_frame_start, masm_->pc_offset()); 3110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { 3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle())); 3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(result, factory()->the_hole_value()); 3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "hole"); 3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <class T> 3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitVectorLoadICRegisters(T* instr) { 3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(FLAG_vector_ics); 3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register vector = ToRegister(instr->temp_vector()); 3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); 3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(vector, instr->hydrogen()->feedback_vector()); 3130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // No need to allocate this register. 3131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(VectorLoadICDescriptor::SlotRegister().is(eax)); 3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(VectorLoadICDescriptor::SlotRegister(), 3133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(Smi::FromInt(instr->hydrogen()->slot()))); 3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { 3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->global_object()) 3140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch .is(LoadDescriptor::ReceiverRegister())); 3141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->result()).is(eax)); 3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(LoadDescriptor::NameRegister(), instr->name()); 3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr); 3146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; 3148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::LoadIC(isolate(), mode).code(); 3149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 3150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { 3154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = ToRegister(instr->value()); 3155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle(); 3156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the cell we are storing to contains the hole it could have 3158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // been deleted from the property dictionary. In that case, we need 3159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to update the property details in the property dictionary to mark 3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // it as no longer deleted. We deoptimize in that case. 3161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value()); 3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "hole"); 3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store the value. 3167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand::ForCell(cell_handle), value); 3168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Cells are always rescanned, so no write barrier here. 3169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 3173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register context = ToRegister(instr->context()); 3174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 3175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, ContextOperand(context, instr->slot_index())); 3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 3178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(result, factory()->the_hole_value()); 3179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->DeoptimizesOnHole()) { 3180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "hole"); 3181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label is_not_hole; 3183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &is_not_hole, Label::kNear); 3184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, factory()->undefined_value()); 3185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&is_not_hole); 3186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 3192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register context = ToRegister(instr->context()); 3193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = ToRegister(instr->value()); 3194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label skip_assignment; 3196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand target = ContextOperand(context, instr->slot_index()); 3198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 3199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(target, factory()->the_hole_value()); 3200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->DeoptimizesOnHole()) { 3201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "hole"); 3202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &skip_assignment, Label::kNear); 3204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(target, value); 3208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->NeedsWriteBarrier()) { 3209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck check_needed = 3210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->value()->type().IsHeapObject() 3211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 3212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp()); 3213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = Context::SlotOffset(instr->slot_index()); 3214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot(context, offset, value, temp, kSaveFPRegs, 3215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, check_needed); 3216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&skip_assignment); 3219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 3223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HObjectAccess access = instr->hydrogen()->access(); 3224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = access.offset(); 3225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (access.IsExternalMemory()) { 3227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 3228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand operand = instr->object()->IsConstantOperand() 3229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? MemOperand::StaticVariable(ToExternalReference( 3230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LConstantOperand::cast(instr->object()))) 3231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : MemOperand(ToRegister(instr->object()), offset); 3232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Load(result, operand, access.representation()); 3233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 3234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object = ToRegister(instr->object()); 3237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->representation().IsDouble()) { 3238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset)); 3239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 3240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 3243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!access.IsInobject()) { 3244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); 3245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch object = result; 3246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Load(result, FieldOperand(object, offset), access.representation()); 3248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitPushTaggedOperand(LOperand* operand) { 3252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!operand->IsDoubleRegister()); 3253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (operand->IsConstantOperand()) { 3254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> object = ToHandle(LConstantOperand::cast(operand)); 3255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllowDeferredHandleDereference smi_check; 3256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (object->IsSmi()) { 3257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Handle<Smi>::cast(object)); 3258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushHeapObject(Handle<HeapObject>::cast(object)); 3260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (operand->IsRegister()) { 3262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ToRegister(operand)); 3263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ToOperand(operand)); 3265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { 3270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 3271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister())); 3272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->result()).is(eax)); 3273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(LoadDescriptor::NameRegister(), instr->name()); 3275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 3276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr); 3277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code(); 3279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 3280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { 3284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register function = ToRegister(instr->function()); 3285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp()); 3286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 3287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the prototype or initial map from the function. 3289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, 3290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 3291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the function has a prototype or an initial map. 3293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(Operand(result), Immediate(factory()->the_hole_value())); 3294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "hole"); 3295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the function does not have an initial map, we're done. 3297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 3298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(result, MAP_TYPE, temp); 3299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &done, Label::kNear); 3300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the prototype from the initial map. 3302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); 3303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // All done. 3305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 3306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadRoot(LLoadRoot* instr) { 3310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 3311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result, instr->index()); 3312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { 3316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register arguments = ToRegister(instr->arguments()); 3317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 3318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->length()->IsConstantOperand() && 3319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->index()->IsConstantOperand()) { 3320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int const_index = ToInteger32(LConstantOperand::cast(instr->index())); 3321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int const_length = ToInteger32(LConstantOperand::cast(instr->length())); 3322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = (const_length - const_index) + 1; 3323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Operand(arguments, index * kPointerSize)); 3324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register length = ToRegister(instr->length()); 3326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand index = ToOperand(instr->index()); 3327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // There are two words between the frame pointer and the last argument. 3328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Subtracting from length accounts for one of them add one more. 3329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(length, index); 3330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Operand(arguments, length, times_4, kPointerSize)); 3331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { 3336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind elements_kind = instr->elements_kind(); 3337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* key = instr->key(); 3338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!key->IsConstantOperand() && 3339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), 3340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements_kind)) { 3341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(ToRegister(key)); 3342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand operand(BuildFastArrayOperand( 3344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->elements(), 3345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch key, 3346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->key()->representation(), 3347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements_kind, 3348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->base_offset())); 3349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || 3350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements_kind == FLOAT32_ELEMENTS) { 3351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand); 3352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || 3353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements_kind == FLOAT64_ELEMENTS) { 3354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Mov(ToX87Register(instr->result()), operand); 3355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result(ToRegister(instr->result())); 3357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (elements_kind) { 3358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_INT8_ELEMENTS: 3359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case INT8_ELEMENTS: 3360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movsx_b(result, operand); 3361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_UINT8_CLAMPED_ELEMENTS: 3363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_UINT8_ELEMENTS: 3364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case UINT8_ELEMENTS: 3365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case UINT8_CLAMPED_ELEMENTS: 3366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzx_b(result, operand); 3367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_INT16_ELEMENTS: 3369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case INT16_ELEMENTS: 3370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movsx_w(result, operand); 3371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_UINT16_ELEMENTS: 3373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case UINT16_ELEMENTS: 3374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzx_w(result, operand); 3375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_INT32_ELEMENTS: 3377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case INT32_ELEMENTS: 3378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, operand); 3379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_UINT32_ELEMENTS: 3381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case UINT32_ELEMENTS: 3382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, operand); 3383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { 3384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(result, Operand(result)); 3385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(negative, instr, "negative value"); 3386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_FLOAT32_ELEMENTS: 3389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_FLOAT64_ELEMENTS: 3390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FLOAT32_ELEMENTS: 3391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FLOAT64_ELEMENTS: 3392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FAST_SMI_ELEMENTS: 3393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FAST_ELEMENTS: 3394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FAST_DOUBLE_ELEMENTS: 3395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FAST_HOLEY_SMI_ELEMENTS: 3396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FAST_HOLEY_ELEMENTS: 3397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FAST_HOLEY_DOUBLE_ELEMENTS: 3398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case DICTIONARY_ELEMENTS: 3399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case SLOPPY_ARGUMENTS_ELEMENTS: 3400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 3401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 3402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { 3408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 3409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand hole_check_operand = BuildFastArrayOperand( 3410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->elements(), instr->key(), 3411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->key()->representation(), 3412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FAST_DOUBLE_ELEMENTS, 3413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->base_offset() + sizeof(kHoleNanLower32)); 3414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); 3415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "hole"); 3416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand double_load_operand = BuildFastArrayOperand( 3419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->elements(), 3420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->key(), 3421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->key()->representation(), 3422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FAST_DOUBLE_ELEMENTS, 3423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->base_offset()); 3424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Mov(ToX87Register(instr->result()), double_load_operand); 3425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { 3429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 3430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the result. 3432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, 3433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BuildFastArrayOperand(instr->elements(), instr->key(), 3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->key()->representation(), 3435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FAST_ELEMENTS, instr->base_offset())); 3436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for the hole value. 3438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 3439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { 3440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(result, Immediate(kSmiTagMask)); 3441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "not a Smi"); 3442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(result, factory()->the_hole_value()); 3444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "hole"); 3445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { 3451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->is_typed_elements()) { 3452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DoLoadKeyedExternalArray(instr); 3453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (instr->hydrogen()->representation().IsDouble()) { 3454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DoLoadKeyedFixedDoubleArray(instr); 3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DoLoadKeyedFixedArray(instr); 3457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOperand LCodeGen::BuildFastArrayOperand( 3462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* elements_pointer, 3463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* key, 3464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation key_representation, 3465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind elements_kind, 3466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t base_offset) { 3467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements_pointer_reg = ToRegister(elements_pointer); 3468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int element_shift_size = ElementsKindToShiftSize(elements_kind); 3469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int shift_size = element_shift_size; 3470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (key->IsConstantOperand()) { 3471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int constant_value = ToInteger32(LConstantOperand::cast(key)); 3472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (constant_value & 0xF0000000) { 3473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Abort(kArrayIndexConstantValueTooBig); 3474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Operand(elements_pointer_reg, 3476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ((constant_value) << shift_size) 3477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch + base_offset); 3478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Take the tag bit into account while computing the shift size. 3480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (key_representation.IsSmi() && (shift_size >= 1)) { 3481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shift_size -= kSmiTagSize; 3482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); 3484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Operand(elements_pointer_reg, 3485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToRegister(key), 3486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scale_factor, 3487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base_offset); 3488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { 3493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 3494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister())); 3495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister())); 3496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 3498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr); 3499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code(); 3502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 3503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { 3507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 3508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->from_inlined()) { 3510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(result, Operand(esp, -2 * kPointerSize)); 3511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for arguments adapter frame. 3513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, adapted; 3514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 3515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); 3516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(Operand(result), 3517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 3518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &adapted, Label::kNear); 3519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // No arguments adaptor frame. 3521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Operand(ebp)); 3522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 3523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Arguments adaptor frame present. 3525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&adapted); 3526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 3527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Result is the frame pointer for the frame if not adapted and for the real 3529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // frame below the adaptor frame if adapted. 3530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 3531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { 3536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand elem = ToOperand(instr->elements()); 3537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 3538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 3540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If no arguments adaptor frame the number of arguments is fixed. 3542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ebp, elem); 3543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Immediate(scope()->num_parameters())); 3544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &done, Label::kNear); 3545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Arguments adaptor frame present. Get argument length from there. 3547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 3548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Operand(result, 3549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArgumentsAdaptorFrameConstants::kLengthOffset)); 3550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(result); 3551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Argument length is in result register. 3553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 3554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { 3558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = ToRegister(instr->receiver()); 3559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register function = ToRegister(instr->function()); 3560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the receiver is null or undefined, we have to pass the global 3562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // object as a receiver to normal functions. Values have to be 3563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // passed unchanged to builtins and strict-mode functions. 3564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label receiver_ok, global_object; 3565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; 3566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = ToRegister(instr->temp()); 3567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!instr->hydrogen()->known_function()) { 3569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do not transform the receiver to object for strict mode 3570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // functions. 3571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch, 3572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); 3573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset), 3574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1 << SharedFunctionInfo::kStrictModeBitWithinByte); 3575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &receiver_ok, dist); 3576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do not transform the receiver to object for builtins. 3578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset), 3579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1 << SharedFunctionInfo::kNativeBitWithinByte); 3580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &receiver_ok, dist); 3581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Normal function. Replace undefined or null with global receiver. 3584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(receiver, factory()->null_value()); 3585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &global_object, Label::kNear); 3586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(receiver, factory()->undefined_value()); 3587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &global_object, Label::kNear); 3588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The receiver should be a JS object. 3590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(receiver, Immediate(kSmiTagMask)); 3591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "Smi"); 3592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); 3593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(below, instr, "not a JavaScript object"); 3594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&receiver_ok, Label::kNear); 3596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&global_object); 3597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); 3598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); 3599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(receiver, Operand(receiver, global_offset)); 3600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int proxy_offset = GlobalObject::kGlobalProxyOffset; 3601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(receiver, FieldOperand(receiver, proxy_offset)); 3602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&receiver_ok); 3603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoApplyArguments(LApplyArguments* instr) { 3607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = ToRegister(instr->receiver()); 3608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register function = ToRegister(instr->function()); 3609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register length = ToRegister(instr->length()); 3610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements = ToRegister(instr->elements()); 3611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(receiver.is(eax)); // Used for parameter count. 3612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(function.is(edi)); // Required by InvokeFunction. 3613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->result()).is(eax)); 3614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy the arguments to this function possibly from the 3616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // adaptor frame below it. 3617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const uint32_t kArgumentsLimit = 1 * KB; 3618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(length, kArgumentsLimit); 3619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(above, instr, "too many arguments"); 3620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(receiver); 3622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(receiver, length); 3623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Loop through the arguments pushing them onto the execution 3625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stack. 3626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label invoke, loop; 3627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // length is a small non-negative integer, due to the test above. 3628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(length, Operand(length)); 3629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &invoke, Label::kNear); 3630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop); 3631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); 3632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ dec(length); 3633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &loop); 3634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Invoke the function. 3636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&invoke); 3637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->HasPointerMap()); 3638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LPointerMap* pointers = instr->pointer_map(); 3639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SafepointGenerator safepoint_generator( 3640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch this, pointers, Safepoint::kLazyDeopt); 3641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount actual(eax); 3642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator); 3643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDebugBreak(LDebugBreak* instr) { 3647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ int3(); 3648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoPushArgument(LPushArgument* instr) { 3652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* argument = instr->value(); 3653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitPushTaggedOperand(argument); 3654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDrop(LDrop* instr) { 3658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(instr->count()); 3659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoThisFunction(LThisFunction* instr) { 3663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 3664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 3665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoContext(LContext* instr) { 3669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 3670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info()->IsOptimizing()) { 3671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset)); 3672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If there is no frame, the context must be in esi. 3674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result.is(esi)); 3675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { 3680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 3681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(esi); // The context is the first argument. 3682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(instr->hydrogen()->pairs())); 3683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags()))); 3684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntime(Runtime::kDeclareGlobals, 3, instr); 3685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::CallKnownFunction(Handle<JSFunction> function, 3689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int formal_parameter_count, 3690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arity, 3691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LInstruction* instr, 3692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EDIState edi_state) { 3693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool dont_adapt_arguments = 3694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; 3695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool can_invoke_directly = 3696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dont_adapt_arguments || formal_parameter_count == arity; 3697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (can_invoke_directly) { 3699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (edi_state == EDI_UNINITIALIZED) { 3700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadHeapObject(edi, function); 3701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Change context. 3704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 3705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set eax to arguments count if adaption is not needed. Assumes that eax 3707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is available to write to at this point. 3708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (dont_adapt_arguments) { 3709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, arity); 3710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Invoke function directly. 3713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (function.is_identical_to(info()->closure())) { 3714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallSelf(); 3715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset)); 3717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 3719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We need to adapt arguments. 3721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LPointerMap* pointers = instr->pointer_map(); 3722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SafepointGenerator generator( 3723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch this, pointers, Safepoint::kLazyDeopt); 3724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount count(arity); 3725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount expected(formal_parameter_count); 3726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(function, expected, count, CALL_FUNCTION, generator); 3727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoTailCallThroughMegamorphicCache( 3732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LTailCallThroughMegamorphicCache* instr) { 3733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = ToRegister(instr->receiver()); 3734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register name = ToRegister(instr->name()); 3735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(receiver.is(LoadDescriptor::ReceiverRegister())); 3736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name.is(LoadDescriptor::NameRegister())); 3737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = ebx; 3739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register extra = eax; 3740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch.is(receiver) && !scratch.is(name)); 3741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!extra.is(receiver) && !extra.is(name)); 3742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Important for the tail-call. 3744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool must_teardown_frame = NeedsEagerFrame(); 3745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The probe will tail call to a handler if found. 3747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->stub_cache()->GenerateProbe(masm(), instr->hydrogen()->flags(), 3748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch must_teardown_frame, receiver, name, 3749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scratch, extra); 3750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Tail call to miss if we ended up here. 3752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (must_teardown_frame) __ leave(); 3753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadIC::GenerateMiss(masm()); 3754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { 3758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->result()).is(eax)); 3759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LPointerMap* pointers = instr->pointer_map(); 3761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); 3762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->target()->IsConstantOperand()) { 3764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LConstantOperand* target = LConstantOperand::cast(instr->target()); 3765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> code = Handle<Code>::cast(ToHandle(target)); 3766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET)); 3767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(code, RelocInfo::CODE_TARGET); 3768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->target()->IsRegister()); 3770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register target = ToRegister(instr->target()); 3771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator.BeforeCall(__ CallSize(Operand(target))); 3772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(target, Immediate(Code::kHeaderSize - kHeapObjectTag)); 3773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(target); 3774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator.AfterCall(); 3776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { 3780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->function()).is(edi)); 3781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->result()).is(eax)); 3782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->pass_argument_count()) { 3784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, instr->arity()); 3785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Change context. 3788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 3789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_self_call = false; 3791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->function()->IsConstant()) { 3792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HConstant* fun_const = HConstant::cast(instr->hydrogen()->function()); 3793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> jsfun = 3794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction>::cast(fun_const->handle(isolate())); 3795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch is_self_call = jsfun.is_identical_to(info()->closure()); 3796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_self_call) { 3799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallSelf(); 3800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset)); 3802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 3805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { 3809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_reg = ToRegister(instr->value()); 3810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 3811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch factory()->heap_number_map()); 3812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "not a heap number"); 3813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow, allocated, done; 3815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register tmp = input_reg.is(eax) ? ecx : eax; 3816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; 3817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the value of all registers. 3819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 3820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 3822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the sign of the argument. If the argument is positive, just 3823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // return it. We do not need to patch the stack since |input| and 3824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // |result| are the same register and |input| will be restored 3825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // unchanged by popping safepoint registers. 3826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(tmp, Immediate(HeapNumber::kSignMask)); 3827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &done, Label::kNear); 3828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); 3830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&allocated, Label::kNear); 3831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Slow case: Call the runtime system to do the number allocation. 3833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 3834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, 3835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr, instr->context()); 3836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set the pointer to the new heap number in tmp. 3837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!tmp.is(eax)) __ mov(tmp, eax); 3838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore input_reg after call to runtime. 3839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadFromSafepointRegisterSlot(input_reg, input_reg); 3840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&allocated); 3842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 3843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(tmp2, ~HeapNumber::kSignMask); 3844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); 3845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); 3846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2); 3847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreToSafepointRegisterSlot(input_reg, tmp); 3848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 3850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { 3854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_reg = ToRegister(instr->value()); 3855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(input_reg, Operand(input_reg)); 3856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label is_positive; 3857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_sign, &is_positive, Label::kNear); 3858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ neg(input_reg); // Sets flags. 3859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(negative, instr, "overflow"); 3860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&is_positive); 3861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathAbs(LMathAbs* instr) { 3865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Class for deferred case. 3866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { 3867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 3868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, 3869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LMathAbs* instr, 3870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const X87Stack& x87_stack) 3871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : LDeferredCode(codegen, x87_stack), instr_(instr) { } 3872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Generate() OVERRIDE { 3873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); 3874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual LInstruction* instr() OVERRIDE { return instr_; } 3876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 3877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LMathAbs* instr_; 3878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 3879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->value()->Equals(instr->result())); 3881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation r = instr->hydrogen()->value()->representation(); 3882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (r.IsDouble()) { 3884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register value = ToX87Register(instr->value()); 3885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fxch(value); 3886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fabs(); 3887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (r.IsSmiOrInteger32()) { 3888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitIntegerMathAbs(instr); 3889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { // Tagged case. 3890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredMathAbsTaggedHeapNumber* deferred = 3891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr, x87_stack_); 3892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_reg = ToRegister(instr->value()); 3893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Smi check. 3894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotSmi(input_reg, deferred->entry()); 3895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitIntegerMathAbs(instr); 3896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(deferred->exit()); 3897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathFloor(LMathFloor* instr) { 3902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register output_reg = ToRegister(instr->result()); 3903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register input_reg = ToX87Register(instr->value()); 3904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fxch(input_reg); 3905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label not_minus_zero, done; 3907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Deoptimize on unordered. 3908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fldz(); 3909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(1); 3910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 3911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(parity_even, instr, "NaN"); 3912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below, ¬_minus_zero, Label::kNear); 3913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for negative zero. 3916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, ¬_minus_zero, Label::kNear); 3917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // +- 0.0. 3918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(0); 3919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FXamSign(); 3920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_zero, instr, "minus zero"); 3921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(output_reg, Immediate(0)); 3922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kFar); 3923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Positive input. 3926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rc=01B, round down. 3927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_minus_zero); 3928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fnclex(); 3929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ X87SetRC(0x0400); 3930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(esp, Immediate(kPointerSize)); 3931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fist_s(Operand(esp, 0)); 3932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(output_reg); 3933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ X87CheckIA(); 3934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "overflow"); 3935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fnclex(); 3936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ X87SetRC(0x0000); 3937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 3938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathRound(LMathRound* instr) { 3942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register input_reg = ToX87Register(instr->value()); 3943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 3944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fxch(input_reg); 3945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label below_one_half, below_minus_one_half, done; 3946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference one_half = ExternalReference::address_of_one_half(); 3948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference minus_one_half = 3949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_minus_one_half(); 3950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(Operand::StaticVariable(one_half)); 3952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(1); 3953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 3954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(carry, &below_one_half); 3955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use rounds towards zero, since 0.5 <= x, we use floor(0.5 + x) 3957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(0); 3958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fadd_d(Operand::StaticVariable(one_half)); 3959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rc=11B, round toward zero. 3960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ X87SetRC(0x0c00); 3961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(esp, Immediate(kPointerSize)); 3962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Clear exception bits. 3963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fnclex(); 3964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fistp_s(MemOperand(esp, 0)); 3965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check overflow. 3966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ X87CheckIA(); 3967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(result); 3968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "conversion overflow"); 3969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fnclex(); 3970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore round mode. 3971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ X87SetRC(0x0000); 3972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 3973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&below_one_half); 3975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(Operand::StaticVariable(minus_one_half)); 3976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(1); 3977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 3978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(carry, &below_minus_one_half); 3979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if 3980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we can ignore the difference between a result of -0 and +0. 3981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the sign is positive, we return +0. 3983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(0); 3984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FXamSign(); 3985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_zero, instr, "minus zero"); 3986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(result, Immediate(0)); 3988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 3989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&below_minus_one_half); 3991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(0); 3992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fadd_d(Operand::StaticVariable(one_half)); 3993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rc=01B, round down. 3994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ X87SetRC(0x0400); 3995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(esp, Immediate(kPointerSize)); 3996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Clear exception bits. 3997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fnclex(); 3998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fistp_s(MemOperand(esp, 0)); 3999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check overflow. 4000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ X87CheckIA(); 4001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(result); 4002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "conversion overflow"); 4003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fnclex(); 4004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore round mode. 4005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ X87SetRC(0x0000); 4006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 4008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathFround(LMathFround* instr) { 4012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register input_reg = ToX87Register(instr->value()); 4013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fxch(input_reg); 4014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(esp, Immediate(kPointerSize)); 4015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp_s(MemOperand(esp, 0)); 4016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fld(MemOperand(esp, 0), kX87FloatOperand); 4017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(esp, Immediate(kPointerSize)); 4018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathSqrt(LMathSqrt* instr) { 4022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register input = ToX87Register(instr->value()); 4023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register result_reg = ToX87Register(instr->result()); 4024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp_result = ToRegister(instr->temp1()); 4025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp2()); 4026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow, done, smi, finish; 4027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result_reg.is(input)); 4028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store input into Heap number and call runtime function kMathExpRT. 4030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_inline_new) { 4031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AllocateHeapNumber(temp_result, temp, no_reg, &slow); 4032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 4033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Slow case: Call the runtime system to do the number allocation. 4036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 4037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 4038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(3095996): Put a valid pointer value in the stack slot where the 4039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result register is stored, as this register is in the pointer map, but 4040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // contains an integer value. 4041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(temp_result, Immediate(0)); 4042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the value of all registers. 4044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 4045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 4047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 4048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithRegisters( 4049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 4050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreToSafepointRegisterSlot(temp_result, eax); 4051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 4053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87LoadForUsage(input); 4054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp_d(FieldOperand(temp_result, HeapNumber::kValueOffset)); 4055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 4057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the value of all registers. 4058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 4059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 4061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(temp_result); 4062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntimeSaveDoubles(Runtime::kMathSqrtRT); 4063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithRegisters(instr->pointer_map(), 1, 4064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Safepoint::kNoLazyDeopt); 4065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreToSafepointRegisterSlot(temp_result, eax); 4066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87PrepareToWrite(result_reg); 4068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // return value of MathExpRT is Smi or Heap Number. 4069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(temp_result, &smi); 4070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Heap number(double) 4071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(FieldOperand(temp_result, HeapNumber::kValueOffset)); 4072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&finish); 4073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // SMI 4074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&smi); 4075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(temp_result); 4076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(temp_result); 4077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fild_s(MemOperand(esp, 0)); 4078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(temp_result); 4079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&finish); 4080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87CommitWrite(result_reg); 4081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { 4085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register input_reg = ToX87Register(instr->value()); 4086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToX87Register(instr->result()).is(input_reg)); 4087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fxch(input_reg); 4088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Note that according to ECMA-262 15.8.2.13: 4089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Math.pow(-Infinity, 0.5) == Infinity 4090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Math.sqrt(-Infinity) == NaN 4091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, sqrt; 4092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check base for -Infinity. C3 == 0, C2 == 1, C1 == 1 and C0 == 1 4093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fxam(); 4094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(eax); 4095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fnstsw_ax(); 4096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(eax, Immediate(0x4700)); 4097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, Immediate(0x0700)); 4098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &sqrt, Label::kNear); 4099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If input is -Infinity, return Infinity. 4100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fchs(); 4101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 4102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Square root. 4104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&sqrt); 4105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fldz(); 4106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ faddp(); // Convert -0 to +0. 4107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fsqrt(); 4108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 4109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(eax); 4110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoPower(LPower* instr) { 4114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation exponent_type = instr->hydrogen()->right()->representation(); 4115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register result = ToX87Register(instr->result()); 4116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Having marked this as a call, we can use any registers. 4117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register base = ToX87Register(instr->left()); 4118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference one_half = ExternalReference::address_of_one_half(); 4119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (exponent_type.IsSmi()) { 4121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register exponent = ToRegister(instr->right()); 4122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87LoadForUsage(base); 4123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(exponent); 4124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(exponent); 4125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fild_s(MemOperand(esp, 0)); 4126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(exponent); 4127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (exponent_type.IsTagged()) { 4128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register exponent = ToRegister(instr->right()); 4129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = exponent.is(ecx) ? eax : ecx; 4130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_deopt, done; 4131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87LoadForUsage(base); 4132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(exponent, &no_deopt); 4133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, temp); 4134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "not a heap number"); 4135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Heap number(double) 4136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(FieldOperand(exponent, HeapNumber::kValueOffset)); 4137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 4138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // SMI 4139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_deopt); 4140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(exponent); 4141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(exponent); 4142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fild_s(MemOperand(esp, 0)); 4143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(exponent); 4144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 4145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (exponent_type.IsInteger32()) { 4146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register exponent = ToRegister(instr->right()); 4147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87LoadForUsage(base); 4148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(exponent); 4149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fild_s(MemOperand(esp, 0)); 4150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(exponent); 4151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(exponent_type.IsDouble()); 4153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register exponent_double = ToX87Register(instr->right()); 4154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87LoadForUsage(base, exponent_double); 4155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP data stack {base, exponent(TOS)}. 4158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Handle (exponent==+-0.5 && base == -0). 4159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label not_plus_0; 4160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(0); 4161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fabs(); 4162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fld(Operand::StaticVariable(one_half), kX87DoubleOperand); 4163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 4164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(parity_even, ¬_plus_0, Label::kNear); // NaN. 4165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, ¬_plus_0, Label::kNear); 4166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fldz(); 4167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP data stack {base, exponent(TOS), zero}. 4168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ faddp(2); 4169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_plus_0); 4170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 4172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PrepareCallCFunction(4, eax); 4173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp_d(MemOperand(esp, kDoubleSize)); // Exponent value. 4174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp_d(MemOperand(esp, 0)); // Base value. 4175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87PrepareToWrite(result); 4176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallCFunction(ExternalReference::power_double_double_function(isolate()), 4177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4); 4178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return value is in st(0) on ia32. 4179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87CommitWrite(result); 4180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathLog(LMathLog* instr) { 4185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->value()->Equals(instr->result())); 4186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register input_reg = ToX87Register(instr->value()); 4187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fxch(input_reg); 4188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label positive, done, zero, nan_result; 4190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fldz(); 4191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(1); 4192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 4193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below, &nan_result, Label::kNear); 4194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &zero, Label::kNear); 4195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Positive input. 4196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // {input, ln2}. 4197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fldln2(); 4198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // {ln2, input}. 4199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fxch(); 4200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // {result}. 4201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fyl2x(); 4202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 4203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&nan_result); 4205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference nan = 4206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_canonical_non_hole_nan(); 4207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87PrepareToWrite(input_reg); 4208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(Operand::StaticVariable(nan)); 4209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87CommitWrite(input_reg); 4210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 4211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&zero); 4213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ninf = ExternalReference::address_of_negative_infinity(); 4214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87PrepareToWrite(input_reg); 4215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(Operand::StaticVariable(ninf)); 4216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87CommitWrite(input_reg); 4217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 4219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathClz32(LMathClz32* instr) { 4223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input = ToRegister(instr->value()); 4224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 4225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label not_zero_input; 4226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bsr(result, input); 4227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, ¬_zero_input); 4229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(result, Immediate(63)); // 63^31 == 32 4230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_zero_input); 4232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xor_(result, Immediate(31)); // for x in [0..31], 31^x == 31-x. 4233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoMathExp(LMathExp* instr) { 4237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register input = ToX87Register(instr->value()); 4238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register result_reg = ToX87Register(instr->result()); 4239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp_result = ToRegister(instr->temp1()); 4240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp2()); 4241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow, done, smi, finish; 4242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result_reg.is(input)); 4243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store input into Heap number and call runtime function kMathExpRT. 4245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_inline_new) { 4246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AllocateHeapNumber(temp_result, temp, no_reg, &slow); 4247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 4248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Slow case: Call the runtime system to do the number allocation. 4251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 4252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 4253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(3095996): Put a valid pointer value in the stack slot where the 4254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result register is stored, as this register is in the pointer map, but 4255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // contains an integer value. 4256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(temp_result, Immediate(0)); 4257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the value of all registers. 4259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 4260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 4262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 4263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithRegisters(instr->pointer_map(), 0, 4264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Safepoint::kNoLazyDeopt); 4265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreToSafepointRegisterSlot(temp_result, eax); 4266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 4268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87LoadForUsage(input); 4269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp_d(FieldOperand(temp_result, HeapNumber::kValueOffset)); 4270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 4272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the value of all registers. 4273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 4274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 4276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(temp_result); 4277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntimeSaveDoubles(Runtime::kMathExpRT); 4278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithRegisters(instr->pointer_map(), 1, 4279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Safepoint::kNoLazyDeopt); 4280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreToSafepointRegisterSlot(temp_result, eax); 4281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87PrepareToWrite(result_reg); 4283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // return value of MathExpRT is Smi or Heap Number. 4284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(temp_result, &smi); 4285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Heap number(double) 4286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(FieldOperand(temp_result, HeapNumber::kValueOffset)); 4287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&finish); 4288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // SMI 4289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&smi); 4290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(temp_result); 4291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(temp_result); 4292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fild_s(MemOperand(esp, 0)); 4293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(temp_result); 4294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&finish); 4295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87CommitWrite(result_reg); 4296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { 4300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 4301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->function()).is(edi)); 4302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->HasPointerMap()); 4303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> known_function = instr->hydrogen()->known_function(); 4305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (known_function.is_null()) { 4306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LPointerMap* pointers = instr->pointer_map(); 4307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SafepointGenerator generator( 4308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch this, pointers, Safepoint::kLazyDeopt); 4309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ParameterCount count(instr->arity()); 4310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(edi, count, CALL_FUNCTION, generator); 4311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallKnownFunction(known_function, 4313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->formal_parameter_count(), 4314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->arity(), 4315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr, 4316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EDI_CONTAINS_TARGET); 4317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCallFunction(LCallFunction* instr) { 4322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 4323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->function()).is(edi)); 4324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->result()).is(eax)); 4325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arity = instr->arity(); 4327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags()); 4328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCallNew(LCallNew* instr) { 4333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 4334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->constructor()).is(edi)); 4335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->result()).is(eax)); 4336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // No cell in ebx for construct type feedback in optimized code 4338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, isolate()->factory()->undefined_value()); 4339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS); 4340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(eax, Immediate(instr->arity())); 4341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); 4342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCallNewArray(LCallNewArray* instr) { 4346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 4347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->constructor()).is(edi)); 4348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->result()).is(eax)); 4349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(eax, Immediate(instr->arity())); 4351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, isolate()->factory()->undefined_value()); 4352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind kind = instr->hydrogen()->elements_kind(); 4353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSiteOverrideMode override_mode = 4354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) 4355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? DISABLE_ALLOCATION_SITES 4356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : DONT_OVERRIDE; 4357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->arity() == 0) { 4359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArrayNoArgumentConstructorStub stub(isolate(), kind, override_mode); 4360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); 4361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (instr->arity() == 1) { 4362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 4363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsFastPackedElementsKind(kind)) { 4364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label packed_case; 4365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We might need a change here 4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // look at the first argument 4367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, Operand(esp, 0)); 4368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(ecx, ecx); 4369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &packed_case, Label::kNear); 4370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind holey_kind = GetHoleyElementsKind(kind); 4372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArraySingleArgumentConstructorStub stub(isolate(), 4373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch holey_kind, 4374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch override_mode); 4375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); 4376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 4377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&packed_case); 4378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode); 4381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); 4382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 4383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode); 4385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); 4386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCallRuntime(LCallRuntime* instr) { 4391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 4392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles()); 4393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) { 4397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register function = ToRegister(instr->function()); 4398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register code_object = ToRegister(instr->code_object()); 4399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize)); 4400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); 4401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { 4405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 4406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register base = ToRegister(instr->base_object()); 4407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->offset()->IsConstantOperand()) { 4408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LConstantOperand* offset = LConstantOperand::cast(instr->offset()); 4409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(result, Operand(base, ToInteger32(offset))); 4410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register offset = ToRegister(instr->offset()); 4412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(result, Operand(base, offset, times_1, 0)); 4413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { 4418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation representation = instr->hydrogen()->field_representation(); 4419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HObjectAccess access = instr->hydrogen()->access(); 4421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = access.offset(); 4422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (access.IsExternalMemory()) { 4424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); 4425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand operand = instr->object()->IsConstantOperand() 4426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? MemOperand::StaticVariable( 4427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToExternalReference(LConstantOperand::cast(instr->object()))) 4428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : MemOperand(ToRegister(instr->object()), offset); 4429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->value()->IsConstantOperand()) { 4430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); 4431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(operand, Immediate(ToInteger32(operand_value))); 4432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = ToRegister(instr->value()); 4434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Store(value, operand, representation); 4435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 4437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object = ToRegister(instr->object()); 4440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertNotSmi(object); 4441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!representation.IsSmi() || 4442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !instr->value()->IsConstantOperand() || 4443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IsSmi(LConstantOperand::cast(instr->value()))); 4444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (representation.IsDouble()) { 4445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(access.IsInobject()); 4446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!instr->hydrogen()->has_transition()); 4447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); 4448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register value = ToX87Register(instr->value()); 4449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Mov(FieldOperand(object, offset), value); 4450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 4451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->has_transition()) { 4454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> transition = instr->hydrogen()->transition_map(); 4455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddDeprecationDependency(transition); 4456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(object, HeapObject::kMapOffset), transition); 4457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->NeedsWriteBarrierForMap()) { 4458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp()); 4459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp_map = ToRegister(instr->temp_map()); 4460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp_map, transition); 4461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map); 4462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier for the map field. 4463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteForMap(object, transition, temp_map, temp, kSaveFPRegs); 4464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do the store. 4468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register write_register = object; 4469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!access.IsInobject()) { 4470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch write_register = ToRegister(instr->temp()); 4471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); 4472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand operand = FieldOperand(write_register, offset); 4475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->value()->IsConstantOperand()) { 4476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); 4477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (operand_value->IsRegister()) { 4478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = ToRegister(operand_value); 4479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Store(value, operand, representation); 4480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (representation.IsInteger32()) { 4481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate immediate = ToImmediate(operand_value, representation); 4482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); 4483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(operand, immediate); 4484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> handle_value = ToHandle(operand_value); 4486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); 4487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(operand, handle_value); 4488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = ToRegister(instr->value()); 4491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Store(value, operand, representation); 4492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->NeedsWriteBarrier()) { 4495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = ToRegister(instr->value()); 4496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object; 4497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier for the object for in-object properties. 4498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(write_register, offset, value, temp, kSaveFPRegs, 4499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, 4500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->SmiCheckForWriteBarrier(), 4501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->PointersToHereCheckForValue()); 4502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 4507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 4508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister())); 4509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister())); 4510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(StoreDescriptor::NameRegister(), instr->name()); 4512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode()); 4513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 4514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { 4518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cc = instr->hydrogen()->allow_equality() ? above : above_equal; 4519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->index()->IsConstantOperand()) { 4520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ToOperand(instr->length()), 4521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToImmediate(LConstantOperand::cast(instr->index()), 4522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->length()->representation())); 4523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cc = CommuteCondition(cc); 4524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (instr->length()->IsConstantOperand()) { 4525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ToOperand(instr->index()), 4526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToImmediate(LConstantOperand::cast(instr->length()), 4527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->index()->representation())); 4528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); 4530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code && instr->hydrogen()->skip_check()) { 4532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 4533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(NegateCondition(cc), &done, Label::kNear); 4534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ int3(); 4535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 4536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(cc, instr, "out of bounds"); 4538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { 4543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind elements_kind = instr->elements_kind(); 4544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* key = instr->key(); 4545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!key->IsConstantOperand() && 4546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), 4547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements_kind)) { 4548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(ToRegister(key)); 4549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand operand(BuildFastArrayOperand( 4551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->elements(), 4552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch key, 4553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->key()->representation(), 4554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements_kind, 4555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->base_offset())); 4556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || 4557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements_kind == FLOAT32_ELEMENTS) { 4558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Mov(operand, ToX87Register(instr->value()), kX87FloatOperand); 4559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || 4560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements_kind == FLOAT64_ELEMENTS) { 4561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Mov(operand, ToX87Register(instr->value())); 4562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = ToRegister(instr->value()); 4564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (elements_kind) { 4565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_UINT8_CLAMPED_ELEMENTS: 4566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_UINT8_ELEMENTS: 4567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_INT8_ELEMENTS: 4568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case UINT8_ELEMENTS: 4569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case INT8_ELEMENTS: 4570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case UINT8_CLAMPED_ELEMENTS: 4571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov_b(operand, value); 4572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_INT16_ELEMENTS: 4574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_UINT16_ELEMENTS: 4575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case UINT16_ELEMENTS: 4576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case INT16_ELEMENTS: 4577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov_w(operand, value); 4578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_INT32_ELEMENTS: 4580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_UINT32_ELEMENTS: 4581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case UINT32_ELEMENTS: 4582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case INT32_ELEMENTS: 4583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(operand, value); 4584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_FLOAT32_ELEMENTS: 4586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case EXTERNAL_FLOAT64_ELEMENTS: 4587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FLOAT32_ELEMENTS: 4588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FLOAT64_ELEMENTS: 4589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FAST_SMI_ELEMENTS: 4590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FAST_ELEMENTS: 4591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FAST_DOUBLE_ELEMENTS: 4592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FAST_HOLEY_SMI_ELEMENTS: 4593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FAST_HOLEY_ELEMENTS: 4594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FAST_HOLEY_DOUBLE_ELEMENTS: 4595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case DICTIONARY_ELEMENTS: 4596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case SLOPPY_ARGUMENTS_ELEMENTS: 4597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 4598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { 4605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference canonical_nan_reference = 4606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_canonical_non_hole_nan(); 4607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand double_store_operand = BuildFastArrayOperand( 4608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->elements(), 4609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->key(), 4610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->key()->representation(), 4611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FAST_DOUBLE_ELEMENTS, 4612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->base_offset()); 4613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Can't use SSE2 in the serializer 4615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->IsConstantHoleStore()) { 4616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This means we should store the (double) hole. No floating point 4617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // registers required. 4618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double nan_double = FixedDoubleArray::hole_nan_as_double(); 4619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t int_val = bit_cast<uint64_t, double>(nan_double); 4620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t lower = static_cast<int32_t>(int_val); 4621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); 4622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(double_store_operand, Immediate(lower)); 4624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand double_store_operand2 = BuildFastArrayOperand( 4625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->elements(), 4626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->key(), 4627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->key()->representation(), 4628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FAST_DOUBLE_ELEMENTS, 4629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->base_offset() + kPointerSize); 4630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(double_store_operand2, Immediate(upper)); 4631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_special_nan_handling; 4633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register value = ToX87Register(instr->value()); 4634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fxch(value); 4635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->NeedsCanonicalization()) { 4637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(0); 4638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(0); 4639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 4640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(parity_odd, &no_special_nan_handling, Label::kNear); 4642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(esp, Immediate(kDoubleSize)); 4643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fst_d(MemOperand(esp, 0)); 4644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)), 4645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(kHoleNanUpper32)); 4646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(esp, Immediate(kDoubleSize)); 4647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label canonicalize; 4648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &canonicalize, Label::kNear); 4649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&no_special_nan_handling, Label::kNear); 4650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&canonicalize); 4651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp(0); 4652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(Operand::StaticVariable(canonical_nan_reference)); 4653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_special_nan_handling); 4656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fst_d(double_store_operand); 4657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { 4662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements = ToRegister(instr->elements()); 4663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; 4664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand operand = BuildFastArrayOperand( 4666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->elements(), 4667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->key(), 4668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->key()->representation(), 4669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FAST_ELEMENTS, 4670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->base_offset()); 4671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->value()->IsRegister()) { 4672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(operand, ToRegister(instr->value())); 4673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); 4675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsSmi(operand_value)) { 4676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate immediate = ToImmediate(operand_value, Representation::Smi()); 4677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(operand, immediate); 4678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!IsInteger32(operand_value)); 4680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> handle_value = ToHandle(operand_value); 4681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(operand, handle_value); 4682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->NeedsWriteBarrier()) { 4686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->value()->IsRegister()); 4687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = ToRegister(instr->value()); 4688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!instr->key()->IsConstantOperand()); 4689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiCheck check_needed = 4690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->value()->type().IsHeapObject() 4691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 4692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compute address of modified element and store it into key register. 4693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(key, operand); 4694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWrite(elements, key, value, kSaveFPRegs, EMIT_REMEMBERED_SET, 4695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch check_needed, 4696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->PointersToHereCheckForValue()); 4697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { 4702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // By cases...external, fast-double, fast 4703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->is_typed_elements()) { 4704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DoStoreKeyedExternalArray(instr); 4705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (instr->hydrogen()->value()->representation().IsDouble()) { 4706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DoStoreKeyedFixedDoubleArray(instr); 4707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DoStoreKeyedFixedArray(instr); 4709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { 4714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 4715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister())); 4716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister())); 4717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister())); 4718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = 4720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code(); 4721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 4722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { 4726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object = ToRegister(instr->object()); 4727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp()); 4728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_memento_found; 4729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); 4730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "memento found"); 4731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_memento_found); 4732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { 4736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object_reg = ToRegister(instr->object()); 4737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> from_map = instr->original_map(); 4739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> to_map = instr->transitioned_map(); 4740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind from_kind = instr->from_kind(); 4741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsKind to_kind = instr->to_kind(); 4742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label not_applicable; 4744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_simple_map_transition = 4745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IsSimpleMapChangeTransition(from_kind, to_kind); 4746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label::Distance branch_distance = 4747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch is_simple_map_transition ? Label::kNear : Label::kFar; 4748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); 4749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, ¬_applicable, branch_distance); 4750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_simple_map_transition) { 4751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register new_map_reg = ToRegister(instr->new_map_temp()); 4752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), 4753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(to_map)); 4754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Write barrier. 4755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_NE(instr->temp(), NULL); 4756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteForMap(object_reg, to_map, new_map_reg, 4757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToRegister(instr->temp()), kDontSaveFPRegs); 4758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 4760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(object_reg.is(eax)); 4761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 4762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, to_map); 4763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE; 4764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array); 4765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 4766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithLazyDeopt(instr, 4767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); 4768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_applicable); 4770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 4774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class DeferredStringCharCodeAt FINAL : public LDeferredCode { 4775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 4776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredStringCharCodeAt(LCodeGen* codegen, 4777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LStringCharCodeAt* instr, 4778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const X87Stack& x87_stack) 4779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : LDeferredCode(codegen, x87_stack), instr_(instr) { } 4780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Generate() OVERRIDE { 4781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoDeferredStringCharCodeAt(instr_); 4782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual LInstruction* instr() OVERRIDE { return instr_; } 4784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 4785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LStringCharCodeAt* instr_; 4786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 4787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredStringCharCodeAt* deferred = 4789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch new(zone()) DeferredStringCharCodeAt(this, instr, x87_stack_); 4790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringCharLoadGenerator::Generate(masm(), 4792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch factory(), 4793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToRegister(instr->string()), 4794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToRegister(instr->index()), 4795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToRegister(instr->result()), 4796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch deferred->entry()); 4797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(deferred->exit()); 4798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { 4802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register string = ToRegister(instr->string()); 4803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 4804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(3095996): Get rid of this. For now, we need to make the 4806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result register contain a valid pointer because it is already 4807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // contained in the register pointer map. 4808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(result, Immediate(0)); 4809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 4811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(string); 4812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the index as a smi. This is safe because of the checks in 4813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // DoStringCharCodeAt above. 4814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); 4815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->index()->IsConstantOperand()) { 4816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate immediate = ToImmediate(LConstantOperand::cast(instr->index()), 4817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation::Smi()); 4818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(immediate); 4819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index = ToRegister(instr->index()); 4821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(index); 4822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(index); 4823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntimeFromDeferred(Runtime::kStringCharCodeAtRT, 2, 4825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr, instr->context()); 4826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertSmi(eax); 4827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(eax); 4828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreToSafepointRegisterSlot(result, eax); 4829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { 4833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class DeferredStringCharFromCode FINAL : public LDeferredCode { 4834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 4835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredStringCharFromCode(LCodeGen* codegen, 4836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LStringCharFromCode* instr, 4837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const X87Stack& x87_stack) 4838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : LDeferredCode(codegen, x87_stack), instr_(instr) { } 4839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Generate() OVERRIDE { 4840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoDeferredStringCharFromCode(instr_); 4841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual LInstruction* instr() OVERRIDE { return instr_; } 4843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 4844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LStringCharFromCode* instr_; 4845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 4846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredStringCharFromCode* deferred = 4848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch new(zone()) DeferredStringCharFromCode(this, instr, x87_stack_); 4849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->hydrogen()->value()->representation().IsInteger32()); 4851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register char_code = ToRegister(instr->char_code()); 4852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 4853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!char_code.is(result)); 4854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(char_code, String::kMaxOneByteCharCode); 4856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above, deferred->entry()); 4857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(result, Immediate(factory()->single_character_string_cache())); 4858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, FieldOperand(result, 4859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char_code, times_pointer_size, 4860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::kHeaderSize)); 4861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(result, factory()->undefined_value()); 4862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, deferred->entry()); 4863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(deferred->exit()); 4864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { 4868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register char_code = ToRegister(instr->char_code()); 4869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 4870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(3095996): Get rid of this. For now, we need to make the 4872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result register contain a valid pointer because it is already 4873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // contained in the register pointer map. 4874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(result, Immediate(0)); 4875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 4877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(char_code); 4878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(char_code); 4879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); 4880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreToSafepointRegisterSlot(result, eax); 4881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStringAdd(LStringAdd* instr) { 4885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 4886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->left()).is(edx)); 4887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->right()).is(eax)); 4888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringAddStub stub(isolate(), 4889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->flags(), 4890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->pretenure_flag()); 4891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { 4896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* input = instr->value(); 4897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* output = instr->result(); 4898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(input->IsRegister() || input->IsStackSlot()); 4899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(output->IsDoubleRegister()); 4900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (input->IsRegister()) { 4901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_reg = ToRegister(input); 4902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(input_reg); 4903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Mov(ToX87Register(output), Operand(esp, 0), kX87IntOperand); 4904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(input_reg); 4905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand); 4907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { 4912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* input = instr->value(); 4913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* output = instr->result(); 4914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register res = ToX87Register(output); 4915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87PrepareToWrite(res); 4916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadUint32NoSSE2(ToRegister(input)); 4917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87CommitWrite(res); 4918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoNumberTagI(LNumberTagI* instr) { 4922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class DeferredNumberTagI FINAL : public LDeferredCode { 4923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 4924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredNumberTagI(LCodeGen* codegen, 4925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LNumberTagI* instr, 4926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const X87Stack& x87_stack) 4927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : LDeferredCode(codegen, x87_stack), instr_(instr) { } 4928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Generate() OVERRIDE { 4929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(), 4930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SIGNED_INT32); 4931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual LInstruction* instr() OVERRIDE { return instr_; } 4933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 4934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LNumberTagI* instr_; 4935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 4936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* input = instr->value(); 4938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(input->IsRegister() && input->Equals(instr->result())); 4939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(input); 4940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredNumberTagI* deferred = 4942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch new(zone()) DeferredNumberTagI(this, instr, x87_stack_); 4943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(reg); 4944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(overflow, deferred->entry()); 4945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(deferred->exit()); 4946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoNumberTagU(LNumberTagU* instr) { 4950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class DeferredNumberTagU FINAL : public LDeferredCode { 4951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 4952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredNumberTagU(LCodeGen* codegen, 4953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LNumberTagU* instr, 4954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const X87Stack& x87_stack) 4955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : LDeferredCode(codegen, x87_stack), instr_(instr) { } 4956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Generate() OVERRIDE { 4957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(), 4958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNSIGNED_INT32); 4959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual LInstruction* instr() OVERRIDE { return instr_; } 4961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 4962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LNumberTagU* instr_; 4963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 4964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* input = instr->value(); 4966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(input->IsRegister() && input->Equals(instr->result())); 4967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(input); 4968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredNumberTagU* deferred = 4970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch new(zone()) DeferredNumberTagU(this, instr, x87_stack_); 4971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(reg, Immediate(Smi::kMaxValue)); 4972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above, deferred->entry()); 4973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(reg); 4974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(deferred->exit()); 4975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, 4979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* value, 4980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* temp, 4981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IntegerSignedness signedness) { 4982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, slow; 4983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(value); 4984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register tmp = ToRegister(temp); 4985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (signedness == SIGNED_INT32) { 4987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // There was overflow, so bits 30 and 31 of the original integer 4988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // disagree. Try to allocate a heap number in new space and store 4989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the value in there. If that fails, call the runtime system. 4990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(reg); 4991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xor_(reg, 0x80000000); 4992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(reg); 4993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fild_s(Operand(esp, 0)); 4994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(reg); 4995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // There's no fild variant for unsigned values, so zero-extend to a 64-bit 4997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // int manually. 4998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(0)); 4999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(reg); 5000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fild_d(Operand(esp, 0)); 5001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(reg); 5002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(reg); 5003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_inline_new) { 5006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AllocateHeapNumber(reg, tmp, no_reg, &slow); 5007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 5008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Slow case: Call the runtime system to do the number allocation. 5011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 5012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 5013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(3095996): Put a valid pointer value in the stack slot where the 5014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result register is stored, as this register is in the pointer map, but 5015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // contains an integer value. 5016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(reg, Immediate(0)); 5017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the value of all registers. 5019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 5020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // NumberTagI and NumberTagD use the context from the frame, rather than 5022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the environment's HContext or HInlinedContext value. 5023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // They only call Runtime::kAllocateHeapNumber. 5024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The corresponding HChange instructions are added in a phase that does 5025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // not have easy access to the local context. 5026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 5027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 5028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithRegisters( 5029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 5030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreToSafepointRegisterSlot(reg, eax); 5031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 5034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); 5035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoNumberTagD(LNumberTagD* instr) { 5039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class DeferredNumberTagD FINAL : public LDeferredCode { 5040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 5041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredNumberTagD(LCodeGen* codegen, 5042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LNumberTagD* instr, 5043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const X87Stack& x87_stack) 5044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : LDeferredCode(codegen, x87_stack), instr_(instr) { } 5045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Generate() OVERRIDE { 5046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoDeferredNumberTagD(instr_); 5047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual LInstruction* instr() OVERRIDE { return instr_; } 5049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 5050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LNumberTagD* instr_; 5051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 5052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(instr->result()); 5054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put the value to the top of stack 5056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register src = ToX87Register(instr->value()); 5057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Don't use X87LoadForUsage here, which is only used by Instruction which 5058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // clobbers fp registers. 5059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch x87_stack_.Fxch(src); 5060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredNumberTagD* deferred = 5062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch new(zone()) DeferredNumberTagD(this, instr, x87_stack_); 5063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_inline_new) { 5064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register tmp = ToRegister(instr->temp()); 5065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); 5066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(deferred->entry()); 5068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(deferred->exit()); 5070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fst_d(FieldOperand(reg, HeapNumber::kValueOffset)); 5071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { 5075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(3095996): Get rid of this. For now, we need to make the 5076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result register contain a valid pointer because it is already 5077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // contained in the register pointer map. 5078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(instr->result()); 5079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(reg, Immediate(0)); 5080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 5082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // NumberTagI and NumberTagD use the context from the frame, rather than 5083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the environment's HContext or HInlinedContext value. 5084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // They only call Runtime::kAllocateHeapNumber. 5085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The corresponding HChange instructions are added in a phase that does 5086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // not have easy access to the local context. 5087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 5088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 5089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithRegisters( 5090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 5091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreToSafepointRegisterSlot(reg, eax); 5092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoSmiTag(LSmiTag* instr) { 5096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HChange* hchange = instr->hydrogen(); 5097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input = ToRegister(instr->value()); 5098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hchange->CheckFlag(HValue::kCanOverflow) && 5099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch hchange->value()->CheckFlag(HValue::kUint32)) { 5100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(input, Immediate(0xc0000000)); 5101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_zero, instr, "overflow"); 5102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(input); 5104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hchange->CheckFlag(HValue::kCanOverflow) && 5105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !hchange->value()->CheckFlag(HValue::kUint32)) { 5106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(overflow, instr, "overflow"); 5107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoSmiUntag(LSmiUntag* instr) { 5112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* input = instr->value(); 5113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(input); 5114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(input->IsRegister() && input->Equals(instr->result())); 5115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->needs_check()) { 5116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(result, Immediate(kSmiTagMask)); 5117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_zero, instr, "not a Smi"); 5118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertSmi(result); 5120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(result); 5122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg, 5126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp_reg, X87Register res_reg, 5127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NumberUntagDMode mode) { 5128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool can_convert_undefined_to_nan = 5129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->can_convert_undefined_to_nan(); 5130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); 5131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label load_smi, done; 5133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87PrepareToWrite(res_reg); 5135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { 5136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Smi check. 5137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(input_reg, &load_smi); 5138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Heap number map check. 5140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch factory()->heap_number_map()); 5142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!can_convert_undefined_to_nan) { 5143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "not a heap number"); 5144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label heap_number, convert; 5146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &heap_number); 5147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert undefined (or hole) to NaN. 5149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(input_reg, factory()->undefined_value()); 5150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "not a heap number/undefined"); 5151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&convert); 5153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference nan = 5154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_canonical_non_hole_nan(); 5155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(Operand::StaticVariable(nan)); 5156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 5157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&heap_number); 5159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Heap number to x87 conversion. 5161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 5162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (deoptimize_on_minus_zero) { 5163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fldz(); 5164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 5165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 5166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &done, Label::kNear); 5167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use general purpose registers to check if we have -0.0 5169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 5170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(temp_reg, Immediate(HeapNumber::kSignMask)); 5171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &done, Label::kNear); 5172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pop FPU stack before deoptimizing. 5174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp(0); 5175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_zero, instr, "minus zero"); 5176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 5178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); 5180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&load_smi); 5183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Clobbering a temp is faster than re-tagging the 5184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // input register since we avoid dependencies. 5185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp_reg, input_reg); 5186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(temp_reg); // Untag smi before converting to float. 5187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(temp_reg); 5188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fild_s(Operand(esp, 0)); 5189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(esp, Immediate(kPointerSize)); 5190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 5191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87CommitWrite(res_reg); 5192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { 5196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_reg = ToRegister(instr->value()); 5197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The input was optimistically untagged; revert it. 5199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1); 5200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(input_reg, Operand(input_reg, times_2, kHeapObjectTag)); 5201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->truncating()) { 5203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_heap_number, check_bools, check_false; 5204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Heap number map check. 5206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch factory()->heap_number_map()); 5208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &no_heap_number, Label::kNear); 5209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TruncateHeapNumberToI(input_reg, input_reg); 5210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(done); 5211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_heap_number); 5213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for Oddballs. Undefined/False is converted to zero and True to one 5214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // for truncating conversions. 5215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(input_reg, factory()->undefined_value()); 5216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &check_bools, Label::kNear); 5217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(input_reg, Immediate(0)); 5218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(done); 5219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_bools); 5221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(input_reg, factory()->true_value()); 5222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &check_false, Label::kNear); 5223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(input_reg, Immediate(1)); 5224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(done); 5225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_false); 5227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(input_reg, factory()->false_value()); 5228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "not a heap number/undefined/true/false"); 5229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(input_reg, Immediate(0)); 5230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(olivf) Converting a number on the fpu is actually quite slow. We 5232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // should first try a fast conversion and then bailout to this slow case. 5233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->factory()->heap_number_map()); 5235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "not a heap number"); 5236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(esp, Immediate(kPointerSize)); 5238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 5239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { 5241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_precision_lost, not_nan, zero_check; 5242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld(0); 5243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fist_s(MemOperand(esp, 0)); 5245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fild_s(MemOperand(esp, 0)); 5246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 5247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(input_reg); 5248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &no_precision_lost, Label::kNear); 5250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp(0); 5251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(no_condition, instr, "lost precision"); 5252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_precision_lost); 5253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(parity_odd, ¬_nan); 5255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp(0); 5256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(no_condition, instr, "NaN"); 5257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_nan); 5258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(input_reg, Operand(input_reg)); 5260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &zero_check, Label::kNear); 5261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp(0); 5262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(done); 5263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&zero_check); 5265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // To check for minus zero, we load the value again as float, and check 5266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if that is still 0. 5267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(esp, Immediate(kPointerSize)); 5268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp_s(Operand(esp, 0)); 5269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(input_reg); 5270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(input_reg, Operand(input_reg)); 5271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_zero, instr, "minus zero"); 5272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fist_s(MemOperand(esp, 0)); 5274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fild_s(MemOperand(esp, 0)); 5275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ FCmp(); 5276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(input_reg); 5277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "lost precision"); 5278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(parity_even, instr, "NaN"); 5279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoTaggedToI(LTaggedToI* instr) { 5285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class DeferredTaggedToI FINAL : public LDeferredCode { 5286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 5287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredTaggedToI(LCodeGen* codegen, 5288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LTaggedToI* instr, 5289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const X87Stack& x87_stack) 5290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : LDeferredCode(codegen, x87_stack), instr_(instr) { } 5291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Generate() OVERRIDE { 5292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoDeferredTaggedToI(instr_, done()); 5293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual LInstruction* instr() OVERRIDE { return instr_; } 5295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 5296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LTaggedToI* instr_; 5297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 5298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* input = instr->value(); 5300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(input->IsRegister()); 5301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_reg = ToRegister(input); 5302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(input_reg.is(ToRegister(instr->result()))); 5303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->value()->representation().IsSmi()) { 5305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(input_reg); 5306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredTaggedToI* deferred = 5308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch new(zone()) DeferredTaggedToI(this, instr, x87_stack_); 5309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Optimistically untag the input. 5310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the input is a HeapObject, SmiUntag will set the carry flag. 5311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 5312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(input_reg); 5313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Branch to deferred code if the input was tagged. 5314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The deferred code will take care of restoring the tag. 5315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(carry, deferred->entry()); 5316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(deferred->exit()); 5317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { 5322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* input = instr->value(); 5323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(input->IsRegister()); 5324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* temp = instr->temp(); 5325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(temp->IsRegister()); 5326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* result = instr->result(); 5327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result->IsDoubleRegister()); 5328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_reg = ToRegister(input); 5330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp_reg = ToRegister(temp); 5331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HValue* value = instr->hydrogen()->value(); 5333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NumberUntagDMode mode = value->representation().IsSmi() 5334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; 5335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNumberUntagDNoSSE2(instr, input_reg, temp_reg, ToX87Register(result), 5337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mode); 5338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDoubleToI(LDoubleToI* instr) { 5342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* input = instr->value(); 5343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(input->IsDoubleRegister()); 5344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* result = instr->result(); 5345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result->IsRegister()); 5346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result_reg = ToRegister(result); 5347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->truncating()) { 5349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register input_reg = ToX87Register(input); 5350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fxch(input_reg); 5351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TruncateX87TOSToI(result_reg); 5352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label lost_precision, is_nan, minus_zero, done; 5354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register input_reg = ToX87Register(input); 5355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fxch(input_reg); 5356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; 5357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), 5358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &lost_precision, &is_nan, &minus_zero, dist); 5359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 5360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&lost_precision); 5361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(no_condition, instr, "lost precision"); 5362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&is_nan); 5363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(no_condition, instr, "NaN"); 5364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&minus_zero); 5365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(no_condition, instr, "minus zero"); 5366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 5367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 5372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* input = instr->value(); 5373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(input->IsDoubleRegister()); 5374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* result = instr->result(); 5375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result->IsRegister()); 5376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result_reg = ToRegister(result); 5377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label lost_precision, is_nan, minus_zero, done; 5379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register input_reg = ToX87Register(input); 5380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fxch(input_reg); 5381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; 5382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), 5383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &lost_precision, &is_nan, &minus_zero, dist); 5384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 5385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&lost_precision); 5386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(no_condition, instr, "lost precision"); 5387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&is_nan); 5388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(no_condition, instr, "NaN"); 5389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&minus_zero); 5390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(no_condition, instr, "minus zero"); 5391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 5392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(result_reg); 5393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(overflow, instr, "overflow"); 5394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCheckSmi(LCheckSmi* instr) { 5398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* input = instr->value(); 5399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(ToOperand(input), Immediate(kSmiTagMask)); 5400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_zero, instr, "not a Smi"); 5401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 5405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!instr->hydrogen()->value()->type().IsHeapObject()) { 5406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* input = instr->value(); 5407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(ToOperand(input), Immediate(kSmiTagMask)); 5408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "Smi"); 5409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 5414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input = ToRegister(instr->value()); 5415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp()); 5416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 5418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->is_interval_check()) { 5420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstanceType first; 5421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstanceType last; 5422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->GetCheckInterval(&first, &last); 5423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 5425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int8_t>(first)); 5426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If there is only one type in the interval check for equality. 5428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (first == last) { 5429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "wrong instance type"); 5430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(below, instr, "wrong instance type"); 5432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Omit check for the last type. 5433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (last != LAST_TYPE) { 5434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 5435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int8_t>(last)); 5436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(above, instr, "wrong instance type"); 5437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint8_t mask; 5441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint8_t tag; 5442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); 5443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (base::bits::IsPowerOfTwo32(mask)) { 5445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); 5446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask); 5447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(tag == 0 ? not_zero : zero, instr, "wrong instance type"); 5448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 5450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(temp, mask); 5451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(temp, tag); 5452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "wrong instance type"); 5453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCheckValue(LCheckValue* instr) { 5459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<HeapObject> object = instr->hydrogen()->object().handle(); 5460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->object_in_new_space()) { 5461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(instr->value()); 5462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Cell> cell = isolate()->factory()->NewCell(object); 5463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(reg, Operand::ForCell(cell)); 5464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand operand = ToOperand(instr->value()); 5466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(operand, object); 5467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "value mismatch"); 5469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { 5473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 5474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 5475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(object); 5476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xor_(esi, esi); 5477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); 5478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithRegisters( 5479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); 5480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(eax, Immediate(kSmiTagMask)); 5482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "instance migration failed"); 5484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCheckMaps(LCheckMaps* instr) { 5488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class DeferredCheckMaps FINAL : public LDeferredCode { 5489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 5490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredCheckMaps(LCodeGen* codegen, 5491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LCheckMaps* instr, 5492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object, 5493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const X87Stack& x87_stack) 5494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : LDeferredCode(codegen, x87_stack), instr_(instr), object_(object) { 5495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetExit(check_maps()); 5496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Generate() OVERRIDE { 5498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoDeferredInstanceMigration(instr_, object_); 5499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* check_maps() { return &check_maps_; } 5501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual LInstruction* instr() OVERRIDE { return instr_; } 5502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 5503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LCheckMaps* instr_; 5504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label check_maps_; 5505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object_; 5506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 5507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->IsStabilityCheck()) { 5509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const UniqueSet<Map>* maps = instr->hydrogen()->maps(); 5510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < maps->size(); ++i) { 5511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddStabilityDependency(maps->at(i).handle()); 5512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 5514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* input = instr->value(); 5517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(input->IsRegister()); 5518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = ToRegister(input); 5519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredCheckMaps* deferred = NULL; 5521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->HasMigrationTarget()) { 5522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_); 5523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(deferred->check_maps()); 5524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const UniqueSet<Map>* maps = instr->hydrogen()->maps(); 5527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label success; 5528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < maps->size() - 1; i++) { 5529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> map = maps->at(i).handle(); 5530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareMap(reg, map); 5531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &success, Label::kNear); 5532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> map = maps->at(maps->size() - 1).handle(); 5535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareMap(reg, map); 5536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->HasMigrationTarget()) { 5537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, deferred->entry()); 5538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "wrong map"); 5540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&success); 5543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 5547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register value_reg = ToX87Register(instr->unclamped()); 5548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result_reg = ToRegister(instr->result()); 5549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fxch(value_reg); 5550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ClampTOSToUint8(result_reg); 5551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { 5555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->unclamped()->Equals(instr->result())); 5556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value_reg = ToRegister(instr->result()); 5557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ClampUint8(value_reg); 5558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoClampTToUint8NoSSE2(LClampTToUint8NoSSE2* instr) { 5562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input_reg = ToRegister(instr->unclamped()); 5563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result_reg = ToRegister(instr->result()); 5564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = ToRegister(instr->scratch()); 5565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2 = ToRegister(instr->scratch2()); 5566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch3 = ToRegister(instr->scratch3()); 5567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label is_smi, done, heap_number, valid_exponent, 5568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch largest_value, zero_result, maybe_nan_or_infinity; 5569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(input_reg, &is_smi); 5571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for heap number 5573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch factory()->heap_number_map()); 5575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &heap_number, Label::kNear); 5576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for undefined. Undefined is converted to zero for clamping 5578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // conversions. 5579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(input_reg, factory()->undefined_value()); 5580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "not a heap number/undefined"); 5581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&zero_result, Label::kNear); 5582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Heap number 5584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&heap_number); 5585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Surprisingly, all of the hand-crafted bit-manipulations below are much 5587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // faster than the x86 FPU built-in instruction, especially since "banker's 5588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rounding" would be additionally very expensive 5589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get exponent word. 5591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 5592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); 5593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Test for negative values --> clamp to zero 5595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(scratch, scratch); 5596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(negative, &zero_result, Label::kNear); 5597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get exponent alone in scratch2. 5599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch2, scratch); 5600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(scratch2, HeapNumber::kExponentMask); 5601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shr(scratch2, HeapNumber::kExponentShift); 5602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &zero_result, Label::kNear); 5603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1)); 5604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(negative, &zero_result, Label::kNear); 5605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const uint32_t non_int8_exponent = 7; 5607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(scratch2, Immediate(non_int8_exponent + 1)); 5608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the exponent is too big, check for special values. 5609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(greater, &maybe_nan_or_infinity, Label::kNear); 5610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&valid_exponent); 5612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent 5613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // < 7. The shift bias is the number of bits to shift the mantissa such that 5614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // with an exponent of 7 such the that top-most one is in bit 30, allowing 5615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // detection the rounding overflow of a 255.5 to 256 (bit 31 goes from 0 to 5616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1). 5617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int shift_bias = (30 - HeapNumber::kExponentShift) - 7 - 1; 5618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(result_reg, MemOperand(scratch2, shift_bias)); 5619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Here result_reg (ecx) is the shift, scratch is the exponent word. Get the 5620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // top bits of the mantissa. 5621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(scratch, HeapNumber::kMantissaMask); 5622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put back the implicit 1 of the mantissa 5623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ or_(scratch, 1 << HeapNumber::kExponentShift); 5624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Shift up to round 5625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shl_cl(scratch); 5626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use "banker's rounding" to spec: If fractional part of number is 0.5, then 5627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // use the bit in the "ones" place and add it to the "halves" place, which has 5628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the effect of rounding to even. 5629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch2, scratch); 5630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8; 5631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const uint32_t one_bit_shift = one_half_bit_shift + 1; 5632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(scratch2, Immediate((1 << one_bit_shift) - 1)); 5633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(scratch2, Immediate(1 << one_half_bit_shift)); 5634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_round; 5635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(less, &no_round, Label::kNear); 5636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label round_up; 5637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch2, Immediate(1 << one_half_bit_shift)); 5638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(greater, &round_up, Label::kNear); 5639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(scratch3, scratch3); 5640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &round_up, Label::kNear); 5641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch2, scratch); 5642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(scratch2, Immediate(1 << one_bit_shift)); 5643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shr(scratch2, 1); 5644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&round_up); 5645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(scratch, scratch2); 5646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(overflow, &largest_value, Label::kNear); 5647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_round); 5648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shr(scratch, 23); 5649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result_reg, scratch); 5650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 5651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&maybe_nan_or_infinity); 5653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for NaN/Infinity, all other values map to 255 5654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1)); 5655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &largest_value, Label::kNear); 5656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for NaN, which differs from Infinity in that at least one mantissa 5658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bit is set. 5659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(scratch, HeapNumber::kMantissaMask); 5660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); 5661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &zero_result, Label::kNear); // M!=0 --> NaN 5662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Infinity -> Fall through to map to 255. 5663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&largest_value); 5665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result_reg, Immediate(255)); 5666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 5667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&zero_result); 5669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xor_(result_reg, result_reg); 5670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 5671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // smi 5673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&is_smi); 5674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!input_reg.is(result_reg)) { 5675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result_reg, input_reg); 5676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(result_reg); 5678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ClampUint8(result_reg); 5679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 5680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDoubleBits(LDoubleBits* instr) { 5684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register value_reg = ToX87Register(instr->value()); 5685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result_reg = ToRegister(instr->result()); 5686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Fxch(value_reg); 5687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(esp, Immediate(kDoubleSize)); 5688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fst_d(Operand(esp, 0)); 5689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->bits() == HDoubleBits::HIGH) { 5690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result_reg, Operand(esp, kPointerSize)); 5691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result_reg, Operand(esp, 0)); 5693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(esp, Immediate(kDoubleSize)); 5695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoConstructDouble(LConstructDouble* instr) { 5699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register hi_reg = ToRegister(instr->hi()); 5700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register lo_reg = ToRegister(instr->lo()); 5701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87Register result_reg = ToX87Register(instr->result()); 5702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Follow below pattern to write a x87 fp register. 5703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87PrepareToWrite(result_reg); 5704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(esp, Immediate(kDoubleSize)); 5705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 0), lo_reg); 5706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, kPointerSize), hi_reg); 5707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(Operand(esp, 0)); 5708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(esp, Immediate(kDoubleSize)); 5709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch X87CommitWrite(result_reg); 5710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoAllocate(LAllocate* instr) { 5714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class DeferredAllocate FINAL : public LDeferredCode { 5715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 5716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredAllocate(LCodeGen* codegen, 5717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LAllocate* instr, 5718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const X87Stack& x87_stack) 5719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : LDeferredCode(codegen, x87_stack), instr_(instr) { } 5720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Generate() OVERRIDE { 5721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoDeferredAllocate(instr_); 5722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual LInstruction* instr() OVERRIDE { return instr_; } 5724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 5725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LAllocate* instr_; 5726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 5727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredAllocate* deferred = 5729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch new(zone()) DeferredAllocate(this, instr, x87_stack_); 5730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 5732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp()); 5733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate memory for the object. 5735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationFlags flags = TAG_OBJECT; 5736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->MustAllocateDoubleAligned()) { 5737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); 5738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { 5740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation()); 5741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); 5742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); 5743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { 5744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); 5745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); 5746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->size()->IsConstantOperand()) { 5749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); 5750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (size <= Page::kMaxRegularHeapObjectSize) { 5751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(size, result, temp, no_reg, deferred->entry(), flags); 5752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(deferred->entry()); 5754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register size = ToRegister(instr->size()); 5757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(size, result, temp, no_reg, deferred->entry(), flags); 5758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(deferred->exit()); 5761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->MustPrefillWithFiller()) { 5763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->size()->IsConstantOperand()) { 5764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); 5765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp, (size / kPointerSize) - 1); 5766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch temp = ToRegister(instr->size()); 5768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shr(temp, kPointerSizeLog2); 5769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ dec(temp); 5770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop; 5772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop); 5773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(result, temp, times_pointer_size, 0), 5774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->factory()->one_pointer_filler_map()); 5775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ dec(temp); 5776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &loop); 5777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredAllocate(LAllocate* instr) { 5782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 5783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(3095996): Get rid of this. For now, we need to make the 5785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result register contain a valid pointer because it is already 5786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // contained in the register pointer map. 5787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(result, Immediate(Smi::FromInt(0))); 5788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 5790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->size()->IsRegister()) { 5791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register size = ToRegister(instr->size()); 5792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!size.is(result)); 5793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(ToRegister(instr->size())); 5794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(size); 5795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); 5797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (size >= 0 && size <= Smi::kMaxValue) { 5798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(Smi::FromInt(size))); 5799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We should never get here at runtime => abort 5801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ int3(); 5802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 5803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int flags = AllocateDoubleAlignFlag::encode( 5807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->MustAllocateDoubleAligned()); 5808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { 5809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation()); 5810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); 5811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); 5812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { 5813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); 5814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); 5815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch flags = AllocateTargetSpace::update(flags, NEW_SPACE); 5817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(Smi::FromInt(flags))); 5819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntimeFromDeferred( 5821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); 5822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreToSafepointRegisterSlot(result, eax); 5823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoToFastProperties(LToFastProperties* instr) { 5827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->value()).is(eax)); 5828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(eax); 5829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntime(Runtime::kToFastProperties, 1, instr); 5830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { 5834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 5835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialized; 5836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Registers will be used as follows: 5837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ecx = literals array. 5838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ebx = regexp literal. 5839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // eax = regexp literal clone. 5840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // esi = context. 5841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int literal_offset = 5842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); 5843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadHeapObject(ecx, instr->hydrogen()->literals()); 5844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, FieldOperand(ecx, literal_offset)); 5845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ebx, factory()->undefined_value()); 5846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &materialized, Label::kNear); 5847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Create regexp literal using runtime function 5849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Result will be in eax. 5850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ecx); 5851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); 5852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(instr->hydrogen()->pattern())); 5853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(instr->hydrogen()->flags())); 5854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); 5855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, eax); 5856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&materialized); 5858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 5859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label allocated, runtime_allocate; 5860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); 5861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&allocated, Label::kNear); 5862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&runtime_allocate); 5864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ebx); 5865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(Smi::FromInt(size))); 5866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); 5867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(ebx); 5868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&allocated); 5870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy the content into the newly allocated memory. 5871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (Unroll copy loop once for better throughput). 5872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { 5873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(edx, FieldOperand(ebx, i)); 5874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); 5875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(eax, i), edx); 5876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(eax, i + kPointerSize), ecx); 5877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((size % (2 * kPointerSize)) != 0) { 5879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(edx, FieldOperand(ebx, size - kPointerSize)); 5880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(FieldOperand(eax, size - kPointerSize), edx); 5881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { 5886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 5887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use the fast case closure allocation code that allocates in new 5888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // space for nested functions that don't need literals cloning. 5889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool pretenure = instr->hydrogen()->pretenure(); 5890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!pretenure && instr->hydrogen()->has_no_literals()) { 5891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(), 5892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->hydrogen()->kind()); 5893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, Immediate(instr->hydrogen()->shared_info())); 5894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 5895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(esi); 5897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(instr->hydrogen()->shared_info())); 5898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(pretenure ? factory()->true_value() 5899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : factory()->false_value())); 5900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntime(Runtime::kNewClosure, 3, instr); 5901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoTypeof(LTypeof* instr) { 5906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 5907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LOperand* input = instr->value(); 5908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitPushTaggedOperand(input); 5909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntime(Runtime::kTypeof, 1, instr); 5910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 5914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register input = ToRegister(instr->value()); 5915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition final_branch_condition = EmitTypeofIs(instr, input); 5916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (final_branch_condition != no_condition) { 5917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, final_branch_condition); 5918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) { 5923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* true_label = instr->TrueLabel(chunk_); 5924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* false_label = instr->FalseLabel(chunk_); 5925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> type_name = instr->type_literal(); 5926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int left_block = instr->TrueDestination(chunk_); 5927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int right_block = instr->FalseDestination(chunk_); 5928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int next_block = GetNextEmittedBlock(); 5929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label::Distance true_distance = left_block == next_block ? Label::kNear 5931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Label::kFar; 5932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label::Distance false_distance = right_block == next_block ? Label::kNear 5933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Label::kFar; 5934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition final_branch_condition = no_condition; 5935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (String::Equals(type_name, factory()->number_string())) { 5936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(input, true_label, true_distance); 5937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(input, HeapObject::kMapOffset), 5938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch factory()->heap_number_map()); 5939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch final_branch_condition = equal; 5940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(type_name, factory()->string_string())) { 5942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(input, false_label, false_distance); 5943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); 5944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above_equal, false_label, false_distance); 5945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test_b(FieldOperand(input, Map::kBitFieldOffset), 5946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1 << Map::kIsUndetectable); 5947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch final_branch_condition = zero; 5948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(type_name, factory()->symbol_string())) { 5950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(input, false_label, false_distance); 5951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(input, SYMBOL_TYPE, input); 5952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch final_branch_condition = equal; 5953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(type_name, factory()->boolean_string())) { 5955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(input, factory()->true_value()); 5956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, true_label, true_distance); 5957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(input, factory()->false_value()); 5958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch final_branch_condition = equal; 5959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(type_name, factory()->undefined_string())) { 5961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(input, factory()->undefined_value()); 5962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, true_label, true_distance); 5963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(input, false_label, false_distance); 5964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for undetectable objects => true. 5965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); 5966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test_b(FieldOperand(input, Map::kBitFieldOffset), 5967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1 << Map::kIsUndetectable); 5968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch final_branch_condition = not_zero; 5969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(type_name, factory()->function_string())) { 5971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 5972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(input, false_label, false_distance); 5973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(input, JS_FUNCTION_TYPE, input); 5974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, true_label, true_distance); 5975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE); 5976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch final_branch_condition = equal; 5977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(type_name, factory()->object_string())) { 5979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(input, false_label, false_distance); 5980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(input, factory()->null_value()); 5981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, true_label, true_distance); 5982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); 5983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below, false_label, false_distance); 5984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 5985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above, false_label, false_distance); 5986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for undetectable objects => false. 5987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test_b(FieldOperand(input, Map::kBitFieldOffset), 5988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1 << Map::kIsUndetectable); 5989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch final_branch_condition = zero; 5990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 5992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(false_label, false_distance); 5993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return final_branch_condition; 5995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 5996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 5999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register temp = ToRegister(instr->temp()); 6000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitIsConstructCall(temp); 6002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBranch(instr, equal); 6003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EmitIsConstructCall(Register temp) { 6007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the frame pointer for the calling frame. 6008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 6009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Skip the arguments adaptor frame if it exists. 6011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label check_frame_marker; 6012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), 6013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 6014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &check_frame_marker, Label::kNear); 6015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); 6016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the marker in the calling frame. 6018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_frame_marker); 6019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), 6020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); 6021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { 6025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!info()->IsStub()) { 6026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Ensure that we have enough space after the previous lazy-bailout 6027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instruction for patching the code here. 6028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int current_pc = masm()->pc_offset(); 6029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current_pc < last_lazy_deopt_pc_ + space_needed) { 6030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; 6031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Nop(padding_size); 6032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 6033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 6034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch last_lazy_deopt_pc_ = masm()->pc_offset(); 6035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLazyBailout(LLazyBailout* instr) { 6039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch last_lazy_deopt_pc_ = masm()->pc_offset(); 6040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->HasEnvironment()); 6041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LEnvironment* env = instr->environment(); 6042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); 6043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 6044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeoptimize(LDeoptimize* instr) { 6048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Deoptimizer::BailoutType type = instr->hydrogen()->type(); 6049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the 6050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // needed return address), even though the implementation of LAZY and EAGER is 6051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // now identical. When LAZY is eventually completely folded into EAGER, remove 6052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the special case below. 6053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info()->IsStub() && type == Deoptimizer::EAGER) { 6054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch type = Deoptimizer::LAZY; 6055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 6056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(no_condition, instr, instr->hydrogen()->reason(), type); 6057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDummy(LDummy* instr) { 6061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Nothing to see here, move on! 6062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDummyUse(LDummyUse* instr) { 6066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Nothing to see here, move on! 6067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { 6071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 6072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 6073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntimeSaveDoubles(Runtime::kStackGuard); 6074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithLazyDeopt( 6075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); 6076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->HasEnvironment()); 6077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LEnvironment* env = instr->environment(); 6078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 6079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStackCheck(LStackCheck* instr) { 6083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class DeferredStackCheck FINAL : public LDeferredCode { 6084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 6085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredStackCheck(LCodeGen* codegen, 6086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LStackCheck* instr, 6087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const X87Stack& x87_stack) 6088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : LDeferredCode(codegen, x87_stack), instr_(instr) { } 6089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Generate() OVERRIDE { 6090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoDeferredStackCheck(instr_); 6091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 6092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual LInstruction* instr() OVERRIDE { return instr_; } 6093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 6094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LStackCheck* instr_; 6095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 6096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->HasEnvironment()); 6098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LEnvironment* env = instr->environment(); 6099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // There is no LLazyBailout instruction for stack-checks. We have to 6100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // prepare for lazy deoptimization explicitly here. 6101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (instr->hydrogen()->is_function_entry()) { 6102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform stack overflow check. 6103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 6104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference stack_limit = 6105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_stack_limit(isolate()); 6106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(esp, Operand::StaticVariable(stack_limit)); 6107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above_equal, &done, Label::kNear); 6108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->context()->IsRegister()); 6110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 6111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallCode(isolate()->builtins()->StackCheck(), 6112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::CODE_TARGET, 6113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr); 6114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 6115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 6116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->hydrogen()->is_backwards_branch()); 6117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform stack overflow check if this goto needs it before jumping. 6118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredStackCheck* deferred_stack_check = 6119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch new(zone()) DeferredStackCheck(this, instr, x87_stack_); 6120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference stack_limit = 6121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_stack_limit(isolate()); 6122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(esp, Operand::StaticVariable(stack_limit)); 6123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below, deferred_stack_check->entry()); 6124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); 6125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(instr->done_label()); 6126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch deferred_stack_check->SetExit(instr->done_label()); 6127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); 6128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Don't record a deoptimization index for the safepoint here. 6129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This will be done explicitly when emitting call and the safepoint in 6130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the deferred code. 6131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 6132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoOsrEntry(LOsrEntry* instr) { 6136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is a pseudo-instruction that ensures that the environment here is 6137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // properly registered for deoptimization and records the assembler's PC 6138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // offset. 6139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LEnvironment* environment = instr->environment(); 6140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the environment were already registered, we would have no way of 6142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // backpatching it with the spill slot operands. 6143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!environment->HasBeenRegistered()); 6144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 6145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateOsrPrologue(); 6147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 6151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ToRegister(instr->context()).is(esi)); 6152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, isolate()->factory()->undefined_value()); 6153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "undefined"); 6154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, isolate()->factory()->null_value()); 6156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "null"); 6157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(eax, Immediate(kSmiTagMask)); 6159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(zero, instr, "Smi"); 6160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 6162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx); 6163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(below_equal, instr, "wrong instance type"); 6164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label use_cache, call_runtime; 6166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckEnumCache(&call_runtime); 6167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 6169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&use_cache, Label::kNear); 6170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the set of properties to enumerate. 6172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&call_runtime); 6173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(eax); 6174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); 6175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 6177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->factory()->meta_map()); 6178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "wrong map"); 6179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&use_cache); 6180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 6184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map = ToRegister(instr->map()); 6185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = ToRegister(instr->result()); 6186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label load_cache, done; 6187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EnumLength(result, map); 6188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(result, Immediate(Smi::FromInt(0))); 6189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &load_cache, Label::kNear); 6190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, isolate()->factory()->empty_fixed_array()); 6191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 6192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&load_cache); 6194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadInstanceDescriptors(map, result); 6195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, 6196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(result, DescriptorArray::kEnumCacheOffset)); 6197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, 6198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 6199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 6200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(result, result); 6201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(equal, instr, "no cache"); 6202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 6206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object = ToRegister(instr->value()); 6207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ToRegister(instr->map()), 6208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(object, HeapObject::kMapOffset)); 6209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizeIf(not_equal, instr, "wrong map"); 6210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, 6214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object, 6215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index) { 6216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PushSafepointRegistersScope scope(this); 6217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(object); 6218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(index); 6219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xor_(esi, esi); 6220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble); 6221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepointWithRegisters( 6222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->pointer_map(), 2, Safepoint::kNoLazyDeopt); 6223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreToSafepointRegisterSlot(object, eax); 6224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { 6228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class DeferredLoadMutableDouble FINAL : public LDeferredCode { 6229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 6230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredLoadMutableDouble(LCodeGen* codegen, 6231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LLoadFieldByIndex* instr, 6232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object, 6233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index, 6234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const X87Stack& x87_stack) 6235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : LDeferredCode(codegen, x87_stack), 6236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr_(instr), 6237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch object_(object), 6238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index_(index) { 6239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 6240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Generate() OVERRIDE { 6241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_); 6242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 6243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual LInstruction* instr() OVERRIDE { return instr_; } 6244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 6245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LLoadFieldByIndex* instr_; 6246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object_; 6247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index_; 6248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 6249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register object = ToRegister(instr->object()); 6251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index = ToRegister(instr->index()); 6252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeferredLoadMutableDouble* deferred; 6254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch deferred = new(zone()) DeferredLoadMutableDouble( 6255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch this, instr, object, index, x87_stack_); 6256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label out_of_object, done; 6258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(index, Immediate(Smi::FromInt(1))); 6259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, deferred->entry()); 6260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sar(index, 1); 6262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(index, Immediate(0)); 6264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(less, &out_of_object, Label::kNear); 6265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(object, FieldOperand(object, 6266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index, 6267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch times_half_pointer_size, 6268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSObject::kHeaderSize)); 6269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done, Label::kNear); 6270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&out_of_object); 6272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(object, FieldOperand(object, JSObject::kPropertiesOffset)); 6273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ neg(index); 6274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Index is now equal to out of object property index plus 1. 6275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(object, FieldOperand(object, 6276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index, 6277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch times_half_pointer_size, 6278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::kHeaderSize - kPointerSize)); 6279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(deferred->exit()); 6280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 6281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) { 6285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register context = ToRegister(instr->context()); 6286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), context); 6287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LCodeGen::DoAllocateBlockContext(LAllocateBlockContext* instr) { 6291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<ScopeInfo> scope_info = instr->scope_info(); 6292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(scope_info); 6293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ToRegister(instr->function())); 6294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallRuntime(Runtime::kPushBlockContext, 2, instr); 6295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordSafepoint(Safepoint::kNoLazyDeopt); 6296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 6297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 6300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} } // namespace v8::internal 6302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_X87 6304