lithium-codegen-x64.cc revision 692be65d6b06edd9ff4cfc4c308555b7c99c1191
1b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Redistribution and use in source and binary forms, with or without 3b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// modification, are permitted provided that the following conditions are 4b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// met: 5b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// 6b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// * Redistributions of source code must retain the above copyright 7b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// notice, this list of conditions and the following disclaimer. 8b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// * Redistributions in binary form must reproduce the above 9b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// copyright notice, this list of conditions and the following 10b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// disclaimer in the documentation and/or other materials provided 11b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// with the distribution. 12b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// * Neither the name of Google Inc. nor the names of its 13b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// contributors may be used to endorse or promote products derived 14b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// from this software without specific prior written permission. 15b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// 16b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 28b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#include "v8.h" 29b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 30b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#if defined(V8_TARGET_ARCH_X64) 31b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 32b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#include "x64/lithium-codegen-x64.h" 33b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#include "code-stubs.h" 34b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#include "stub-cache.h" 35b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 36b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochnamespace v8 { 37b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochnamespace internal { 38b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 39b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 40e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// When invoking builtins, we need to record the safepoint in the middle of 41e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// the invoke instruction sequence generated by the macro assembler. 4244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass SafepointGenerator : public CallWrapper { 43e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public: 44e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch SafepointGenerator(LCodeGen* codegen, 45e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LPointerMap* pointers, 4644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int deoptimization_index) 47e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch : codegen_(codegen), 48e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pointers_(pointers), 4944f0eee88ff00398ff7f715fab053374d808c90dSteve Block deoptimization_index_(deoptimization_index) { } 50e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual ~SafepointGenerator() { } 51e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 52257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch virtual void BeforeCall(int call_size) const { 5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(call_size >= 0); 54e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Ensure that we have enough space after the previous safepoint position 5544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // for the jump generated there. 5644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int call_end = codegen_->masm()->pc_offset() + call_size; 5744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int prev_jump_end = codegen_->LastSafepointEnd() + kMinSafepointSize; 5844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (call_end < prev_jump_end) { 5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int padding_size = prev_jump_end - call_end; 60e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch STATIC_ASSERT(kMinSafepointSize <= 9); // One multibyte nop is enough. 61e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch codegen_->masm()->nop(padding_size); 62e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 6344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 6444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 65257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch virtual void AfterCall() const { 66e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch codegen_->RecordSafepoint(pointers_, deoptimization_index_); 67e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 68e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 69e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private: 70e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch static const int kMinSafepointSize = 71e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MacroAssembler::kShortCallInstructionLength; 72e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LCodeGen* codegen_; 73e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LPointerMap* pointers_; 74e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int deoptimization_index_; 75e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}; 76e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 77e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 78b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#define __ masm()-> 79b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 80b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochbool LCodeGen::GenerateCode() { 81b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch HPhase phase("Code generation", chunk()); 82b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(is_unused()); 83b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch status_ = GENERATING; 84b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return GeneratePrologue() && 85b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateBody() && 86b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateDeferredCode() && 87e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch GenerateJumpTable() && 88b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateSafepointTable(); 89b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 90b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 91b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 92b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::FinishCode(Handle<Code> code) { 93b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(is_done()); 94257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch code->set_stack_slots(GetStackSlotCount()); 951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); 96b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch PopulateDeoptimizationData(code); 9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code); 98b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 99b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 100b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 101b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::Abort(const char* format, ...) { 102b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (FLAG_trace_bailout) { 103589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SmartArrayPointer<char> name( 104589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch info()->shared_info()->DebugName()->ToCString()); 105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PrintF("Aborting LCodeGen in @\"%s\": ", *name); 106b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch va_list arguments; 107b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch va_start(arguments, format); 108b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch OS::VPrint(format, arguments); 109b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch va_end(arguments); 110b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch PrintF("\n"); 111b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 112b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch status_ = ABORTED; 113b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 114b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 115b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 116b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::Comment(const char* format, ...) { 117b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (!FLAG_code_comments) return; 118b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch char buffer[4 * KB]; 119b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch StringBuilder builder(buffer, ARRAY_SIZE(buffer)); 120b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch va_list arguments; 121b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch va_start(arguments, format); 122b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch builder.AddFormattedList(format, arguments); 123b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch va_end(arguments); 124b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 125b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Copy the string before recording it in the assembler to avoid 126b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // issues when the stack allocated buffer goes out of scope. 127b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int length = builder.position(); 128b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Vector<char> copy = Vector<char>::New(length + 1); 129b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch memcpy(copy.start(), builder.Finalize(), copy.length()); 130b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch masm()->RecordComment(copy.start()); 131b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 132b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 133b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 134b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochbool LCodeGen::GeneratePrologue() { 135b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(is_generating()); 136b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 137b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#ifdef DEBUG 138b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (strlen(FLAG_stop_at) > 0 && 139b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 140b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ int3(); 141b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 142b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif 143b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Strict mode functions need to replace the receiver with undefined 145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // when called as functions (without an explicit receiver 146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // object). rcx is zero for method calls and non-zero for function 147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // calls. 1483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (info_->is_strict_mode() || info_->is_native()) { 149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testq(rcx, rcx); 151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &ok, Label::kNear); 152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // +1 for return address. 153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; 154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(Operand(rsp, receiver_offset), kScratchRegister); 156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&ok); 157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 159b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ push(rbp); // Caller's frame pointer. 160b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ movq(rbp, rsp); 161b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ push(rsi); // Callee's context. 162b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ push(rdi); // Callee's JS function. 163b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 164b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Reserve space for the stack slots needed by the code. 165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int slots = GetStackSlotCount(); 166b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (slots > 0) { 167b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (FLAG_debug_code) { 1688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Set(rax, slots); 169b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ movq(kScratchRegister, kSlotsZapValue, RelocInfo::NONE); 170b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label loop; 171b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&loop); 172b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ push(kScratchRegister); 173b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ decl(rax); 174b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ j(not_zero, &loop); 175b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 176b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ subq(rsp, Immediate(slots * kPointerSize)); 177b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#ifdef _MSC_VER 178b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // On windows, you may not access the stack more than one page below 179b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // the most recently mapped page. To make the allocated area randomly 180b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // accessible, we write to each page in turn (the value is irrelevant). 181b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const int kPageSize = 4 * KB; 182b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int offset = slots * kPointerSize - kPageSize; 183b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch offset > 0; 184b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch offset -= kPageSize) { 185b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ movq(Operand(rsp, offset), rax); 186b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 187b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif 188b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 189b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 190b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Possibly allocate a local context. 192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (heap_slots > 0) { 194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Comment(";;; Allocate local context"); 195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Argument to NewContext is the function, which is still in rdi. 196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(rdi); 197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (heap_slots <= FastNewContextStub::kMaximumSlots) { 198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FastNewContextStub stub(heap_slots); 199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallStub(&stub); 200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CallRuntime(Runtime::kNewFunctionContext, 1); 202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch RecordSafepoint(Safepoint::kNoDeoptimizationIndex); 204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Context is returned in both rax and rsi. It replaces the context 205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // passed to us. It's saved in the stack and kept live in rsi. 206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy any necessary parameters into the context. 209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int num_parameters = scope()->num_parameters(); 210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < num_parameters; i++) { 211589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = scope()->parameter(i); 212589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int parameter_offset = StandardFrameConstants::kCallerSPOffset + 214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (num_parameters - 1 - i) * kPointerSize; 215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Load parameter from stack. 216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rax, Operand(rbp, parameter_offset)); 217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Store it in the context. 218589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int context_offset = Context::SlotOffset(var->index()); 219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(Operand(rsi, context_offset), rax); 220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Update the write barrier. This clobbers all involved 221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // registers, so we have use a third register to avoid 222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // clobbering rsi. 223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rcx, rsi); 224e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ RecordWrite(rcx, context_offset, rax, rbx); 225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Comment(";;; End allocate local context"); 228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 230b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Trace the call. 231b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (FLAG_trace) { 232b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ CallRuntime(Runtime::kTraceEnter, 0); 233b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 234b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return !is_aborted(); 235b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 236b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 237b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 238b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochbool LCodeGen::GenerateBody() { 239b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(is_generating()); 240b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch bool emit_instructions = true; 241b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (current_instruction_ = 0; 242b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch !is_aborted() && current_instruction_ < instructions_->length(); 243b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch current_instruction_++) { 244b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LInstruction* instr = instructions_->at(current_instruction_); 245b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (instr->IsLabel()) { 246b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LLabel* label = LLabel::cast(instr); 247b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch emit_instructions = !label->HasReplacement(); 248b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 249b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 250b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (emit_instructions) { 251b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic()); 252b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch instr->CompileToNative(this); 253b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 254b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 255b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return !is_aborted(); 256b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 257b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 258b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 259b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochLInstruction* LCodeGen::GetNextInstruction() { 260b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (current_instruction_ < instructions_->length() - 1) { 261b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return instructions_->at(current_instruction_ + 1); 262b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 263b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return NULL; 264b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 265b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 266b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 267b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool LCodeGen::GenerateJumpTable() { 269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < jump_table_.length(); i++) { 27044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&jump_table_[i].label); 27144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Jump(jump_table_[i].address, RelocInfo::RUNTIME_ENTRY); 272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return !is_aborted(); 274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 277b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochbool LCodeGen::GenerateDeferredCode() { 278b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(is_generating()); 2793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (deferred_.length() > 0) { 2803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 2813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LDeferredCode* code = deferred_[i]; 2823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(code->entry()); 2833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch code->Generate(); 2843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(code->exit()); 2853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 2863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 2873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Pad code to ensure that the last piece of deferred code have 2883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // room for lazy bailout. 2893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch while ((masm()->pc_offset() - LastSafepointEnd()) 2903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch < Deoptimizer::patch_size()) { 2913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int padding = masm()->pc_offset() - LastSafepointEnd(); 2923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (padding > 9) { 2933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ nop(9); 2943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 2953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ nop(padding); 2963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 2973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 298b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 299b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 300b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Deferred code is the last part of the instruction sequence. Mark 301b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // the generated code as done unless we bailed out. 302b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (!is_aborted()) status_ = DONE; 303b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return !is_aborted(); 304b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 305b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 306b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 307b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochbool LCodeGen::GenerateSafepointTable() { 308b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(is_done()); 3091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Ensure that there is space at the end of the code to write a number 3101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // of jump instructions, as well as to afford writing a call near the end 3111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // of the code. 3121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The jumps are used when there isn't room in the code stream to write 3131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // a long call instruction. Instead it writes a shorter call to a 3141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // jump instruction in the same code object. 3151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The calls are used when lazy deoptimizing a function and calls to a 3161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // deoptimization function. 3171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int short_deopts = safepoints_.CountShortDeoptimizationIntervals( 3181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static_cast<unsigned>(MacroAssembler::kJumpInstructionLength)); 3191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int byte_count = (short_deopts) * MacroAssembler::kJumpInstructionLength; 3201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block while (byte_count-- > 0) { 3211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ int3(); 3221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch safepoints_.Emit(masm(), GetStackSlotCount()); 324b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return !is_aborted(); 325b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 326b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 327b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 328b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochRegister LCodeGen::ToRegister(int index) const { 329b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return Register::FromAllocationIndex(index); 330b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 331b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 332b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 333b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochXMMRegister LCodeGen::ToDoubleRegister(int index) const { 334b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return XMMRegister::FromAllocationIndex(index); 335b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 336b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 337b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 338b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochRegister LCodeGen::ToRegister(LOperand* op) const { 339b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(op->IsRegister()); 340b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return ToRegister(op->index()); 341b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 342b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 343b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 344b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochXMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { 345b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(op->IsDoubleRegister()); 346b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return ToDoubleRegister(op->index()); 347b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 348b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 349b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 350b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochbool LCodeGen::IsInteger32Constant(LConstantOperand* op) const { 351b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return op->IsConstantOperand() && 352b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch chunk_->LookupLiteralRepresentation(op).IsInteger32(); 353b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 354b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 355b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 356b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochbool LCodeGen::IsTaggedConstant(LConstantOperand* op) const { 357b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return op->IsConstantOperand() && 358b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch chunk_->LookupLiteralRepresentation(op).IsTagged(); 359b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 360b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 361b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 362b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochint LCodeGen::ToInteger32(LConstantOperand* op) const { 363b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<Object> value = chunk_->LookupLiteral(op); 364b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32()); 365b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) == 366b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch value->Number()); 367b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return static_cast<int32_t>(value->Number()); 368b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 369b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 370b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 371b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochHandle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { 372b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<Object> literal = chunk_->LookupLiteral(op); 373e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged()); 374b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return literal; 375b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 376b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 377b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 378b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochOperand LCodeGen::ToOperand(LOperand* op) const { 379b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Does not handle registers. In X64 assembler, plain registers are not 380b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // representable as an Operand. 381b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); 382b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int index = op->index(); 383b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index >= 0) { 384b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Local or spill slot. Skip the frame pointer, function, and 385b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // context in the fixed part of the frame. 386b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return Operand(rbp, -(index + 3) * kPointerSize); 387b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 388b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Incoming parameter. Skip the return address. 389b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return Operand(rbp, -(index - 1) * kPointerSize); 390b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 391b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 392b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 393b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 394b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::WriteTranslation(LEnvironment* environment, 395b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Translation* translation) { 396b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (environment == NULL) return; 397b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 398b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // The translation includes one command per value in the environment. 399b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int translation_size = environment->values()->length(); 400b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // The output frame height does not include the parameters. 401b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int height = translation_size - environment->parameter_count(); 402b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 403b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch WriteTranslation(environment->outer(), translation); 404b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int closure_id = DefineDeoptimizationLiteral(environment->closure()); 405b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->BeginFrame(environment->ast_id(), closure_id, height); 406b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = 0; i < translation_size; ++i) { 407b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* value = environment->values()->at(i); 408b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // spilled_registers_ and spilled_double_registers_ are either 409b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // both NULL or both set. 410b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (environment->spilled_registers() != NULL && value != NULL) { 411b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (value->IsRegister() && 412b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch environment->spilled_registers()[value->index()] != NULL) { 413b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->MarkDuplicate(); 414b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AddToTranslation(translation, 415b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch environment->spilled_registers()[value->index()], 416b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch environment->HasTaggedValueAt(i)); 417b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if ( 418b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch value->IsDoubleRegister() && 419b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch environment->spilled_double_registers()[value->index()] != NULL) { 420b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->MarkDuplicate(); 421b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AddToTranslation( 422b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation, 423b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch environment->spilled_double_registers()[value->index()], 424b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch false); 425b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 426b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 427b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 428b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AddToTranslation(translation, value, environment->HasTaggedValueAt(i)); 429b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 430b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 431b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 432b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 433b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::AddToTranslation(Translation* translation, 434b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* op, 435b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch bool is_tagged) { 436b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (op == NULL) { 437b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // TODO(twuerthinger): Introduce marker operands to indicate that this value 438b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // is not present and must be reconstructed from the deoptimizer. Currently 439b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // this is only used for the arguments object. 440b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreArgumentsObject(); 441b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (op->IsStackSlot()) { 442b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (is_tagged) { 443b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreStackSlot(op->index()); 444b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 445b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreInt32StackSlot(op->index()); 446b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 447b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (op->IsDoubleStackSlot()) { 448b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreDoubleStackSlot(op->index()); 449b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (op->IsArgument()) { 450b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(is_tagged); 451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int src_index = GetStackSlotCount() + op->index(); 452b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreStackSlot(src_index); 453b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (op->IsRegister()) { 454b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register reg = ToRegister(op); 455b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (is_tagged) { 456b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreRegister(reg); 457b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 458b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreInt32Register(reg); 459b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 460b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (op->IsDoubleRegister()) { 461b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch XMMRegister reg = ToDoubleRegister(op); 462b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreDoubleRegister(reg); 463b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (op->IsConstantOperand()) { 464b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<Object> literal = chunk()->LookupLiteral(LConstantOperand::cast(op)); 465b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int src_index = DefineDeoptimizationLiteral(literal); 466b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreLiteral(src_index); 467b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 468b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch UNREACHABLE(); 469b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 470b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 471b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 472b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::CallCodeGeneric(Handle<Code> code, 4748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::Mode mode, 4758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch LInstruction* instr, 4768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SafepointMode safepoint_mode, 4778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int argc) { 4781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr != NULL); 4791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LPointerMap* pointers = instr->pointer_map(); 4801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RecordPosition(pointers->position()); 4811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ call(code, mode); 4828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RegisterLazyDeoptimization(instr, safepoint_mode, argc); 483b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 484b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Signal that we don't inline smi code before these stubs in the 485b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // optimizing code generator. 486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (code->kind() == Code::BINARY_OP_IC || 487b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch code->kind() == Code::COMPARE_IC) { 488b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ nop(); 489b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 490b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 491b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 492b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::CallCode(Handle<Code> code, 4948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::Mode mode, 4958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch LInstruction* instr) { 4968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, 0); 4978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 4988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 4998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 50044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::CallRuntime(const Runtime::Function* function, 501b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int num_arguments, 502b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LInstruction* instr) { 5031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr != NULL); 5041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->HasPointerMap()); 5051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LPointerMap* pointers = instr->pointer_map(); 5061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RecordPosition(pointers->position()); 5071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 5081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CallRuntime(function, num_arguments); 5098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT, 0); 5108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 5118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, 5148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int argc, 5158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch LInstruction* instr) { 5168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 5178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ CallRuntimeSaveDoubles(id); 5188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RecordSafepointWithRegisters( 5198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex); 520b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 522b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 5238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::RegisterLazyDeoptimization(LInstruction* instr, 5248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SafepointMode safepoint_mode, 5258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int argc) { 526b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Create the environment to bailout to. If the call has side effects 527b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // execution has to continue after the call otherwise execution can continue 528b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // from a previous bailout point repeating the call. 529b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LEnvironment* deoptimization_environment; 530b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (instr->HasDeoptimizationEnvironment()) { 531b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch deoptimization_environment = instr->deoptimization_environment(); 532b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 533b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch deoptimization_environment = instr->environment(); 534b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 535b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 536b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch RegisterEnvironmentForDeoptimization(deoptimization_environment); 5378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { 5388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(argc == 0); 5398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RecordSafepoint(instr->pointer_map(), 5408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch deoptimization_environment->deoptimization_index()); 5418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 5428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS); 5438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RecordSafepointWithRegisters( 5448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr->pointer_map(), 5458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch argc, 5468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch deoptimization_environment->deoptimization_index()); 5478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 548b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 549b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 550b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 551b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment) { 552b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (!environment->HasBeenRegistered()) { 553b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Physical stack frame layout: 554b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // -x ............. -4 0 ..................................... y 555b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // [incoming arguments] [spill slots] [pushed outgoing arguments] 556b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 557b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Layout of the environment: 558b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // 0 ..................................................... size-1 559b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // [parameters] [locals] [expression stack including arguments] 560b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 561b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Layout of the translation: 562b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // 0 ........................................................ size - 1 + 4 563b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // [expression stack including arguments] [locals] [4 words] [parameters] 564b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // |>------------ translation_size ------------<| 565b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 566b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int frame_count = 0; 567b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (LEnvironment* e = environment; e != NULL; e = e->outer()) { 568b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ++frame_count; 569b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 570b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Translation translation(&translations_, frame_count); 571b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch WriteTranslation(environment, &translation); 572b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int deoptimization_index = deoptimizations_.length(); 573b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch environment->Register(deoptimization_index, translation.index()); 574b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch deoptimizations_.Add(environment); 575b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 576b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 577b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 578b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 579b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) { 5801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RegisterEnvironmentForDeoptimization(environment); 5811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(environment->HasBeenRegistered()); 5821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int id = environment->deoptimization_index(); 5831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER); 5841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(entry != NULL); 5851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (entry == NULL) { 5861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Abort("bailout was not prepared"); 5871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return; 5881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 5891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 5901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (cc == no_condition) { 5911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Jump(entry, RelocInfo::RUNTIME_ENTRY); 5921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 593e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // We often have several deopts to the same entry, reuse the last 594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // jump entry if this is the case. 59544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (jump_table_.is_empty() || 59644f0eee88ff00398ff7f715fab053374d808c90dSteve Block jump_table_.last().address != entry) { 5978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch jump_table_.Add(JumpTableEntry(entry)); 598e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 59944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(cc, &jump_table_.last().label); 6001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 601b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 602b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 603b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 604b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { 605b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int length = deoptimizations_.length(); 606b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (length == 0) return; 607b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(FLAG_deopt); 608b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<DeoptimizationInputData> data = 60944f0eee88ff00398ff7f715fab053374d808c90dSteve Block factory()->NewDeoptimizationInputData(length, TENURED); 610b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 611e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<ByteArray> translations = translations_.CreateByteArray(); 612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch data->SetTranslationByteArray(*translations); 613b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); 614b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 615b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<FixedArray> literals = 61644f0eee88ff00398ff7f715fab053374d808c90dSteve Block factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); 617b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = 0; i < deoptimization_literals_.length(); i++) { 618b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch literals->set(i, *deoptimization_literals_[i]); 619b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 620b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data->SetLiteralArray(*literals); 621b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 622b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id())); 623b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_)); 624b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 625b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Populate the deoptimization entries. 626b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = 0; i < length; i++) { 627b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LEnvironment* env = deoptimizations_[i]; 628b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data->SetAstId(i, Smi::FromInt(env->ast_id())); 629b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data->SetTranslationIndex(i, Smi::FromInt(env->translation_index())); 630b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data->SetArgumentsStackHeight(i, 631b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Smi::FromInt(env->arguments_stack_height())); 632b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 633b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch code->set_deoptimization_data(*data); 634b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 635b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 636b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 637b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochint LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) { 638b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int result = deoptimization_literals_.length(); 639b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = 0; i < deoptimization_literals_.length(); ++i) { 640b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (deoptimization_literals_[i].is_identical_to(literal)) return i; 641b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 642b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch deoptimization_literals_.Add(literal); 643b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return result; 644b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 645b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 646b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 647b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() { 648b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(deoptimization_literals_.length() == 0); 649b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 650b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const ZoneList<Handle<JSFunction> >* inlined_closures = 651b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch chunk()->inlined_closures(); 652b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 653b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = 0, length = inlined_closures->length(); 654b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch i < length; 655b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch i++) { 656b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch DefineDeoptimizationLiteral(inlined_closures->at(i)); 657b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 658b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 659b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch inlined_function_count_ = deoptimization_literals_.length(); 660b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 661b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 662b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 6631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::RecordSafepoint( 6641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LPointerMap* pointers, 6651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Safepoint::Kind kind, 6661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int arguments, 6671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int deoptimization_index) { 6688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(kind == expected_safepoint_kind_); 6698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 670b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const ZoneList<LOperand*>* operands = pointers->operands(); 6711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 672b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Safepoint safepoint = safepoints_.DefineSafepoint(masm(), 6731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block kind, arguments, deoptimization_index); 674b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = 0; i < operands->length(); i++) { 675b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* pointer = operands->at(i); 676b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (pointer->IsStackSlot()) { 677b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch safepoint.DefinePointerSlot(pointer->index()); 6781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { 6791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block safepoint.DefinePointerRegister(ToRegister(pointer)); 680b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 681b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 6821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (kind & Safepoint::kWithRegisters) { 6831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Register rsi always contains a pointer to the context. 6841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block safepoint.DefinePointerRegister(rsi); 6851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 6861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 6871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::RecordSafepoint(LPointerMap* pointers, 6901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int deoptimization_index) { 6911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index); 692b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 693b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 694b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::RecordSafepoint(int deoptimization_index) { 696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LPointerMap empty_pointers(RelocInfo::kNoPosition); 697e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch RecordSafepoint(&empty_pointers, deoptimization_index); 698e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 699e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 701b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, 702b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int arguments, 703b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int deoptimization_index) { 7041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, 7051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block deoptimization_index); 706b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 707b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 708b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 709b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::RecordPosition(int position) { 7103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (position == RelocInfo::kNoPosition) return; 711b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch masm()->positions_recorder()->RecordPosition(position); 712b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 713b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 714b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 715b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLabel(LLabel* label) { 716b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (label->is_loop_header()) { 717b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Comment(";;; B%d - LOOP entry", label->block_id()); 718b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 719b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Comment(";;; B%d", label->block_id()); 720b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 721b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(label->label()); 722b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch current_block_ = label->block_id(); 723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DoGap(label); 724b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 725b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 726b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 727b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoParallelMove(LParallelMove* move) { 7281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block resolver_.Resolve(move); 729b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 730b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 731b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 732b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoGap(LGap* gap) { 733b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = LGap::FIRST_INNER_POSITION; 734b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch i <= LGap::LAST_INNER_POSITION; 735b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch i++) { 736b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); 737b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LParallelMove* move = gap->GetParallelMove(inner_pos); 738b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (move != NULL) DoParallelMove(move); 739b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 740b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 741b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LInstruction* next = GetNextInstruction(); 742b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (next != NULL && next->IsLazyBailout()) { 743b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int pc = masm()->pc_offset(); 744b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch safepoints_.SetPcAfterGap(pc); 745b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 746b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 747b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 748b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoInstructionGap(LInstructionGap* instr) { 750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DoGap(instr); 751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 754b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoParameter(LParameter* instr) { 755b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Nothing to do. 756b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 757b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 758b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 759b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallStub(LCallStub* instr) { 7601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 7611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->hydrogen()->major_key()) { 7621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case CodeStub::RegExpConstructResult: { 7631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RegExpConstructResultStub stub; 7641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 7651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 7661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case CodeStub::RegExpExec: { 7681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RegExpExecStub stub; 7691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 7701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 7711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case CodeStub::SubString: { 7731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SubStringStub stub; 7741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 7751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 7761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case CodeStub::NumberToString: { 7781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NumberToStringStub stub; 7791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 7801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 7811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case CodeStub::StringAdd: { 7831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block StringAddStub stub(NO_STRING_ADD_FLAGS); 7841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 7851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 7861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case CodeStub::StringCompare: { 7881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block StringCompareStub stub; 7891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 7901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 7911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case CodeStub::TranscendentalCache: { 793e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub stub(instr->transcendental_type(), 794e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub::TAGGED); 7951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 7961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 7971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 7991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 8001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 801b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 802b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 803b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 804b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 805b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Nothing to do. 806b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 807b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 808b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 809b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoModI(LModI* instr) { 81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->HasPowerOf2Divisor()) { 81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register dividend = ToRegister(instr->InputAt(0)); 812e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t divisor = 81444f0eee88ff00398ff7f715fab053374d808c90dSteve Block HConstant::cast(instr->hydrogen()->right())->Integer32Value(); 815e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 81644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (divisor < 0) divisor = -divisor; 817e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label positive_dividend, done; 81944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ testl(dividend, dividend); 820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_sign, &positive_dividend, Label::kNear); 82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ negl(dividend); 82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ andl(dividend, Immediate(divisor - 1)); 82344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ negl(dividend); 82444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &done, Label::kNear); 82644f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(no_condition, instr->environment()); 8277d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } else { 828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 82944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&positive_dividend); 83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ andl(dividend, Immediate(divisor - 1)); 83244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 83344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, remainder_eq_dividend, slow, do_subtraction, both_positive; 835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left_reg = ToRegister(instr->InputAt(0)); 836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right_reg = ToRegister(instr->InputAt(1)); 837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result_reg = ToRegister(instr->result()); 838e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(left_reg.is(rax)); 840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(result_reg.is(rdx)); 84144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!right_reg.is(rax)); 84244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!right_reg.is(rdx)); 843e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 84444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check for x % 0. 84544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 84644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ testl(right_reg, right_reg); 84744f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(zero, instr->environment()); 84844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 849e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testl(left_reg, left_reg); 851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &remainder_eq_dividend, Label::kNear); 852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(sign, &slow, Label::kNear); 853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testl(right_reg, right_reg); 855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_sign, &both_positive, Label::kNear); 856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The sign of the divisor doesn't matter. 857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ neg(right_reg); 858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&both_positive); 860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the dividend is smaller than the nonnegative 861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // divisor, the dividend is the result. 862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpl(left_reg, right_reg); 863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(less, &remainder_eq_dividend, Label::kNear); 864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the divisor is a PowerOfTwo integer. 866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch = ToRegister(instr->TempAt(0)); 867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movl(scratch, right_reg); 868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subl(scratch, Immediate(1)); 869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testl(scratch, right_reg); 870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &do_subtraction, Label::kNear); 871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ andl(left_reg, scratch); 872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&remainder_eq_dividend, Label::kNear); 873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&do_subtraction); 875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kUnfolds = 3; 876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Try a few subtractions of the dividend. 877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movl(scratch, left_reg); 878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < kUnfolds; i++) { 879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Reduce the dividend by the divisor. 880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subl(left_reg, right_reg); 881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the dividend is less than the divisor. 882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpl(left_reg, right_reg); 883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(less, &remainder_eq_dividend, Label::kNear); 884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movl(left_reg, scratch); 886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Slow case, using idiv instruction. 888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 88944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Sign extend eax to edx. 89044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (We are using only the low 32 bits of the values.) 89144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cdq(); 89244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 89344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check for (0 % -x) that will produce negative zero. 89444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label positive_left; 896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testl(left_reg, left_reg); 898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_sign, &positive_left, Label::kNear); 89944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ idivl(right_reg); 90044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 90144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Test the remainder for 0, because then the result would be -0. 902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testl(result_reg, result_reg); 903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &done, Label::kNear); 90444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 90544f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(no_condition, instr->environment()); 90644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&positive_left); 90744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ idivl(right_reg); 90844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 90944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 91044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ idivl(right_reg); 91144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&remainder_eq_dividend); 915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movl(result_reg, left_reg); 916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 918e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 919b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 920b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 921b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 922b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoDivI(LDivI* instr) { 9231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* right = instr->InputAt(1); 9241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 9251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->InputAt(0)).is(rax)); 9261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!ToRegister(instr->InputAt(1)).is(rax)); 9271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!ToRegister(instr->InputAt(1)).is(rdx)); 9281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register left_reg = rax; 9301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for x / 0. 9321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register right_reg = ToRegister(right); 9331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 9341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(right_reg, right_reg); 9351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(zero, instr->environment()); 9361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for (0 / -x) that will produce negative zero. 9391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label left_not_zero; 9411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(left_reg, left_reg); 942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &left_not_zero, Label::kNear); 9431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(right_reg, right_reg); 9441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(sign, instr->environment()); 9451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&left_not_zero); 9461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for (-kMinInt / -1). 9491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label left_not_min_int; 9511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpl(left_reg, Immediate(kMinInt)); 952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &left_not_min_int, Label::kNear); 9531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpl(right_reg, Immediate(-1)); 9541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(zero, instr->environment()); 9551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&left_not_min_int); 9561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Sign extend to rdx. 9591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cdq(); 9601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ idivl(right_reg); 9611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Deoptimize if remainder is not 0. 9631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(rdx, rdx); 9641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_zero, instr->environment()); 9651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 966b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 967b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 968b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMulI(LMulI* instr) { 9691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register left = ToRegister(instr->InputAt(0)); 9701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* right = instr->InputAt(1); 9711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 9731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movl(kScratchRegister, left); 9741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 97644f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool can_overflow = 97744f0eee88ff00398ff7f715fab053374d808c90dSteve Block instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 9781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (right->IsConstantOperand()) { 9791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int right_value = ToInteger32(LConstantOperand::cast(right)); 98044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (right_value == -1) { 98144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ negl(left); 98244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (right_value == 0) { 98344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ xorl(left, left); 98444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (right_value == 2) { 98544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ addl(left, left); 98644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (!can_overflow) { 98744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If the multiplication is known to not overflow, we 98844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // can use operations that don't set the overflow flag 98944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // correctly. 99044f0eee88ff00398ff7f715fab053374d808c90dSteve Block switch (right_value) { 99144f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 1: 99244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Do nothing. 99344f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 99444f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 3: 99544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ leal(left, Operand(left, left, times_2, 0)); 99644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 99744f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 4: 99844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ shll(left, Immediate(2)); 99944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 5: 100144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ leal(left, Operand(left, left, times_4, 0)); 100244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 100344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 8: 100444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ shll(left, Immediate(3)); 100544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 100644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 9: 100744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ leal(left, Operand(left, left, times_8, 0)); 100844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 100944f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 16: 101044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ shll(left, Immediate(4)); 101144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 101244f0eee88ff00398ff7f715fab053374d808c90dSteve Block default: 101344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ imull(left, left, Immediate(right_value)); 101444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 101544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 101644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 101744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ imull(left, left, Immediate(right_value)); 101844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 10191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (right->IsStackSlot()) { 10201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ imull(left, ToOperand(right)); 10211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 10221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ imull(left, ToRegister(right)); 10231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 102544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (can_overflow) { 10261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(overflow, instr->environment()); 10271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 10301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Bail out if the result is supposed to be negative zero. 1031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 10321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(left, left); 1033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &done, Label::kNear); 10341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (right->IsConstantOperand()) { 10351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (ToInteger32(LConstantOperand::cast(right)) <= 0) { 10361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(no_condition, instr->environment()); 10371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (right->IsStackSlot()) { 10391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ or_(kScratchRegister, ToOperand(right)); 10401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(sign, instr->environment()); 10411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 10421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Test the non-zero operand for negative sign. 10431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ or_(kScratchRegister, ToRegister(right)); 10441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(sign, instr->environment()); 10451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 10471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 1049b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1050b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1051b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoBitI(LBitI* instr) { 10521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* left = instr->InputAt(0); 10531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* right = instr->InputAt(1); 10541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(left->Equals(instr->result())); 10551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(left->IsRegister()); 10561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (right->IsConstantOperand()) { 10581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int right_operand = ToInteger32(LConstantOperand::cast(right)); 10591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->op()) { 10601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_AND: 10611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ andl(ToRegister(left), Immediate(right_operand)); 10621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_OR: 10641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orl(ToRegister(left), Immediate(right_operand)); 10651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_XOR: 10671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ xorl(ToRegister(left), Immediate(right_operand)); 10681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 10701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 10711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (right->IsStackSlot()) { 10741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->op()) { 10751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_AND: 10761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ andl(ToRegister(left), ToOperand(right)); 10771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_OR: 10791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orl(ToRegister(left), ToOperand(right)); 10801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_XOR: 10821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ xorl(ToRegister(left), ToOperand(right)); 10831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 10851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 10861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 10891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(right->IsRegister()); 10901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->op()) { 10911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_AND: 10921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ andl(ToRegister(left), ToRegister(right)); 10931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_OR: 10951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orl(ToRegister(left), ToRegister(right)); 10961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_XOR: 10981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ xorl(ToRegister(left), ToRegister(right)); 10991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 11001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 11011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 11021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 11031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 11041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 11051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 1106b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1107b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1108b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoShiftI(LShiftI* instr) { 11091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* left = instr->InputAt(0); 11101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* right = instr->InputAt(1); 11111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(left->Equals(instr->result())); 11121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(left->IsRegister()); 11131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (right->IsRegister()) { 11141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(right).is(rcx)); 11151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 11161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->op()) { 11171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::SAR: 11181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ sarl_cl(ToRegister(left)); 11191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 11201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::SHR: 11211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ shrl_cl(ToRegister(left)); 11221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->can_deopt()) { 11231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(ToRegister(left), ToRegister(left)); 11241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(negative, instr->environment()); 11251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 11261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 11271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::SHL: 11281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ shll_cl(ToRegister(left)); 11291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 11301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 11311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 11321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 11331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 11341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 11351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int value = ToInteger32(LConstantOperand::cast(right)); 11361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); 11371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->op()) { 11381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::SAR: 11391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (shift_count != 0) { 11401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ sarl(ToRegister(left), Immediate(shift_count)); 11411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 11421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 11431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::SHR: 11441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (shift_count == 0 && instr->can_deopt()) { 11451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(ToRegister(left), ToRegister(left)); 11461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(negative, instr->environment()); 11471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 11481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ shrl(ToRegister(left), Immediate(shift_count)); 11491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 11501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 11511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::SHL: 11521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (shift_count != 0) { 11531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ shll(ToRegister(left), Immediate(shift_count)); 11541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 11551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 11561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 11571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 11581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 11591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 11601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1161b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1162b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1163b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1164b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoSubI(LSubI* instr) { 11651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* left = instr->InputAt(0); 11661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* right = instr->InputAt(1); 11671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(left->Equals(instr->result())); 11681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 11691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (right->IsConstantOperand()) { 11701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ subl(ToRegister(left), 11711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(ToInteger32(LConstantOperand::cast(right)))); 11721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (right->IsRegister()) { 11731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ subl(ToRegister(left), ToRegister(right)); 11741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 11751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ subl(ToRegister(left), ToOperand(right)); 11761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 11771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 11781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 11791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(overflow, instr->environment()); 11801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1181b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1182b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1183b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1184b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoConstantI(LConstantI* instr) { 1185b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(instr->result()->IsRegister()); 11868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Set(ToRegister(instr->result()), instr->value()); 1187b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1188b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1189b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1190b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoConstantD(LConstantD* instr) { 1191b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(instr->result()->IsDoubleRegister()); 1192b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch XMMRegister res = ToDoubleRegister(instr->result()); 1193b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch double v = instr->value(); 1194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch uint64_t int_val = BitCast<uint64_t, double>(v); 1195b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Use xor to produce +0.0 in a fast and compact way, but avoid to 1196b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // do so if the constant is -0.0. 1197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (int_val == 0) { 1198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(res, res); 1199b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 1200b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register tmp = ToRegister(instr->TempAt(0)); 1201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Set(tmp, int_val); 1202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(res, tmp); 1203b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1204b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1205b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1206b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1207b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoConstantT(LConstantT* instr) { 12081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->result()->IsRegister()); 1209b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ Move(ToRegister(instr->result()), instr->value()); 1210b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1211b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1212b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1213b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { 12141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 12151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register array = ToRegister(instr->InputAt(0)); 12161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, FieldOperand(array, JSArray::kLengthOffset)); 1217b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1218b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1219b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 122069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { 12211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 12221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register array = ToRegister(instr->InputAt(0)); 122369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movq(result, FieldOperand(array, FixedArrayBase::kLengthOffset)); 1224b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1225b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1226b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 12273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoElementsKind(LElementsKind* instr) { 12283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register result = ToRegister(instr->result()); 12293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register input = ToRegister(instr->InputAt(0)); 12303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 12313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Load map into |result|. 12323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(result, FieldOperand(input, HeapObject::kMapOffset)); 12333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Load the map's "bit field 2" into |result|. We only need the first byte. 12343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movzxbq(result, FieldOperand(result, Map::kBitField2Offset)); 12353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Retrieve elements_kind from bit field 2. 12363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ and_(result, Immediate(Map::kElementsKindMask)); 12373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ shr(result, Immediate(Map::kElementsKindShift)); 12383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 12393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 12403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1241b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoValueOf(LValueOf* instr) { 1242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register input = ToRegister(instr->InputAt(0)); 1243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 1244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(input.is(result)); 1245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 1246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If the object is a smi return the object. 1247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(input, &done, Label::kNear); 1248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If the object is not a value type, return the object. 1250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); 1251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &done, Label::kNear); 1252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, FieldOperand(input, JSValue::kValueOffset)); 1253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 1255b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1256b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1257b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1258b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoBitNotI(LBitNotI* instr) { 12591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* input = instr->InputAt(0); 12601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(input->Equals(instr->result())); 12611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ not_(ToRegister(input)); 1262b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1263b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1264b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1265b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoThrow(LThrow* instr) { 12661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(ToRegister(instr->InputAt(0))); 12671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallRuntime(Runtime::kThrow, 1, instr); 12681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_debug_code) { 12701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Comment("Unreachable code."); 12711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ int3(); 12721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1273b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1274b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1275b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1276b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoAddI(LAddI* instr) { 1277b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* left = instr->InputAt(0); 1278b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* right = instr->InputAt(1); 1279b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(left->Equals(instr->result())); 1280b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1281b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (right->IsConstantOperand()) { 1282b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ addl(ToRegister(left), 1283b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Immediate(ToInteger32(LConstantOperand::cast(right)))); 1284b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (right->IsRegister()) { 1285b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ addl(ToRegister(left), ToRegister(right)); 1286b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 1287b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ addl(ToRegister(left), ToOperand(right)); 1288b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1289b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1290b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1291b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch DeoptimizeIf(overflow, instr->environment()); 1292b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1293b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1294b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1295b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1296b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoArithmeticD(LArithmeticD* instr) { 1297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister left = ToDoubleRegister(instr->InputAt(0)); 1298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister right = ToDoubleRegister(instr->InputAt(1)); 1299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister result = ToDoubleRegister(instr->result()); 1300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // All operations except MOD are computed in-place. 1301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(instr->op() == Token::MOD || left.is(result)); 1302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch switch (instr->op()) { 1303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::ADD: 1304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ addsd(left, right); 1305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::SUB: 1307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ subsd(left, right); 1308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::MUL: 1310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mulsd(left, right); 1311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::DIV: 1313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ divsd(left, right); 1314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1315e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::MOD: 1316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ PrepareCallCFunction(2); 1317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movaps(xmm0, left); 1318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(right.is(xmm1)); 131944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CallCFunction( 132044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::double_fp_operation(Token::MOD, isolate()), 2); 1321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movaps(result, xmm0); 1323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch default: 1325e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UNREACHABLE(); 1326e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1327e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1328b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1329b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1330b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1331b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoArithmeticT(LArithmeticT* instr) { 1332b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(ToRegister(instr->InputAt(0)).is(rdx)); 1333b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(ToRegister(instr->InputAt(1)).is(rax)); 1334b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(ToRegister(instr->result()).is(rax)); 1335b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch BinaryOpStub stub(instr->op(), NO_OVERWRITE); 1337b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 133818a6f57610d404676fb0db2114fd7ad91e0402b0Ben Murdoch __ nop(); // Signals no inlined code. 1339b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1340b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1341b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1342b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochint LCodeGen::GetNextEmittedBlock(int block) { 1343b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = block + 1; i < graph()->blocks()->length(); ++i) { 1344b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LLabel* label = chunk_->GetLabel(i); 1345b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (!label->HasReplacement()) return i; 1346b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1347b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return -1; 1348b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1349b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1350b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1351b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::EmitBranch(int left_block, int right_block, Condition cc) { 13521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int next_block = GetNextEmittedBlock(current_block_); 13531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block right_block = chunk_->LookupDestination(right_block); 13541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block left_block = chunk_->LookupDestination(left_block); 13551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 13561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (right_block == left_block) { 13571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitGoto(left_block); 13581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (left_block == next_block) { 13591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); 13601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (right_block == next_block) { 13611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(cc, chunk_->GetAssemblyLabel(left_block)); 13621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 13631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(cc, chunk_->GetAssemblyLabel(left_block)); 13641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (cc != always) { 13651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ jmp(chunk_->GetAssemblyLabel(right_block)); 13661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 13671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1368b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1369b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1370b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1371b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoBranch(LBranch* instr) { 13721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 13731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 13741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 13753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Representation r = instr->hydrogen()->value()->representation(); 13761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (r.IsInteger32()) { 13771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->InputAt(0)); 13781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(reg, reg); 13791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, not_zero); 13801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (r.IsDouble()) { 13811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); 1382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(xmm0, xmm0); 13831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ucomisd(reg, xmm0); 13841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, not_equal); 13851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 13861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(r.IsTagged()); 13871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->InputAt(0)); 13883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HType type = instr->hydrogen()->value()->type(); 13891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (type.IsBoolean()) { 139044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareRoot(reg, Heap::kTrueValueRootIndex); 13911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, equal); 13921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (type.IsSmi()) { 13931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiCompare(reg, Smi::FromInt(0)); 13941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, not_equal); 13951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 13961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* true_label = chunk_->GetAssemblyLabel(true_block); 13971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* false_label = chunk_->GetAssemblyLabel(false_block); 13981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 139969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); 140069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Avoid deopts in the case where we've never executed this path before. 140169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); 140269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 140369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::UNDEFINED)) { 140469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // undefined -> false. 140569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); 140669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, false_label); 140769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 140869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::BOOLEAN)) { 140969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // true -> true. 141069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(reg, Heap::kTrueValueRootIndex); 141169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, true_label); 141269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // false -> false. 141369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(reg, Heap::kFalseValueRootIndex); 141469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, false_label); 141569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 141669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::NULL_TYPE)) { 141769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // 'null' -> false. 141869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(reg, Heap::kNullValueRootIndex); 141969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, false_label); 142069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 142169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 142269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::SMI)) { 142369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Smis: 0 -> false, all other -> true. 142469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Cmp(reg, Smi::FromInt(0)); 142569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, false_label); 142669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ JumpIfSmi(reg, true_label); 142769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (expected.NeedsMap()) { 142869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // If we need a map later and have a Smi -> deopt. 142969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ testb(reg, Immediate(kSmiTagMask)); 143069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(zero, instr->environment()); 143169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 143269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 143369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch const Register map = kScratchRegister; 143469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.NeedsMap()) { 143569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movq(map, FieldOperand(reg, HeapObject::kMapOffset)); 143669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 143769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.CanBeUndetectable()) { 143869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Undetectable -> false. 143969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ testb(FieldOperand(map, Map::kBitFieldOffset), 144069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Immediate(1 << Map::kIsUndetectable)); 144169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(not_zero, false_label); 144269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 144369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 144469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 144569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { 144669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // spec object -> true. 144769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); 144869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(above_equal, true_label); 144969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 145069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 145169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::STRING)) { 145269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // String value -> false iff empty. 145369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label not_string; 145469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); 145569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(above_equal, ¬_string, Label::kNear); 145669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmpq(FieldOperand(reg, String::kLengthOffset), Immediate(0)); 145769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(not_zero, true_label); 145869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ jmp(false_label); 145969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(¬_string); 146069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 146169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 146269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { 146369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // heap number -> false iff +0, -0, or NaN. 146469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label not_heap_number; 146569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); 146669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(not_equal, ¬_heap_number, Label::kNear); 146769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ xorps(xmm0, xmm0); 146869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); 146969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(zero, false_label); 147069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ jmp(true_label); 147169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(¬_heap_number); 147269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 147369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 147469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // We've seen something for the first time -> deopt. 147569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(no_condition, instr->environment()); 14761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 14771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1478b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1479b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1480b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 14813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::EmitGoto(int block) { 1482b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch block = chunk_->LookupDestination(block); 1483b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int next_block = GetNextEmittedBlock(current_block_); 1484b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (block != next_block) { 14853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(chunk_->GetAssemblyLabel(block)); 1486b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1487b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1488b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1489b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1490b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoGoto(LGoto* instr) { 14913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitGoto(instr->block_id()); 1492b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1493b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1494b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 14951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockinline Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { 1496b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Condition cond = no_condition; 1497b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch switch (op) { 1498b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::EQ: 1499b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::EQ_STRICT: 1500b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch cond = equal; 1501b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch break; 1502b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::LT: 1503b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch cond = is_unsigned ? below : less; 1504b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch break; 1505b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::GT: 1506b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch cond = is_unsigned ? above : greater; 1507b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch break; 1508b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::LTE: 1509b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch cond = is_unsigned ? below_equal : less_equal; 1510b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch break; 1511b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::GTE: 1512b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch cond = is_unsigned ? above_equal : greater_equal; 1513b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch break; 1514b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::IN: 1515b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::INSTANCEOF: 1516b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch default: 1517b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch UNREACHABLE(); 1518b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1519b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return cond; 1520b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1522b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1523b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { 15241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (right->IsConstantOperand()) { 15251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int32_t value = ToInteger32(LConstantOperand::cast(right)); 15261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (left->IsRegister()) { 15271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpl(ToRegister(left), Immediate(value)); 15281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 15291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpl(ToOperand(left), Immediate(value)); 15301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 15311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (right->IsRegister()) { 15321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpl(ToRegister(left), ToRegister(right)); 15331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 15341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpl(ToRegister(left), ToOperand(right)); 15351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1536b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1537b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1538b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1539b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 15401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* left = instr->InputAt(0); 15411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* right = instr->InputAt(1); 15421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 15431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 15441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 15451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->is_double()) { 15461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Don't base result on EFLAGS when a NaN is involved. Instead 15471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // jump to the false block. 15481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); 15491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); 15501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 15511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitCmpI(left, right); 15521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 15531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 15541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition cc = TokenToCondition(instr->op(), instr->is_double()); 15551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, cc); 1556b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1557b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1558b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 15593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { 15601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register left = ToRegister(instr->InputAt(0)); 15611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register right = ToRegister(instr->InputAt(1)); 15621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 15631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 15641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 15651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpq(left, right); 15661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, equal); 1567b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1568b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1569b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 15703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { 1571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left = ToRegister(instr->InputAt(0)); 1572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 15733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 15753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmpq(left, Immediate(instr->hydrogen()->right())); 1576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitBranch(true_block, false_block, equal); 1577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1580b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { 15811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->InputAt(0)); 15821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 15831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 15841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 15851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->representation().IsSpecialization() || 15861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block instr->hydrogen()->type().IsSmi()) { 15871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If the expression is known to untagged or smi, then it's definitely 15881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // not null, and it can't be a an undetectable object. 15891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Jump directly to the false block. 15901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitGoto(false_block); 15911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return; 15921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 15931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 15941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 15951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 159644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareRoot(reg, Heap::kNullValueRootIndex); 15971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->is_strict()) { 15981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, equal); 15991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 16001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* true_label = chunk_->GetAssemblyLabel(true_block); 16011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* false_label = chunk_->GetAssemblyLabel(false_block); 16021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, true_label); 160344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); 16041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, true_label); 16051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(reg, false_label); 16061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for undetectable objects by looking in the bit field in 16071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the map. The object has already been smi checked. 16081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register scratch = ToRegister(instr->TempAt(0)); 16091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 16101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(FieldOperand(scratch, Map::kBitFieldOffset), 16111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(1 << Map::kIsUndetectable)); 16121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, not_zero); 16131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1614b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1615b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1616b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1617b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochCondition LCodeGen::EmitIsObject(Register input, 1618b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* is_not_object, 1619b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* is_object) { 16201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!input.is(kScratchRegister)); 16211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, is_not_object); 16231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(input, Heap::kNullValueRootIndex); 16251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, is_object); 16261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); 16281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Undetectable objects behave like undefined. 16291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), 16301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(1 << Map::kIsUndetectable)); 16311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_zero, is_not_object); 16321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movzxbl(kScratchRegister, 16341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); 16353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 16361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(below, is_not_object); 16373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 1638b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return below_equal; 1639b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1640b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1641b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1642b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { 16431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->InputAt(0)); 16441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 16461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 16471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* true_label = chunk_->GetAssemblyLabel(true_block); 16481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* false_label = chunk_->GetAssemblyLabel(false_block); 16491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition true_cond = EmitIsObject(reg, false_label, true_label); 16511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, true_cond); 1653b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1654b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1655b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1656b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 16571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 16581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 16591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition is_smi; 16611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->InputAt(0)->IsRegister()) { 16621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 16631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block is_smi = masm()->CheckSmi(input); 16641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 16651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand input = ToOperand(instr->InputAt(0)); 16661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block is_smi = masm()->CheckSmi(input); 16671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 16681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, is_smi); 16691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 16701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { 1673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register input = ToRegister(instr->InputAt(0)); 1674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register temp = ToRegister(instr->TempAt(0)); 1675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 1677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); 1680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); 1681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testb(FieldOperand(temp, Map::kBitFieldOffset), 1682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Immediate(1 << Map::kIsUndetectable)); 1683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitBranch(true_block, false_block, not_zero); 1684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 16873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic InstanceType TestType(HHasInstanceTypeAndBranch* instr) { 16881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block InstanceType from = instr->from(); 16891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block InstanceType to = instr->to(); 16901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (from == FIRST_TYPE) return to; 16911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(from == to || to == LAST_TYPE); 16921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return from; 16931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 16941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { 16971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block InstanceType from = instr->from(); 16981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block InstanceType to = instr->to(); 16991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (from == to) return equal; 17001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (to == LAST_TYPE) return above_equal; 17011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (from == FIRST_TYPE) return below_equal; 17021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 17031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return equal; 1704b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1705b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1706b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1707b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 17081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 17091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 17111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 17121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* false_label = chunk_->GetAssemblyLabel(false_block); 17141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, false_label); 17161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); 17181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); 1719b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1720b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1721b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1722e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { 1723e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register input = ToRegister(instr->InputAt(0)); 1724e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 1725e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1726e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (FLAG_debug_code) { 1727e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ AbortIfNotString(input); 1728e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1729e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1730e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movl(result, FieldOperand(input, String::kHashFieldOffset)); 1731e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(String::kHashShift >= kSmiTagSize); 1732e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ IndexFromHash(result, result); 1733e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 1734e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1735e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1736b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoHasCachedArrayIndexAndBranch( 1737b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LHasCachedArrayIndexAndBranch* instr) { 17381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 17391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 17411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 17421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(FieldOperand(input, String::kHashFieldOffset), 17441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(String::kContainsCachedArrayIndexMask)); 1745e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitBranch(true_block, false_block, equal); 1746b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1747b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1748b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 17491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Branches to a label or falls through with the answer in the z flag. 17501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Trashes the temp register and possibly input (if it and temp are aliased). 1751b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::EmitClassOfTest(Label* is_true, 1752b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* is_false, 17531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<String> class_name, 1754b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register input, 17551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register temp) { 17561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, is_false); 17573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp); 17581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(below, is_false); 17591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Map is now in temp. 17611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Functions have class 'Function'. 17623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpInstanceType(temp, FIRST_CALLABLE_SPEC_OBJECT_TYPE); 17631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (class_name->IsEqualTo(CStrVector("Function"))) { 17643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above_equal, is_true); 17651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 17663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above_equal, is_false); 17671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 17681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check if the constructor in the map is a function. 17701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(temp, FieldOperand(temp, Map::kConstructorOffset)); 17711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last type and 17733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after 17743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter. 17753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE); 17763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE == 17773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1); 17781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Objects with a non-function constructor have class 'Object'. 17801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CmpObjectType(temp, JS_FUNCTION_TYPE, kScratchRegister); 17811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (class_name->IsEqualTo(CStrVector("Object"))) { 17821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_equal, is_true); 17831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 17841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_equal, is_false); 17851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 17861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // temp now contains the constructor function. Grab the 17881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // instance class name from there. 17891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset)); 17901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(temp, FieldOperand(temp, 17911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SharedFunctionInfo::kInstanceClassNameOffset)); 17921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The class name we are testing against is a symbol because it's a literal. 17931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The name in the constructor is a symbol because of the way the context is 17941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // booted. This routine isn't expected to work for random API-created 17951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // classes and it doesn't have to because you can't access it with natives 17961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // syntax. Since both sides are symbols it is sufficient to use an identity 17971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // comparison. 17981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(class_name->IsSymbol()); 17991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Cmp(temp, class_name); 18001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // End with the answer in the z flag. 1801b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1802b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1803b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1804b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 18051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 18061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register temp = ToRegister(instr->TempAt(0)); 18071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<String> class_name = instr->hydrogen()->class_name(); 18081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 18101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 18111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* true_label = chunk_->GetAssemblyLabel(true_block); 18131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* false_label = chunk_->GetAssemblyLabel(false_block); 18141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitClassOfTest(true_label, false_label, class_name, input, temp); 18161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, equal); 1818b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1819b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1820b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1821b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { 18221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->InputAt(0)); 18231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = instr->true_block_id(); 18241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = instr->false_block_id(); 18251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); 18271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, equal); 1828b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1829b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1830b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1831b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoInstanceOf(LInstanceOf* instr) { 1832e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InstanceofStub stub(InstanceofStub::kNoFlags); 1833e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(ToRegister(instr->InputAt(0))); 1834e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(ToRegister(instr->InputAt(1))); 1835e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 1836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label true_value, done; 1837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testq(rax, rax); 1838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &true_value, Label::kNear); 1839e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); 1840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 1841e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&true_value); 1842e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); 1843e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 1844b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1845b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1846b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1847b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 1848e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch class DeferredInstanceOfKnownGlobal: public LDeferredCode { 1849e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public: 1850e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeferredInstanceOfKnownGlobal(LCodeGen* codegen, 1851e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LInstanceOfKnownGlobal* instr) 1852e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch : LDeferredCode(codegen), instr_(instr) { } 1853e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual void Generate() { 185444f0eee88ff00398ff7f715fab053374d808c90dSteve Block codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_); 1855e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1856e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 185744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* map_check() { return &map_check_; } 185844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private: 1860e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LInstanceOfKnownGlobal* instr_; 186144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label map_check_; 1862e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch }; 1863e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1864e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1865e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeferredInstanceOfKnownGlobal* deferred; 1866e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch deferred = new DeferredInstanceOfKnownGlobal(this, instr); 1867e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 186844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label done, false_result; 1869e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register object = ToRegister(instr->InputAt(0)); 1870e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1871e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // A Smi is not an instance of anything. 1872e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(object, &false_result); 1873e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 187444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // This is the inlined call site instanceof cache. The two occurences of the 187544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // hole value will be patched to the last map/result pair generated by the 187644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // instanceof stub. 1877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label cache_miss; 187844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Use a temp register to avoid memory operands with variable lengths. 187944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register map = ToRegister(instr->TempAt(0)); 188044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); 188144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(deferred->map_check()); // Label for calculating code patching. 188244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(kScratchRegister, factory()->the_hole_value(), 188344f0eee88ff00398ff7f715fab053374d808c90dSteve Block RelocInfo::EMBEDDED_OBJECT); 188444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpq(map, kScratchRegister); // Patched to cached map. 1885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &cache_miss, Label::kNear); 188644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Patched to load either true or false. 188744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); 188844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG 188944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the code size between patch label and patch sites is invariant. 189044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label end_of_patched_code; 189144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&end_of_patched_code); 189244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(true); 189344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 189444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&done); 189544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 189644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The inlined call site cache did not match. Check for null and string 189744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // before calling the deferred code. 189844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&cache_miss); // Null is not an instance of anything. 1899e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(object, Heap::kNullValueRootIndex); 1900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &false_result, Label::kNear); 1901e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1902e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // String values are not instances of anything. 1903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfNotString(object, kScratchRegister, deferred->entry()); 1904e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&false_result); 1906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); 1907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(deferred->exit()); 190944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 1910b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1911b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1912b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 191344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, 191444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* map_check) { 19158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch { 19168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 19178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( 19188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); 19198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch InstanceofStub stub(flags); 1920e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 19218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ push(ToRegister(instr->InputAt(0))); 19228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Push(instr->function()); 19238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 19248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static const int kAdditionalDelta = 10; 19258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int delta = 19268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; 19278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(delta >= 0); 19288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ push_imm32(delta); 19298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 19308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // We are pushing three values on the stack but recording a 19318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // safepoint with two arguments because stub is going to 19328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // remove the third argument from the stack before jumping 19338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // to instanceof builtin on the slow path. 19348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallCodeGeneric(stub.GetCode(), 19358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::CODE_TARGET, 19368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr, 19378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RECORD_SAFEPOINT_WITH_REGISTERS, 19388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2); 19398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(delta == masm_->SizeOfCodeGeneratedSince(map_check)); 19408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Move result to a register that survives the end of the 19418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // PushSafepointRegisterScope. 19428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(kScratchRegister, rax); 19438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testq(kScratchRegister, kScratchRegister); 1945e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label load_false; 1946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label done; 1947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(not_zero, &load_false); 1948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(rax, Heap::kTrueValueRootIndex); 1949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&done); 1950e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&load_false); 1951e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(rax, Heap::kFalseValueRootIndex); 1952e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 1953b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1954b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1955b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1956b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCmpT(LCmpT* instr) { 19571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Token::Value op = instr->op(); 19581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 19591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Code> ic = CompareIC::GetUninitialized(op); 19601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(ic, RelocInfo::CODE_TARGET, instr); 19611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 19621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition condition = TokenToCondition(op, false); 19631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (op == Token::GT || op == Token::LTE) { 19641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block condition = ReverseCondition(condition); 19651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label true_value, done; 19671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testq(rax, rax); 1968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(condition, &true_value, Label::kNear); 19691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); 1970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 19711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&true_value); 19721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); 19731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 1974b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1975b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1976b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1977b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoReturn(LReturn* instr) { 1978b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (FLAG_trace) { 1979b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Preserve the return value on the stack and rely on the runtime 1980b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // call to return the value in the same register. 1981b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ push(rax); 1982b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ CallRuntime(Runtime::kTraceExit, 1); 1983b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1984b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ movq(rsp, rbp); 1985b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ pop(rbp); 1986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret((GetParameterCount() + 1) * kPointerSize, rcx); 1987b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1988b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1989b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 19908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { 19911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 19921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (result.is(rax)) { 19931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ load_rax(instr->hydrogen()->cell().location(), 19941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RelocInfo::GLOBAL_PROPERTY_CELL); 19951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 19961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, instr->hydrogen()->cell(), RelocInfo::GLOBAL_PROPERTY_CELL); 19971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, Operand(result, 0)); 19981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 19991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->check_hole_value()) { 20001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 20011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(equal, instr->environment()); 20021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2003b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2004b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2005b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 20068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { 20078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(ToRegister(instr->global_object()).is(rax)); 20088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(ToRegister(instr->result()).is(rax)); 20098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 20108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Move(rcx, instr->name()); 20118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : 20128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::CODE_TARGET_CONTEXT; 20138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 20148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallCode(ic, mode, instr); 20158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 20168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 20178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 20188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { 20191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register value = ToRegister(instr->InputAt(0)); 20201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register temp = ToRegister(instr->TempAt(0)); 20211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!value.is(temp)); 20221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool check_hole = instr->hydrogen()->check_hole_value(); 20231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!check_hole && value.is(rax)) { 20241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ store_rax(instr->hydrogen()->cell().location(), 20251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RelocInfo::GLOBAL_PROPERTY_CELL); 20261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return; 20271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 20281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If the cell we are storing to contains the hole it could have 20291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // been deleted from the property dictionary. In that case, we need 20301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to update the property details in the property dictionary to mark 20311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // it as no longer deleted. We deoptimize in that case. 20321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(temp, instr->hydrogen()->cell(), RelocInfo::GLOBAL_PROPERTY_CELL); 20331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (check_hole) { 20341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(Operand(temp, 0), Heap::kTheHoleValueRootIndex); 20351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(equal, instr->environment()); 20361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 20371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(Operand(temp, 0), value); 2038b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2039b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2040b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 20418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { 20428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(ToRegister(instr->global_object()).is(rdx)); 20438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(ToRegister(instr->value()).is(rax)); 20448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 20458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Move(rcx, instr->name()); 20468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<Code> ic = instr->strict_mode() 20478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ? isolate()->builtins()->StoreIC_Initialize_Strict() 20488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : isolate()->builtins()->StoreIC_Initialize(); 20498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); 20508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 20518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 20528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2053b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2054e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register context = ToRegister(instr->context()); 2055e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 2056e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, ContextOperand(context, instr->slot_index())); 2057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2058e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2059e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2060e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 2061e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register context = ToRegister(instr->context()); 2062e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register value = ToRegister(instr->value()); 2063e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(ContextOperand(context, instr->slot_index()), value); 2064e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->needs_write_barrier()) { 2065e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int offset = Context::SlotOffset(instr->slot_index()); 2066e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register scratch = ToRegister(instr->TempAt(0)); 2067e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ RecordWrite(context, offset, value, scratch); 2068e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2069b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2070b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2071b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2072b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 20731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register object = ToRegister(instr->InputAt(0)); 20741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 20751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->is_in_object()) { 20761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); 20771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 20781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); 20791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, FieldOperand(result, instr->hydrogen()->offset())); 20801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2081b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2082b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2083b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::EmitLoadFieldOrConstantFunction(Register result, 2085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register object, 2086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Map> type, 2087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<String> name) { 208844f0eee88ff00398ff7f715fab053374d808c90dSteve Block LookupResult lookup; 208944f0eee88ff00398ff7f715fab053374d808c90dSteve Block type->LookupInDescriptors(NULL, *name, &lookup); 2090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(lookup.IsProperty() && 2091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION)); 2092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (lookup.type() == FIELD) { 2093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int index = lookup.GetLocalFieldIndexFromMap(*type); 2094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int offset = index * kPointerSize; 2095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (index < 0) { 2096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Negative property indices are in-object properties, indexed 2097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // from the end of the fixed part of the object. 2098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(result, FieldOperand(object, offset + type->instance_size())); 2099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Non-negative property indices are in the properties array. 2101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); 2102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(result, FieldOperand(result, offset + FixedArray::kHeaderSize)); 2103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 210444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 2105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type)); 2106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LoadHeapObject(result, Handle<HeapObject>::cast(function)); 210744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 210844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 210944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 211044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 211144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { 211244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register object = ToRegister(instr->object()); 211344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result = ToRegister(instr->result()); 211444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 211544f0eee88ff00398ff7f715fab053374d808c90dSteve Block int map_count = instr->hydrogen()->types()->length(); 211644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<String> name = instr->hydrogen()->name(); 211744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 211844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (map_count == 0) { 211944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(instr->hydrogen()->need_generic()); 212044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(rcx, instr->hydrogen()->name()); 212144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 212244f0eee88ff00398ff7f715fab053374d808c90dSteve Block CallCode(ic, RelocInfo::CODE_TARGET, instr); 212344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 2124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 212544f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < map_count - 1; ++i) { 212644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Map> map = instr->hydrogen()->types()->at(i); 2127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label next; 212844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); 2129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &next, Label::kNear); 2130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitLoadFieldOrConstantFunction(result, object, map, name); 2131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 213244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&next); 213344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 213444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Map> map = instr->hydrogen()->types()->last(); 213544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); 213644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->need_generic()) { 2137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label generic; 2138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &generic, Label::kNear); 2139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitLoadFieldOrConstantFunction(result, object, map, name); 2140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 214144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&generic); 214244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(rcx, instr->hydrogen()->name()); 214344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 214444f0eee88ff00398ff7f715fab053374d808c90dSteve Block CallCode(ic, RelocInfo::CODE_TARGET, instr); 214544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 214644f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(not_equal, instr->environment()); 2147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitLoadFieldOrConstantFunction(result, object, map, name); 214844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 214944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 215044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 215144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 215244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 215344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2154b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { 21551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->object()).is(rax)); 21561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 21571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 21581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(rcx, instr->name()); 215944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 21601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(ic, RelocInfo::CODE_TARGET, instr); 2161b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2162b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2163b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2164b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { 21651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register function = ToRegister(instr->function()); 21661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 21671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 21681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the function really is a function. 21691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CmpObjectType(function, JS_FUNCTION_TYPE, result); 21701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_equal, instr->environment()); 21711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 21721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check whether the function has an instance prototype. 2173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label non_instance; 21741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(FieldOperand(result, Map::kBitFieldOffset), 21751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(1 << Map::kHasNonInstancePrototype)); 2176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &non_instance, Label::kNear); 21771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 21781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Get the prototype or initial map from the function. 21791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, 21801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 21811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 21821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the function has a prototype or an initial map. 21831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 21841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(equal, instr->environment()); 21851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 21861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If the function does not have an initial map, we're done. 2187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 21881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CmpObjectType(result, MAP_TYPE, kScratchRegister); 2189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &done, Label::kNear); 21901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 21911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Get the prototype from the initial map. 21921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, FieldOperand(result, Map::kPrototypeOffset)); 2193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 21941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 21951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Non-instance prototype: Fetch prototype from constructor field 21961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // in the function's map. 21971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&non_instance); 21981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, FieldOperand(result, Map::kConstructorOffset)); 21991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 22001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // All done. 22011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 2202b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2203b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2204b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2205b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadElements(LLoadElements* instr) { 22061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 22071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 22081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, FieldOperand(input, JSObject::kElementsOffset)); 22091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_debug_code) { 22103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label done, ok, fail; 221144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), 221244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::kFixedArrayMapRootIndex); 2213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &done, Label::kNear); 221444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), 221544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::kFixedCOWArrayMapRootIndex); 2216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &done, Label::kNear); 221744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register temp((result.is(rax)) ? rbx : rax); 221844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ push(temp); 221944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(temp, FieldOperand(result, HeapObject::kMapOffset)); 22203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movzxbq(temp, FieldOperand(temp, Map::kBitField2Offset)); 22213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ and_(temp, Immediate(Map::kElementsKindMask)); 22223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ shr(temp, Immediate(Map::kElementsKindShift)); 2223589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ cmpl(temp, Immediate(FAST_ELEMENTS)); 22243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(equal, &ok, Label::kNear); 2225589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ cmpl(temp, Immediate(FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND)); 22263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(less, &fail, Label::kNear); 2227589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ cmpl(temp, Immediate(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND)); 22283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(less_equal, &ok, Label::kNear); 22293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&fail); 22303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Abort("Check for fast or external elements failed"); 22313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&ok); 223244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ pop(temp); 22331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 22341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 22351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 22361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 22371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 223844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoLoadExternalArrayPointer( 223944f0eee88ff00398ff7f715fab053374d808c90dSteve Block LLoadExternalArrayPointer* instr) { 22401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 22411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 224244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(result, FieldOperand(input, 224344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalPixelArray::kExternalPointerOffset)); 2244b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2245b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2246b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2247b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { 2248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register arguments = ToRegister(instr->arguments()); 2249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register length = ToRegister(instr->length()); 2250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 2251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->index()->IsRegister()) { 2253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ subl(length, ToRegister(instr->index())); 2254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ subl(length, ToOperand(instr->index())); 2256e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(below_equal, instr->environment()); 2258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // There are two words between the frame pointer and the last argument. 2260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Subtracting from length accounts for one of them add one more. 2261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, Operand(arguments, length, times_pointer_size, kPointerSize)); 2262b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2263b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2264b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2265b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { 22661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 22671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 22681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Load the result. 226969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movq(result, 227069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch BuildFastArrayOperand(instr->elements(), instr->key(), 2271589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch FAST_ELEMENTS, 227269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch FixedArray::kHeaderSize - kHeapObjectTag)); 22731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 22741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for the hole value. 2275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 2276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 2277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(equal, instr->environment()); 2278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 22823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoLoadKeyedFastDoubleElement( 22833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LLoadKeyedFastDoubleElement* instr) { 22843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch XMMRegister result(ToDoubleRegister(instr->result())); 22853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 22863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 22873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + 22883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sizeof(kHoleNanLower32); 22893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand hole_check_operand = BuildFastArrayOperand( 22903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->elements(), 22913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->key(), 2292589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch FAST_DOUBLE_ELEMENTS, 22933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch offset); 22943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); 22953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DeoptimizeIf(equal, instr->environment()); 22963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 22973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 22983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand double_load_operand = BuildFastArrayOperand( 2299589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS, 23003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedDoubleArray::kHeaderSize - kHeapObjectTag); 23013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movsd(result, double_load_operand); 23023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 23033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 23043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 23053fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochOperand LCodeGen::BuildFastArrayOperand( 230669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch LOperand* elements_pointer, 23073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LOperand* key, 2308589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind, 23093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t offset) { 231069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register elements_pointer_reg = ToRegister(elements_pointer); 23113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int shift_size = ElementsKindToShiftSize(elements_kind); 2312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (key->IsConstantOperand()) { 2313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int constant_value = ToInteger32(LConstantOperand::cast(key)); 2314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (constant_value & 0xF0000000) { 2315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Abort("array index constant value too big"); 2316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 231769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return Operand(elements_pointer_reg, 23183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch constant_value * (1 << shift_size) + offset); 2319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); 232169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return Operand(elements_pointer_reg, ToRegister(key), 23223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch scale_factor, offset); 2323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 23241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 23251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 23261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 232744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoLoadKeyedSpecializedArrayElement( 232844f0eee88ff00398ff7f715fab053374d808c90dSteve Block LLoadKeyedSpecializedArrayElement* instr) { 2329589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = instr->elements_kind(); 23303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand operand(BuildFastArrayOperand(instr->external_pointer(), 23313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->key(), elements_kind, 0)); 2332589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 233344f0eee88ff00398ff7f715fab053374d808c90dSteve Block XMMRegister result(ToDoubleRegister(instr->result())); 2334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movss(result, operand); 233544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cvtss2sd(result, result); 2336589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 2337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsd(ToDoubleRegister(instr->result()), operand); 233844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 233944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result(ToRegister(instr->result())); 23403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 2341589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 2342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsxbq(result, operand); 234344f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2344589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 2345589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 2346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movzxbq(result, operand); 234744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 2349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsxwq(result, operand); 235044f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2351589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 2352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movzxwq(result, operand); 235344f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2354589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 2355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsxlq(result, operand); 235644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2357589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 2358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movl(result, operand); 235944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ testl(result, result); 236044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // TODO(danno): we could be more clever here, perhaps having a special 236144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // version of the stub that detects if the overflow case actually 236244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // happens, and generate code that returns a double rather than int. 236344f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(negative, instr->environment()); 236444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2365589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 2366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 2367589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 2368589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 2369589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 2370589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 237144f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 237244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 237344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 237444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 2375b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2376b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2377b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2378b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { 2379e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->object()).is(rdx)); 2380e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->key()).is(rax)); 2381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 238244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2383e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 2384b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2385b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2386b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2387b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { 2388e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 2389e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2390e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check for arguments adapter frame. 2391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, adapted; 2392e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 239344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(Operand(result, StandardFrameConstants::kContextOffset), 239444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &adapted, Label::kNear); 2396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2397e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // No arguments adaptor frame. 2398e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, rbp); 2399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 2400e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2401e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Arguments adaptor frame present. 2402e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&adapted); 2403e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2405e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Result is the frame pointer for the frame if not adapted and for the real 2406e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // frame below the adaptor frame if adapted. 2407e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 2408b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2409b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2410b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2411b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { 2412e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 2413e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 2415e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If no arguments adaptor frame the number of arguments is fixed. 2417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->InputAt(0)->IsRegister()) { 2418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmpq(rbp, ToRegister(instr->InputAt(0))); 2419e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2420e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmpq(rbp, ToOperand(instr->InputAt(0))); 2421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 24228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movl(result, Immediate(scope()->num_parameters())); 2423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &done, Label::kNear); 2424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Arguments adaptor frame present. Get argument length from there. 2426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 24278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ SmiToInteger32(result, 24288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Operand(result, 24298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ArgumentsAdaptorFrameConstants::kLengthOffset)); 2430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2431e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Argument length is in result register. 2432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 2433b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2434b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2435b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2436b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoApplyArguments(LApplyArguments* instr) { 2437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register receiver = ToRegister(instr->receiver()); 2438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register function = ToRegister(instr->function()); 2439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register length = ToRegister(instr->length()); 2440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register elements = ToRegister(instr->elements()); 2441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(receiver.is(rax)); // Used for parameter count. 2442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(function.is(rdi)); // Required by InvokeFunction. 2443e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->result()).is(rax)); 2444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 24453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // If the receiver is null or undefined, we have to pass the global 24463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // object as a receiver to normal functions. Values have to be 24473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // passed unchanged to builtins and strict-mode functions. 2448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label global_object, receiver_ok; 24493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 24503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Do not transform the receiver to object for strict mode 24513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // functions. 24523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(kScratchRegister, 24533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); 24543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ testb(FieldOperand(kScratchRegister, 24553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SharedFunctionInfo::kStrictModeByteOffset), 24563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte)); 24573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(not_equal, &receiver_ok, Label::kNear); 24583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 24593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Do not transform the receiver to object for builtins. 24603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ testb(FieldOperand(kScratchRegister, 24613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SharedFunctionInfo::kNativeByteOffset), 24623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); 24633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(not_equal, &receiver_ok, Label::kNear); 24643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 24653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Normal function. Replace undefined or null with global receiver. 2466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(receiver, Heap::kNullValueRootIndex); 2467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &global_object, Label::kNear); 2468e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); 2469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &global_object, Label::kNear); 2470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The receiver should be a JS object. 2472e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Condition is_smi = __ CheckSmi(receiver); 2473e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(is_smi, instr->environment()); 24743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); 2475e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(below, instr->environment()); 2476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&receiver_ok, Label::kNear); 2477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2478e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&global_object); 2479e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // TODO(kmillikin): We have a hydrogen value for the global object. See 2480e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // if it's better to use it than to explicitly fetch it from the context 2481e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // here. 2482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(receiver, ContextOperand(rsi, Context::GLOBAL_INDEX)); 2483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(receiver, 2484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset)); 2485e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&receiver_ok); 2486e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2487e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy the arguments to this function possibly from the 2488e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // adaptor frame below it. 2489e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const uint32_t kArgumentsLimit = 1 * KB; 2490e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmpq(length, Immediate(kArgumentsLimit)); 2491e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(above, instr->environment()); 2492e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2493e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(receiver); 2494e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(receiver, length); 2495e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Loop through the arguments pushing them onto the execution 2497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // stack. 2498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label invoke, loop; 2499e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // length is a small non-negative integer, due to the test above. 2500e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testl(length, length); 2501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &invoke, Label::kNear); 2502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&loop); 2503e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); 2504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ decl(length); 2505e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(not_zero, &loop); 2506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Invoke the function. 2508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&invoke); 2509e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 2510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LPointerMap* pointers = instr->pointer_map(); 2511e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LEnvironment* env = instr->deoptimization_environment(); 2512e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch RecordPosition(pointers->position()); 2513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch RegisterEnvironmentForDeoptimization(env); 2514e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch SafepointGenerator safepoint_generator(this, 2515e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pointers, 251644f0eee88ff00398ff7f715fab053374d808c90dSteve Block env->deoptimization_index()); 2517e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch v8::internal::ParameterCount actual(rax); 2518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, actual, CALL_FUNCTION, 2519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch safepoint_generator, CALL_AS_METHOD); 2520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2522b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2523b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2524b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoPushArgument(LPushArgument* instr) { 25251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* argument = instr->InputAt(0); 2526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(argument); 25271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 25281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 25291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 25303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoThisFunction(LThisFunction* instr) { 25313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register result = ToRegister(instr->result()); 25323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 25333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 25343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 25353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 25361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::DoContext(LContext* instr) { 25371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 2538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(result, rsi); 2539b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2540b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2541b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoOuterContext(LOuterContext* instr) { 2543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register context = ToRegister(instr->context()); 2544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 2545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, 25463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); 2547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2550b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoGlobalObject(LGlobalObject* instr) { 25511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 25521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, GlobalObjectOperand()); 2553b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2554b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2555b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2556b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { 255744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register global = ToRegister(instr->global()); 25581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 255944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset)); 2560b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2561b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2562b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2563b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::CallKnownFunction(Handle<JSFunction> function, 2564b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int arity, 2565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LInstruction* instr, 2566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind) { 25671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Change context if needed. 25681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool change_context = 2569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (info()->closure()->context() != function->context()) || 25701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block scope()->contains_with() || 25711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (scope()->num_heap_slots() > 0); 25721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (change_context) { 25731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 25741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 25751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 25761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Set rax to arguments count if adaption is not needed. Assumes that rax 25771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // is available to write to at this point. 25781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!function->NeedsArgumentsAdaption()) { 25791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Set(rax, arity); 25801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 25811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 25821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LPointerMap* pointers = instr->pointer_map(); 25831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RecordPosition(pointers->position()); 25841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 25851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Invoke function. 2586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SetCallKind(rcx, call_kind); 2587e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (*function == *info()->closure()) { 25881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CallSelf(); 25891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 25901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); 25911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 25921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 25931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Setup deoptimization. 25948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT, 0); 25951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 25961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Restore context. 25971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2598b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2599b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2600b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2601b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { 26021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 26031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(rdi, instr->function()); 2604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKnownFunction(instr->function(), 2605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->arity(), 2606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr, 2607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CALL_AS_METHOD); 2608b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2609b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2610b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2611b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { 2612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register input_reg = ToRegister(instr->InputAt(0)); 2613e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 2614e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Heap::kHeapNumberMapRootIndex); 2615e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(not_equal, instr->environment()); 2616e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label done; 2618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register tmp = input_reg.is(rax) ? rcx : rax; 2619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; 2620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2621e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Preserve the value of all registers. 26228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 2623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label negative; 2625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movl(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 2626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check the sign of the argument. If the argument is positive, just 2627e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // return it. We do not need to patch the stack since |input| and 2628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // |result| are the same register and |input| will be restored 2629e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // unchanged by popping safepoint registers. 2630e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testl(tmp, Immediate(HeapNumber::kSignMask)); 2631e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(not_zero, &negative); 2632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&done); 2633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&negative); 2635e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2636e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label allocated, slow; 2637e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ AllocateHeapNumber(tmp, tmp2, &slow); 2638e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&allocated); 2639e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Slow case: Call the runtime system to do the number allocation. 2641e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&slow); 2642e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 26438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); 2644e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Set the pointer to the new heap number in tmp. 2645e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!tmp.is(rax)) { 2646e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(tmp, rax); 2647e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2648e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2649e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Restore input_reg after call to runtime. 2650e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadFromSafepointRegisterSlot(input_reg, input_reg); 2651e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2652e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&allocated); 2653e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); 2654e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ shl(tmp2, Immediate(1)); 2655e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ shr(tmp2, Immediate(1)); 2656e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); 2657e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ StoreToSafepointRegisterSlot(input_reg, tmp); 2658e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2659e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 2660e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2661e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2662e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2663e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { 2664e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register input_reg = ToRegister(instr->InputAt(0)); 2665e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testl(input_reg, input_reg); 2666e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label is_positive; 2667e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(not_sign, &is_positive); 2668e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ negl(input_reg); // Sets flags. 2669e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(negative, instr->environment()); 2670e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&is_positive); 2671b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2672b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2673b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2674b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { 2675e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Class for deferred case. 2676e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { 2677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public: 2678e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, 2679e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LUnaryMathOperation* instr) 2680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch : LDeferredCode(codegen), instr_(instr) { } 2681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual void Generate() { 2682e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); 2683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2684e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private: 2685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LUnaryMathOperation* instr_; 2686e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch }; 2687e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2688e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(instr->InputAt(0)->Equals(instr->result())); 2689e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Representation r = instr->hydrogen()->value()->representation(); 2690e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2691e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (r.IsDouble()) { 2692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister scratch = xmm0; 2693e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(scratch, scratch); 2695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ subsd(scratch, input_reg); 2696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ andpd(input_reg, scratch); 2697e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (r.IsInteger32()) { 2698e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitIntegerMathAbs(instr); 2699e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { // Tagged case. 2700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeferredMathAbsTaggedHeapNumber* deferred = 2701e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch new DeferredMathAbsTaggedHeapNumber(this, instr); 2702e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register input_reg = ToRegister(instr->InputAt(0)); 2703e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Smi check. 2704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfNotSmi(input_reg, deferred->entry()); 27057d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch __ SmiToInteger32(input_reg, input_reg); 2706e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitIntegerMathAbs(instr); 27077d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch __ Integer32ToSmi(input_reg, input_reg); 2708e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(deferred->exit()); 2709e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2710b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2711b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2712b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2713b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { 2714e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister xmm_scratch = xmm0; 2715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register output_reg = ToRegister(instr->result()); 2716e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 271769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label done; 2718e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(SSE4_1)) { 2720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(SSE4_1); 2721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 2722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Deoptimize if minus zero. 2723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(output_reg, input_reg); 2724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subq(output_reg, Immediate(1)); 2725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(overflow, instr->environment()); 2726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); 2728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvttsd2si(output_reg, xmm_scratch); 2729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpl(output_reg, Immediate(0x80000000)); 2730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(equal, instr->environment()); 2731e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 273269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Deoptimize on negative inputs. 2733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(xmm_scratch, xmm_scratch); // Zero the register. 2734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ucomisd(input_reg, xmm_scratch); 273569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(below, instr->environment()); 2736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 273769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Check for negative zero. 273869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label positive_sign; 273969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(above, &positive_sign, Label::kNear); 274069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movmskpd(output_reg, input_reg); 274169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ testq(output_reg, Immediate(1)); 274269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(not_zero, instr->environment()); 274369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Set(output_reg, 0); 274469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ jmp(&done); 274569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&positive_sign); 2746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 27478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use truncating instruction (OK because input is positive). 2749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvttsd2si(output_reg, input_reg); 2750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Overflow is signalled with minint. 2752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpl(output_reg, Immediate(0x80000000)); 2753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(equal, instr->environment()); 2754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 275569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&done); 2756b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2757b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2758b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2759b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathRound(LUnaryMathOperation* instr) { 2760e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const XMMRegister xmm_scratch = xmm0; 2761e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register output_reg = ToRegister(instr->result()); 2762e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2763e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 2765e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // xmm_scratch = 0.5 2766e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); 2767e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(xmm_scratch, kScratchRegister); 2768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label below_half; 2769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ucomisd(xmm_scratch, input_reg); 2770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If input_reg is NaN, this doesn't jump. 2771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above, &below_half, Label::kNear); 2772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // input = input + 0.5 2773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This addition might give a result that isn't the correct for 2774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // rounding, due to loss of precision, but only for a number that's 2775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // so big that the conversion below will overflow anyway. 2776692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ addsd(xmm_scratch, input_reg); 2777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute Math.floor(input). 2778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use truncating instruction (OK because input is positive). 2779692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ cvttsd2si(output_reg, xmm_scratch); 2780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Overflow is signalled with minint. 2781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpl(output_reg, Immediate(0x80000000)); 2782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(equal, instr->environment()); 2783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done); 2784e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&below_half); 2786e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 2787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Bailout if negative (including -0). 2788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(output_reg, input_reg); 2789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testq(output_reg, output_reg); 2790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(negative, instr->environment()); 2791e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Bailout if below -0.5, otherwise round to (positive) zero, even 2793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // if negative. 2794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // xmm_scrach = -0.5 2795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(kScratchRegister, V8_INT64_C(0xBFE0000000000000), RelocInfo::NONE); 2796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(xmm_scratch, kScratchRegister); 2797e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ucomisd(input_reg, xmm_scratch); 2798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(below, instr->environment()); 2799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorl(output_reg, output_reg); 2801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 2803b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2804b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2805b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2806b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { 2807e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2808e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); 2809e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ sqrtsd(input_reg, input_reg); 2810b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2811b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2812b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2813b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { 2814e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister xmm_scratch = xmm0; 2815e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2816e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); 2817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(xmm_scratch, xmm_scratch); 2818e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. 2819e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ sqrtsd(input_reg, input_reg); 2820b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2821b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2822b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2823b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoPower(LPower* instr) { 2824e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* left = instr->InputAt(0); 2825e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister left_reg = ToDoubleRegister(left); 2826e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(!left_reg.is(xmm1)); 2827e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* right = instr->InputAt(1); 2828e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister result_reg = ToDoubleRegister(instr->result()); 2829e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Representation exponent_type = instr->hydrogen()->right()->representation(); 2830e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (exponent_type.IsDouble()) { 2831e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ PrepareCallCFunction(2); 2832e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Move arguments to correct registers 2833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movaps(xmm0, left_reg); 2834e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToDoubleRegister(right).is(xmm1)); 283544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CallCFunction( 283644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::power_double_double_function(isolate()), 2); 2837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (exponent_type.IsInteger32()) { 2838e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ PrepareCallCFunction(2); 2839e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Move arguments to correct registers: xmm0 and edi (not rdi). 2840e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // On Windows, the registers are xmm0 and edx. 2841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movaps(xmm0, left_reg); 2842e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#ifdef _WIN64 2843e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(right).is(rdx)); 2844e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#else 2845e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(right).is(rdi)); 2846e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif 284744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CallCFunction( 284844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::power_double_int_function(isolate()), 2); 2849e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2850e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(exponent_type.IsTagged()); 2851e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register right_reg = ToRegister(right); 2852e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2853e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label non_smi, call; 2854e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfNotSmi(right_reg, &non_smi); 2855e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiToInteger32(right_reg, right_reg); 2856e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cvtlsi2sd(xmm1, right_reg); 2857e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&call); 2858e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&non_smi); 2860e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CmpObjectType(right_reg, HEAP_NUMBER_TYPE , kScratchRegister); 2861e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(not_equal, instr->environment()); 2862e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movsd(xmm1, FieldOperand(right_reg, HeapNumber::kValueOffset)); 2863e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2864e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&call); 2865e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ PrepareCallCFunction(2); 2866e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Move arguments to correct registers xmm0 and xmm1. 2867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movaps(xmm0, left_reg); 2868e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Right argument is already in xmm1. 286944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CallCFunction( 287044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::power_double_double_function(isolate()), 2); 2871e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2872e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Return value is in xmm0. 2873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movaps(result_reg, xmm0); 287444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Restore context register. 287544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2876b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2877b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2878b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2879b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathLog(LUnaryMathOperation* instr) { 2880e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 2881e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub stub(TranscendentalCache::LOG, 2882e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub::UNTAGGED); 2883e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 2884b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2885b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2886b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2887b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathCos(LUnaryMathOperation* instr) { 2888e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 288944f0eee88ff00398ff7f715fab053374d808c90dSteve Block TranscendentalCacheStub stub(TranscendentalCache::COS, 2890e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub::UNTAGGED); 2891e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 2892b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2893b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2894b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2895b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathSin(LUnaryMathOperation* instr) { 2896e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 289744f0eee88ff00398ff7f715fab053374d808c90dSteve Block TranscendentalCacheStub stub(TranscendentalCache::SIN, 2898e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub::UNTAGGED); 2899e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 2900b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2901b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2902b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2903b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { 2904e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch switch (instr->op()) { 2905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathAbs: 2906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathAbs(instr); 2907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathFloor: 2909e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathFloor(instr); 2910e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathRound: 2912e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathRound(instr); 2913e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathSqrt: 2915e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathSqrt(instr); 2916e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2917e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathPowHalf: 2918e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathPowHalf(instr); 2919e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2920e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathCos: 2921e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathCos(instr); 2922e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2923e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathSin: 2924e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathSin(instr); 2925e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2926e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathLog: 2927e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathLog(instr); 2928e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2929e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2930e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch default: 2931e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UNREACHABLE(); 2932e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2933b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2934b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2935b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { 2937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(ToRegister(instr->function()).is(rdi)); 2938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->HasPointerMap()); 2939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->HasDeoptimizationEnvironment()); 2940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LPointerMap* pointers = instr->pointer_map(); 2941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LEnvironment* env = instr->deoptimization_environment(); 2942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RecordPosition(pointers->position()); 2943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RegisterEnvironmentForDeoptimization(env); 2944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SafepointGenerator generator(this, pointers, env->deoptimization_index()); 2945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ParameterCount count(instr->arity()); 2946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); 2947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2951b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallKeyed(LCallKeyed* instr) { 2952e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->key()).is(rcx)); 2953e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->result()).is(rax)); 2954e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2955e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int arity = instr->arity(); 2956589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Handle<Code> ic = 2957589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); 2958e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 2959e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2960b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2961b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2962b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2963b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallNamed(LCallNamed* instr) { 29641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 29651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 29661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int arity = instr->arity(); 2967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RelocInfo::Mode mode = RelocInfo::CODE_TARGET; 2968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = 2969589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeCallInitialize(arity, mode); 29701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(rcx, instr->name()); 2971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallCode(ic, mode, instr); 29721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2973b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2974b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2975b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2976b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallFunction(LCallFunction* instr) { 2977e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->result()).is(rax)); 2978e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2979e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int arity = instr->arity(); 2980589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch CallFunctionStub stub(arity, RECEIVER_MIGHT_BE_IMPLICIT); 2981e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 2982e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2983e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Drop(1); 2984b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2985b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2986b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2987b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallGlobal(LCallGlobal* instr) { 29881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 29891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int arity = instr->arity(); 2990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; 2991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = 2992589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeCallInitialize(arity, mode); 29931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(rcx, instr->name()); 2994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallCode(ic, mode, instr); 29951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2996b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2997b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2998b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2999b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { 30001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 30011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(rdi, instr->target()); 3002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); 3003b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3004b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3005b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3006b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallNew(LCallNew* instr) { 30071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->InputAt(0)).is(rdi)); 30081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 30091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 301044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> builtin = isolate()->builtins()->JSConstructCall(); 30111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Set(rax, instr->arity()); 30121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); 3013b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3014b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3015b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3016b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallRuntime(LCallRuntime* instr) { 3017e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallRuntime(instr->function(), instr->arity(), instr); 3018b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3019b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3020b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3021b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { 30221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register object = ToRegister(instr->object()); 30231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register value = ToRegister(instr->value()); 30241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offset = instr->offset(); 30251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 30261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!instr->transition().is_null()) { 30271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); 30281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 30291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 30301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Do the store. 30311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->is_in_object()) { 30321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(FieldOperand(object, offset), value); 30331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->needs_write_barrier()) { 30341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register temp = ToRegister(instr->TempAt(0)); 30351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Update the write barrier for the object for in-object properties. 30361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ RecordWrite(object, offset, value, temp); 30371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 30381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 30391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register temp = ToRegister(instr->TempAt(0)); 30401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset)); 30411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(FieldOperand(temp, offset), value); 30421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->needs_write_barrier()) { 30431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Update the write barrier for the properties array. 30441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // object is used as a scratch register. 30451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ RecordWrite(temp, offset, value, object); 30461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 30471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3048b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3049b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3050b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3051b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 3052e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->object()).is(rdx)); 3053e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->value()).is(rax)); 3054e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3055e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Move(rcx, instr->hydrogen()->name()); 30568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<Code> ic = instr->strict_mode() 305744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? isolate()->builtins()->StoreIC_Initialize_Strict() 305844f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate()->builtins()->StoreIC_Initialize(); 3059e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 3060e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 3061e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3062e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 306344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoStoreKeyedSpecializedArrayElement( 306444f0eee88ff00398ff7f715fab053374d808c90dSteve Block LStoreKeyedSpecializedArrayElement* instr) { 3065589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = instr->elements_kind(); 30663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand operand(BuildFastArrayOperand(instr->external_pointer(), 30673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->key(), elements_kind, 0)); 3068589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 306944f0eee88ff00398ff7f715fab053374d808c90dSteve Block XMMRegister value(ToDoubleRegister(instr->value())); 307044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cvtsd2ss(value, value); 3071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movss(operand, value); 3072589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsd(operand, ToDoubleRegister(instr->value())); 307444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 307544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register value(ToRegister(instr->value())); 30763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3077589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3078589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3079589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movb(operand, value); 308144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3082589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3083589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movw(operand, value); 308544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3086589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3087589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movl(operand, value); 308944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3090589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3091589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3092589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 3093589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3094589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3095589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 309644f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 309744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 309844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 3099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3100b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3101b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3102b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3103b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { 310469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (instr->index()->IsConstantOperand()) { 310569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (instr->length()->IsRegister()) { 310669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmpq(ToRegister(instr->length()), 310769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Immediate(ToInteger32(LConstantOperand::cast(instr->index())))); 310869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else { 310969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmpq(ToOperand(instr->length()), 311069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Immediate(ToInteger32(LConstantOperand::cast(instr->index())))); 311169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 31121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 311369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (instr->length()->IsRegister()) { 311469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmpq(ToRegister(instr->length()), ToRegister(instr->index())); 311569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else { 311669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmpq(ToOperand(instr->length()), ToRegister(instr->index())); 311769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 31181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 311969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(below_equal, instr->environment()); 3120b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3121b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3122b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3123b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { 31241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register value = ToRegister(instr->value()); 31251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register elements = ToRegister(instr->object()); 31261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; 31271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 31281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Do the store. 31291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->key()->IsConstantOperand()) { 31301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); 31311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); 31321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offset = 31331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; 31341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(FieldOperand(elements, offset), value); 31351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 31361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(FieldOperand(elements, 31371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block key, 31381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block times_pointer_size, 31391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FixedArray::kHeaderSize), 31401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block value); 31411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 31421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 31431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->NeedsWriteBarrier()) { 31441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Compute address of modified element and store it into key register. 31451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ lea(key, FieldOperand(elements, 31461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block key, 31471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block times_pointer_size, 31481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FixedArray::kHeaderSize)); 31491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ RecordWrite(elements, key, value); 31501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3151b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3152b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3153b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 31543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoStoreKeyedFastDoubleElement( 31553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LStoreKeyedFastDoubleElement* instr) { 31563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch XMMRegister value = ToDoubleRegister(instr->value()); 31573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label have_value; 31583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 31593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ucomisd(value, value); 31603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(parity_odd, &have_value); // NaN. 31613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 31623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Set(kScratchRegister, BitCast<uint64_t>( 31633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedDoubleArray::canonical_not_the_hole_nan_as_double())); 31643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(value, kScratchRegister); 31653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 31663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&have_value); 31673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand double_store_operand = BuildFastArrayOperand( 3168589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS, 31693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedDoubleArray::kHeaderSize - kHeapObjectTag); 31703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movsd(double_store_operand, value); 31713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 31723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3173b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { 3174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->object()).is(rdx)); 3175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->key()).is(rcx)); 3176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->value()).is(rax)); 3177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 31788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<Code> ic = instr->strict_mode() 317944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 318044f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate()->builtins()->KeyedStoreIC_Initialize(); 3181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 3182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 3183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoStringAdd(LStringAdd* instr) { 3186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(instr->left()); 3187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(instr->right()); 3188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringAddStub stub(NO_STRING_CHECK_IN_STUB); 3189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 3194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch class DeferredStringCharCodeAt: public LDeferredCode { 3195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public: 3196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) 3197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch : LDeferredCode(codegen), instr_(instr) { } 3198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } 3199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private: 3200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LStringCharCodeAt* instr_; 3201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch }; 3202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register string = ToRegister(instr->string()); 320469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register index = ToRegister(instr->index()); 3205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 3206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeferredStringCharCodeAt* deferred = 3208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch new DeferredStringCharCodeAt(this, instr); 3209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Fetch the instance type of the receiver into result register. 3211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); 3212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); 3213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 321469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // We need special handling for indirect strings. 321569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label check_sequential; 321669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ testb(result, Immediate(kIsIndirectStringMask)); 321769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(zero, &check_sequential, Label::kNear); 321869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 321969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Dispatch on the indirect string shape: slice or cons. 322069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label cons_string; 322169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ testb(result, Immediate(kSlicedNotConsMask)); 322269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(zero, &cons_string, Label::kNear); 3223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 322469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Handle slices. 322569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label indirect_string_loaded; 322669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ SmiToInteger32(result, FieldOperand(string, SlicedString::kOffsetOffset)); 322769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ addq(index, result); 322869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movq(string, FieldOperand(string, SlicedString::kParentOffset)); 322969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ jmp(&indirect_string_loaded, Label::kNear); 3230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 323169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Handle conses. 3232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check whether the right hand side is the empty string (i.e. if 3233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // this is really a flat string in a cons string). If that is not 3234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the case we would rather go to the runtime system now to flatten 3235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the string. 323669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&cons_string); 3237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset), 3238e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Heap::kEmptyStringRootIndex); 3239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(not_equal, deferred->entry()); 3240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(string, FieldOperand(string, ConsString::kFirstOffset)); 324169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 324269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&indirect_string_loaded); 3243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); 3244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); 324569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 324669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Check whether the string is sequential. The only non-sequential 324769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // shapes we support have just been unwrapped above. 324869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&check_sequential); 3249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch STATIC_ASSERT(kSeqStringTag == 0); 3250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testb(result, Immediate(kStringRepresentationMask)); 3251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(not_zero, deferred->entry()); 3252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 325369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Dispatch on the encoding: ASCII or two-byte. 325469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label ascii_string; 3255589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); 3256589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 3257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testb(result, Immediate(kStringEncodingMask)); 3258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &ascii_string, Label::kNear); 3259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Two-byte string. 3261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Load the two-byte character code into the result register. 326269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label done; 3263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 326469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movzxwl(result, FieldOperand(string, 326569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch index, 326669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch times_2, 326769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch SeqTwoByteString::kHeaderSize)); 3268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 3269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // ASCII string. 3271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Load the byte into the result register. 3272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&ascii_string); 327369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movzxbl(result, FieldOperand(string, 327469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch index, 327569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch times_1, 327669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch SeqAsciiString::kHeaderSize)); 3277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 3278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(deferred->exit()); 3279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 3280e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { 3283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register string = ToRegister(instr->string()); 3284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 3285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // TODO(3095996): Get rid of this. For now, we need to make the 3287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // result register contain a valid pointer because it is already 3288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // contained in the register pointer map. 3289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Set(result, 0); 3290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 32918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 3292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(string); 3293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Push the index as a smi. This is safe because of the checks in 3294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // DoStringCharCodeAt above. 3295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); 3296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->index()->IsConstantOperand()) { 3297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int const_index = ToInteger32(LConstantOperand::cast(instr->index())); 3298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(Smi::FromInt(const_index)); 3299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 3300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register index = ToRegister(instr->index()); 3301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Integer32ToSmi(index, index); 3302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(index); 3303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 33048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); 3305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (FLAG_debug_code) { 3306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ AbortIfNotSmi(rax); 3307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiToInteger32(rax, rax); 3309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ StoreToSafepointRegisterSlot(result, rax); 3310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 3311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 331344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { 331444f0eee88ff00398ff7f715fab053374d808c90dSteve Block class DeferredStringCharFromCode: public LDeferredCode { 331544f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 331644f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) 331744f0eee88ff00398ff7f715fab053374d808c90dSteve Block : LDeferredCode(codegen), instr_(instr) { } 331844f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } 331944f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 332044f0eee88ff00398ff7f715fab053374d808c90dSteve Block LStringCharFromCode* instr_; 332144f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 332244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 332344f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeferredStringCharFromCode* deferred = 332444f0eee88ff00398ff7f715fab053374d808c90dSteve Block new DeferredStringCharFromCode(this, instr); 332544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 332644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); 332744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register char_code = ToRegister(instr->char_code()); 332844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result = ToRegister(instr->result()); 332944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!char_code.is(result)); 333044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 333144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpl(char_code, Immediate(String::kMaxAsciiCharCode)); 333244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(above, deferred->entry()); 333344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex); 333444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(result, FieldOperand(result, 333544f0eee88ff00398ff7f715fab053374d808c90dSteve Block char_code, times_pointer_size, 333644f0eee88ff00398ff7f715fab053374d808c90dSteve Block FixedArray::kHeaderSize)); 333744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareRoot(result, Heap::kUndefinedValueRootIndex); 333844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(equal, deferred->entry()); 333944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(deferred->exit()); 334044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 334144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 334244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 334344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { 334444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register char_code = ToRegister(instr->char_code()); 334544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result = ToRegister(instr->result()); 334644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 334744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // TODO(3095996): Get rid of this. For now, we need to make the 334844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // result register contain a valid pointer because it is already 334944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // contained in the register pointer map. 335044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(result, 0); 335144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 33528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 335344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Integer32ToSmi(char_code, char_code); 335444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ push(char_code); 33558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); 335644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ StoreToSafepointRegisterSlot(result, rax); 335744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 335844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 335944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3360e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoStringLength(LStringLength* instr) { 3361e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register string = ToRegister(instr->string()); 3362e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 3363e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, FieldOperand(string, String::kLengthOffset)); 3364b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3365b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3366b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3367b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { 33681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* input = instr->InputAt(0); 33691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(input->IsRegister() || input->IsStackSlot()); 33701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* output = instr->result(); 33711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(output->IsDoubleRegister()); 3372e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (input->IsRegister()) { 3373e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cvtlsi2sd(ToDoubleRegister(output), ToRegister(input)); 3374e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 3375e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cvtlsi2sd(ToDoubleRegister(output), ToOperand(input)); 3376e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3377b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3378b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3379b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3380b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoNumberTagI(LNumberTagI* instr) { 33811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* input = instr->InputAt(0); 33821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(input->IsRegister() && input->Equals(instr->result())); 33831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(input); 3384b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 33851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Integer32ToSmi(reg, reg); 3386b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3387b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3388b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3389b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoNumberTagD(LNumberTagD* instr) { 33901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block class DeferredNumberTagD: public LDeferredCode { 33911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public: 33921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) 33931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block : LDeferredCode(codegen), instr_(instr) { } 33941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } 33951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private: 33961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LNumberTagD* instr_; 33971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block }; 33981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 34001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->result()); 34011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register tmp = ToRegister(instr->TempAt(0)); 34021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); 34041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_inline_new) { 34051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(reg, tmp, deferred->entry()); 34061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 34071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ jmp(deferred->entry()); 34081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(deferred->exit()); 34101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); 3411b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3412b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3413b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3414b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { 34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // TODO(3095996): Get rid of this. For now, we need to make the 34161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // result register contain a valid pointer because it is already 34171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // contained in the register pointer map. 34181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->result()); 34191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(reg, Smi::FromInt(0)); 34201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch { 34228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 34238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); 34248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Ensure that value in rax survives popping registers. 34258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(kScratchRegister, rax); 34268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 34271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(reg, kScratchRegister); 3428b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3429b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3430b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3431b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoSmiTag(LSmiTag* instr) { 34321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->InputAt(0)->Equals(instr->result())); 34331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 34341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); 34351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Integer32ToSmi(input, input); 3436b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3437b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3438b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3439b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoSmiUntag(LSmiUntag* instr) { 34401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->InputAt(0)->Equals(instr->result())); 34411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 34421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->needs_check()) { 34431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition is_smi = __ CheckSmi(input); 34441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(NegateCondition(is_smi), instr->environment()); 34451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiToInteger32(input, input); 3447b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3448b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3449b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3450b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::EmitNumberUntagD(Register input_reg, 3451b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch XMMRegister result_reg, 34527d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch bool deoptimize_on_undefined, 3453b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LEnvironment* env) { 3454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label load_smi, done; 34551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Smi check. 3457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(input_reg, &load_smi, Label::kNear); 34581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Heap number map check. 34601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 34611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Heap::kHeapNumberMapRootIndex); 34627d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch if (deoptimize_on_undefined) { 34637d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch DeoptimizeIf(not_equal, env); 34647d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } else { 3465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label heap_number; 3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &heap_number, Label::kNear); 3467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 34687d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); 34697d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch DeoptimizeIf(not_equal, env); 34701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34717d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch // Convert undefined to NaN. Compute NaN as 0/0. 3472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(result_reg, result_reg); 34737d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch __ divsd(result_reg, result_reg); 3474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 34751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34767d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch __ bind(&heap_number); 34777d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } 34781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Heap number to XMM conversion. 34791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); 3480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 34811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Smi to XMM conversion 34831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&load_smi); 3484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiToInteger32(kScratchRegister, input_reg); 34851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cvtlsi2sd(result_reg, kScratchRegister); 34861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 3487b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3488b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3489b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 34901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass DeferredTaggedToI: public LDeferredCode { 34911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public: 34921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 34931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block : LDeferredCode(codegen), instr_(instr) { } 34941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } 34951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private: 34961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LTaggedToI* instr_; 34971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}; 34981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3500b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { 3501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, heap_number; 35021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input_reg = ToRegister(instr->InputAt(0)); 35031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Heap number map check. 35051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 35061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Heap::kHeapNumberMapRootIndex); 35071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->truncating()) { 3509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &heap_number, Label::kNear); 35101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for undefined. Undefined is converted to zero for truncating 35111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // conversions. 35121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); 35131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_equal, instr->environment()); 35148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Set(input_reg, 0); 3515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 35161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&heap_number); 35181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 35201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cvttsd2siq(input_reg, xmm0); 35211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); 35228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ cmpq(input_reg, kScratchRegister); 35231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(equal, instr->environment()); 35241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 35251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Deoptimize if we don't have a heap number. 35261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_equal, instr->environment()); 35271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); 35291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 35301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cvttsd2si(input_reg, xmm0); 35311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cvtlsi2sd(xmm_temp, input_reg); 35321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ucomisd(xmm0, xmm_temp); 35331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_equal, instr->environment()); 35341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(parity_even, instr->environment()); // NaN. 35351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 35361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(input_reg, input_reg); 35371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_zero, &done); 35381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movmskpd(input_reg, xmm0); 35391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ andl(input_reg, Immediate(1)); 35401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_zero, instr->environment()); 35411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 35421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 35431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 3544b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3545b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3546b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3547b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoTaggedToI(LTaggedToI* instr) { 35481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* input = instr->InputAt(0); 35491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(input->IsRegister()); 35501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(input->Equals(instr->result())); 35511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input_reg = ToRegister(input); 35531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); 35541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfNotSmi(input_reg, deferred->entry()); 35551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiToInteger32(input_reg, input_reg); 35561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(deferred->exit()); 3557b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3558b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3559b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3560b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { 3561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* input = instr->InputAt(0); 3562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(input->IsRegister()); 3563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* result = instr->result(); 3564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(result->IsDoubleRegister()); 3565e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3566e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register input_reg = ToRegister(input); 3567e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister result_reg = ToDoubleRegister(result); 3568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 35697d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch EmitNumberUntagD(input_reg, result_reg, 35707d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch instr->hydrogen()->deoptimize_on_undefined(), 35717d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch instr->environment()); 3572b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3573b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3574b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3575b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoDoubleToI(LDoubleToI* instr) { 3576e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* input = instr->InputAt(0); 3577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(input->IsDoubleRegister()); 3578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* result = instr->result(); 3579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(result->IsRegister()); 3580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister input_reg = ToDoubleRegister(input); 3582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result_reg = ToRegister(result); 3583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->truncating()) { 3585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Performs a truncating conversion of a floating point number as used by 3586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the JS bitwise operations. 3587e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cvttsd2siq(result_reg, input_reg); 3588e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(kScratchRegister, V8_INT64_C(0x8000000000000000), RelocInfo::NONE); 35898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ cmpq(result_reg, kScratchRegister); 3590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(equal, instr->environment()); 3591e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 3592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cvttsd2si(result_reg, input_reg); 3593e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cvtlsi2sd(xmm0, result_reg); 3594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ucomisd(xmm0, input_reg); 3595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(not_equal, instr->environment()); 3596e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(parity_even, instr->environment()); // NaN. 3597e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 3599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The integer converted back is equal to the original. We 3600e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // only have to test if we got -0 as an input. 3601e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testl(result_reg, result_reg); 3602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &done, Label::kNear); 3603e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movmskpd(result_reg, input_reg); 3604e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Bit 0 contains the sign of the double in input_reg. 3605e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If input was positive, we are ok and return 0, otherwise 3606e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // deoptimize. 3607e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ andl(result_reg, Immediate(1)); 3608e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(not_zero, instr->environment()); 3609e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 3610e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3611e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3612b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3613b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3614b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3615b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCheckSmi(LCheckSmi* instr) { 36161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* input = instr->InputAt(0); 36171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition cc = masm()->CheckSmi(ToRegister(input)); 361844f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(NegateCondition(cc), instr->environment()); 361944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 362044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 362144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 362244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 362344f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOperand* input = instr->InputAt(0); 362444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Condition cc = masm()->CheckSmi(ToRegister(input)); 36251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(cc, instr->environment()); 3626b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3627b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3628b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3629b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 36301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 36311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); 36331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (instr->hydrogen()->is_interval_check()) { 3635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InstanceType first; 3636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InstanceType last; 3637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->hydrogen()->GetCheckInterval(&first, &last); 3638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 36391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 36401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(static_cast<int8_t>(first))); 3641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If there is only one type in the interval check for equality. 3643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (first == last) { 3644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 3645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(below, instr->environment()); 3647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Omit check for the last type. 3648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (last != LAST_TYPE) { 3649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 3650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Immediate(static_cast<int8_t>(last))); 3651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(above, instr->environment()); 3652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 36541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 3655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint8_t mask; 3656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint8_t tag; 3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); 3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (IsPowerOf2(mask)) { 3660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(tag == 0 || IsPowerOf2(tag)); 3661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 3662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Immediate(mask)); 3663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment()); 3664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movzxbl(kScratchRegister, 3666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); 3667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ andb(kScratchRegister, Immediate(mask)); 3668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpb(kScratchRegister, Immediate(tag)); 3669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 36701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 36711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3672b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3673b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3674b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3675b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCheckFunction(LCheckFunction* instr) { 36761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->InputAt(0)->IsRegister()); 36771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->InputAt(0)); 36781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Cmp(reg, instr->hydrogen()->target()); 36791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_equal, instr->environment()); 3680b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3681b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3682b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3683b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCheckMap(LCheckMap* instr) { 36841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* input = instr->InputAt(0); 36851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(input->IsRegister()); 36861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(input); 36871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), 36881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block instr->hydrogen()->map()); 36891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_equal, instr->environment()); 3690b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3691b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3692b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 3694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); 3695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result_reg = ToRegister(instr->result()); 3696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register temp_reg = ToRegister(instr->TempAt(0)); 3697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ClampDoubleToUint8(value_reg, xmm0, result_reg, temp_reg); 3698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { 3702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->unclamped()->Equals(instr->result())); 3703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register value_reg = ToRegister(instr->result()); 3704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ClampUint8(value_reg); 3705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { 3709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->unclamped()->Equals(instr->result())); 3710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register input_reg = ToRegister(instr->unclamped()); 3711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register temp_reg = ToRegister(instr->TempAt(0)); 3712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch XMMRegister temp_xmm_reg = ToDoubleRegister(instr->TempAt(1)); 3713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label is_smi, done, heap_number; 3714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(input_reg, &is_smi); 3716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for heap number 3718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 3719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch factory()->heap_number_map()); 3720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &heap_number, Label::kNear); 3721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for undefined. Undefined is converted to zero for clamping 3723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // conversions. 3724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Cmp(input_reg, factory()->undefined_value()); 3725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 3726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(input_reg, Immediate(0)); 3727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 3728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Heap number 3730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&heap_number); 3731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 3732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ClampDoubleToUint8(xmm0, temp_xmm_reg, input_reg, temp_reg); 3733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 3734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // smi 3736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&is_smi); 3737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiToInteger32(input_reg, input_reg); 3738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ClampUint8(input_reg); 3739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 3741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3744b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) { 374544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (heap()->InNewSpace(*object)) { 37461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<JSGlobalPropertyCell> cell = 374744f0eee88ff00398ff7f715fab053374d808c90dSteve Block factory()->NewJSGlobalPropertyCell(object); 37481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, cell, RelocInfo::GLOBAL_PROPERTY_CELL); 37491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, Operand(result, 0)); 37501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 37511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(result, object); 37521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3753b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3754b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3755b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3756b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { 37571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->TempAt(0)); 37581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<JSObject> holder = instr->holder(); 37601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<JSObject> current_prototype = instr->prototype(); 37611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Load prototype object. 37631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LoadHeapObject(reg, current_prototype); 37641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check prototype maps up to the holder. 37661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block while (!current_prototype.is_identical_to(holder)) { 37671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), 37681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Map>(current_prototype->map())); 37691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_equal, instr->environment()); 37701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block current_prototype = 37711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); 37721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Load next prototype object. 37731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LoadHeapObject(reg, current_prototype); 37741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 37751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check the holder map. 37771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), 37781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Map>(current_prototype->map())); 37791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_equal, instr->environment()); 3780b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3781b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3782b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3783b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { 37841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Setup the parameters to the stub/runtime call. 37851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 37861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); 37871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); 37881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Push(instr->hydrogen()->constant_elements()); 37891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Pick the right runtime function or stub to call. 37911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int length = instr->hydrogen()->length(); 37921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->IsCopyOnWrite()) { 37931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->hydrogen()->depth() == 1); 37941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FastCloneShallowArrayStub::Mode mode = 37951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; 37961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FastCloneShallowArrayStub stub(mode, length); 37971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 37981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (instr->hydrogen()->depth() > 1) { 37991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallRuntime(Runtime::kCreateArrayLiteral, 3, instr); 38001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 38011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr); 38021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 38031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FastCloneShallowArrayStub::Mode mode = 38041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FastCloneShallowArrayStub::CLONE_ELEMENTS; 38051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FastCloneShallowArrayStub stub(mode, length); 38061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 38071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3808b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3809b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3810b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3811b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { 38121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Setup the parameters to the stub/runtime call. 38131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 38141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); 38151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); 38161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Push(instr->hydrogen()->constant_properties()); 38171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Push(Smi::FromInt(instr->hydrogen()->fast_elements() ? 1 : 0)); 38181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 38191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Pick the right runtime function to call. 38201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->depth() > 1) { 38211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallRuntime(Runtime::kCreateObjectLiteral, 4, instr); 38221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 38231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); 38241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3825b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3826b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3827b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 382844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoToFastProperties(LToFastProperties* instr) { 382944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(ToRegister(instr->InputAt(0)).is(rax)); 383044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ push(rax); 383144f0eee88ff00398ff7f715fab053374d808c90dSteve Block CallRuntime(Runtime::kToFastProperties, 1, instr); 383244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 383344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 383444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3835b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { 3836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label materialized; 3837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Registers will be used as follows: 3838e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // rdi = JS function. 3839e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // rcx = literals array. 3840e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // rbx = regexp literal. 3841e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // rax = regexp literal clone. 3842e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 3843e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 3844e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int literal_offset = FixedArray::kHeaderSize + 3845e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch instr->hydrogen()->literal_index() * kPointerSize; 3846e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rbx, FieldOperand(rcx, literal_offset)); 3847e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); 3848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &materialized, Label::kNear); 3849e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3850e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Create regexp literal using runtime function 3851e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Result will be in rax. 3852e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(rcx); 3853e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); 3854e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(instr->hydrogen()->pattern()); 3855e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(instr->hydrogen()->flags()); 3856e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); 3857e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rbx, rax); 3858e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&materialized); 3860e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 3861e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label allocated, runtime_allocate; 3862e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); 3863e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&allocated); 3864e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3865e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&runtime_allocate); 3866e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(rbx); 3867e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(Smi::FromInt(size)); 3868e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); 3869e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ pop(rbx); 3870e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3871e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&allocated); 3872e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy the content into the newly allocated memory. 3873e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // (Unroll copy loop once for better throughput). 3874e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { 3875e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rdx, FieldOperand(rbx, i)); 3876e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rcx, FieldOperand(rbx, i + kPointerSize)); 3877e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(FieldOperand(rax, i), rdx); 3878e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(FieldOperand(rax, i + kPointerSize), rcx); 3879e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3880e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if ((size % (2 * kPointerSize)) != 0) { 3881e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rdx, FieldOperand(rbx, size - kPointerSize)); 3882e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(FieldOperand(rax, size - kPointerSize), rdx); 3883e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3884b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3885b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3886b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3887b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { 38881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Use the fast case closure allocation code that allocates in new 38891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // space for nested functions that don't need literals cloning. 38901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<SharedFunctionInfo> shared_info = instr->shared_info(); 38911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool pretenure = instr->hydrogen()->pretenure(); 389244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!pretenure && shared_info->num_literals() == 0) { 389344f0eee88ff00398ff7f715fab053374d808c90dSteve Block FastNewClosureStub stub( 389444f0eee88ff00398ff7f715fab053374d808c90dSteve Block shared_info->strict_mode() ? kStrictMode : kNonStrictMode); 38951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Push(shared_info); 38961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 38971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 38981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(rsi); 38991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Push(shared_info); 390044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ PushRoot(pretenure ? 390144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::kTrueValueRootIndex : 390244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::kFalseValueRootIndex); 39031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallRuntime(Runtime::kNewClosure, 3, instr); 39041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3905b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3906b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3907b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3908b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoTypeof(LTypeof* instr) { 3909e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* input = instr->InputAt(0); 3910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(input); 3911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallRuntime(Runtime::kTypeof, 1, instr); 3912b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3913b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3914b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::EmitPushTaggedOperand(LOperand* operand) { 3916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!operand->IsDoubleRegister()); 3917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (operand->IsConstantOperand()) { 3918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(ToHandle(LConstantOperand::cast(operand))); 3919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (operand->IsRegister()) { 3920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(ToRegister(operand)); 3921e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 3922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(ToOperand(operand)); 3923e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 39241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 39251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 39261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3927b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 39281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 39291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 39301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 39311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* true_label = chunk_->GetAssemblyLabel(true_block); 39321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* false_label = chunk_->GetAssemblyLabel(false_block); 39331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 39341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition final_branch_condition = EmitTypeofIs(true_label, 39351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block false_label, 39361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block input, 39371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block instr->type_literal()); 39381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 39391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, final_branch_condition); 3940b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3941b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3942b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3943b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochCondition LCodeGen::EmitTypeofIs(Label* true_label, 3944b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* false_label, 3945b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register input, 3946b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<String> type_name) { 39471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition final_branch_condition = no_condition; 394844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (type_name->Equals(heap()->number_symbol())) { 39491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, true_label); 395044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareRoot(FieldOperand(input, HeapObject::kMapOffset), 395144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::kHeapNumberMapRootIndex); 395244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 39531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block final_branch_condition = equal; 39541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 395544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->string_symbol())) { 39561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, false_label); 3957e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); 3958e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(above_equal, false_label); 39591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(FieldOperand(input, Map::kBitFieldOffset), 39601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(1 << Map::kIsUndetectable)); 3961e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch final_branch_condition = zero; 39621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 396344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->boolean_symbol())) { 39641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(input, Heap::kTrueValueRootIndex); 39651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, true_label); 39661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(input, Heap::kFalseValueRootIndex); 39671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block final_branch_condition = equal; 39681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 396969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_symbol())) { 397069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(input, Heap::kNullValueRootIndex); 397169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch final_branch_condition = equal; 397269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 397344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->undefined_symbol())) { 39741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(input, Heap::kUndefinedValueRootIndex); 39751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, true_label); 39761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, false_label); 39771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for undetectable objects => true. 39781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(input, FieldOperand(input, HeapObject::kMapOffset)); 39791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(FieldOperand(input, Map::kBitFieldOffset), 39801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(1 << Map::kIsUndetectable)); 39811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block final_branch_condition = not_zero; 39821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 398344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->function_symbol())) { 39841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, false_label); 39853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(input, FIRST_CALLABLE_SPEC_OBJECT_TYPE, input); 39861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block final_branch_condition = above_equal; 39871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 398844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->object_symbol())) { 39891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, false_label); 399069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (!FLAG_harmony_typeof) { 399169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(input, Heap::kNullValueRootIndex); 399269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, true_label); 399369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 39943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); 3995e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(below, false_label); 39963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 39973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above, false_label); 39981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for undetectable objects => false. 39991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(FieldOperand(input, Map::kBitFieldOffset), 40001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(1 << Map::kIsUndetectable)); 4001e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch final_branch_condition = zero; 40021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 40031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 40041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block final_branch_condition = never; 40051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ jmp(false_label); 40061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 40071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 40081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return final_branch_condition; 4009b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4010b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4011b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4012e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 4013e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register temp = ToRegister(instr->TempAt(0)); 4014e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 4015e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 4016e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4017e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitIsConstructCall(temp); 4018e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitBranch(true_block, false_block, equal); 4019e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 4020e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4022e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::EmitIsConstructCall(Register temp) { 4023e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Get the frame pointer for the calling frame. 4024e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 4025e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4026e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Skip the arguments adaptor frame if it exists. 4027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label check_frame_marker; 402844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), 402944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 4030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &check_frame_marker, Label::kNear); 4031e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 4032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check the marker in the calling frame. 4034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&check_frame_marker); 403544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), 403644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(StackFrame::CONSTRUCT)); 4037e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 4038e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4039e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4040b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLazyBailout(LLazyBailout* instr) { 4041b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // No code for lazy bailout instruction. Used to capture environment after a 4042b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // call for populating the safepoint data with deoptimization data. 4043b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4044b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4045b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4046b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoDeoptimize(LDeoptimize* instr) { 4047b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch DeoptimizeIf(no_condition, instr->environment()); 4048b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4049b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4050b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4051b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { 4052e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* obj = instr->object(); 4053e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* key = instr->key(); 4054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(obj); 4055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(key); 4056e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 4057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LPointerMap* pointers = instr->pointer_map(); 4058e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LEnvironment* env = instr->deoptimization_environment(); 4059e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch RecordPosition(pointers->position()); 4060e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch RegisterEnvironmentForDeoptimization(env); 4061e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Create safepoint generator that will also ensure enough space in the 4062e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // reloc info for patching in deoptimization (since this is invoking a 4063e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // builtin) 4064e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch SafepointGenerator safepoint_generator(this, 4065e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pointers, 406644f0eee88ff00398ff7f715fab053374d808c90dSteve Block env->deoptimization_index()); 4067e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(Smi::FromInt(strict_mode_flag())); 4068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); 4069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 4070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoIn(LIn* instr) { 4073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LOperand* obj = instr->object(); 4074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LOperand* key = instr->key(); 4075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(key); 4076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(obj); 4077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 4078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LPointerMap* pointers = instr->pointer_map(); 4079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LEnvironment* env = instr->deoptimization_environment(); 4080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RecordPosition(pointers->position()); 4081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RegisterEnvironmentForDeoptimization(env); 4082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Create safepoint generator that will also ensure enough space in the 4083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // reloc info for patching in deoptimization (since this is invoking a 4084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // builtin) 4085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SafepointGenerator safepoint_generator(this, 4086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch pointers, 4087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch env->deoptimization_index()); 4088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); 4089b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4090b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4091b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 40923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { 40933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch { 40943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PushSafepointRegistersScope scope(this); 40953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 40963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CallRuntimeSaveDoubles(Runtime::kStackGuard); 40973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RegisterLazyDeoptimization(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); 40983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 40993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // The gap code includes the restoring of the safepoint registers. 41013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int pc = masm()->pc_offset(); 41023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch safepoints_.SetPcAfterGap(pc); 41033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 41043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4106b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoStackCheck(LStackCheck* instr) { 41073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch class DeferredStackCheck: public LDeferredCode { 41083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public: 41093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) 41103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch : LDeferredCode(codegen), instr_(instr) { } 41113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } 41123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private: 41133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LStackCheck* instr_; 41143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch }; 4115b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 41163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (instr->hydrogen()->is_function_entry()) { 41173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Perform stack overflow check. 41183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label done; 41193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 41203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above_equal, &done, Label::kNear); 41213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch StackCheckStub stub; 41223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 41233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&done); 41243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 41253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(instr->hydrogen()->is_backwards_branch()); 41263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Perform stack overflow check if this goto needs it before jumping. 41273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DeferredStackCheck* deferred_stack_check = 41283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new DeferredStackCheck(this, instr); 41293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 41303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(below, deferred_stack_check->entry()); 41313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(instr->done_label()); 41323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch deferred_stack_check->SetExit(instr->done_label()); 41333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 4134b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4135b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4136b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4137b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoOsrEntry(LOsrEntry* instr) { 4138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This is a pseudo-instruction that ensures that the environment here is 4139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // properly registered for deoptimization and records the assembler's PC 4140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // offset. 4141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LEnvironment* environment = instr->environment(); 4142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch environment->SetSpilledRegisters(instr->SpilledRegisterArray(), 4143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch instr->SpilledDoubleRegisterArray()); 4144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If the environment were already registered, we would have no way of 4146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // backpatching it with the spill slot operands. 4147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(!environment->HasBeenRegistered()); 4148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch RegisterEnvironmentForDeoptimization(environment); 4149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(osr_pc_offset_ == -1); 4150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch osr_pc_offset_ = masm()->pc_offset(); 4151b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4152b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4153b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#undef __ 4154b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4155b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} } // namespace v8::internal 4156b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4157b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif // V8_TARGET_ARCH_X64 4158