13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 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, 462b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Safepoint::DeoptMode mode) 47e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch : codegen_(codegen), 48e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pointers_(pointers), 492b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch deopt_mode_(mode) { } 50e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual ~SafepointGenerator() { } 51e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 52257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch virtual void BeforeCall(int call_size) const { 532b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch codegen_->EnsureSpaceForLazyDeopt(Deoptimizer::patch_size() - call_size); 5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 5544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 56257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch virtual void AfterCall() const { 572b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch codegen_->RecordSafepoint(pointers_, deopt_mode_); 58e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 59e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 60e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private: 61e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LCodeGen* codegen_; 62e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LPointerMap* pointers_; 632b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Safepoint::DeoptMode deopt_mode_; 64e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}; 65e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 66e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 67b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#define __ masm()-> 68b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 69b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochbool LCodeGen::GenerateCode() { 703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("Z_Code generation", chunk()); 71b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(is_unused()); 72b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch status_ = GENERATING; 733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Open a frame scope to indicate that there is a frame on the stack. The 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // MANUAL indicates that the scope shouldn't actually generate code to set up 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the frame (that is done in GeneratePrologue). 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm_, StackFrame::MANUAL); 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 79b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return GeneratePrologue() && 80b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateBody() && 81b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateDeferredCode() && 82e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch GenerateJumpTable() && 83b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateSafepointTable(); 84b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 85b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 86b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 87b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::FinishCode(Handle<Code> code) { 88b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(is_done()); 89257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch code->set_stack_slots(GetStackSlotCount()); 901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); 91b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch PopulateDeoptimizationData(code); 92b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 93b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 94b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 95b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::Abort(const char* format, ...) { 96b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (FLAG_trace_bailout) { 97589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SmartArrayPointer<char> name( 98589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch info()->shared_info()->DebugName()->ToCString()); 99e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PrintF("Aborting LCodeGen in @\"%s\": ", *name); 100b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch va_list arguments; 101b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch va_start(arguments, format); 102b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch OS::VPrint(format, arguments); 103b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch va_end(arguments); 104b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch PrintF("\n"); 105b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 106b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch status_ = ABORTED; 107b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 108b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 109b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 110b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::Comment(const char* format, ...) { 111b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (!FLAG_code_comments) return; 112b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch char buffer[4 * KB]; 113b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch StringBuilder builder(buffer, ARRAY_SIZE(buffer)); 114b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch va_list arguments; 115b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch va_start(arguments, format); 116b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch builder.AddFormattedList(format, arguments); 117b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch va_end(arguments); 118b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 119b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Copy the string before recording it in the assembler to avoid 120b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // issues when the stack allocated buffer goes out of scope. 121b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int length = builder.position(); 122b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Vector<char> copy = Vector<char>::New(length + 1); 123b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch memcpy(copy.start(), builder.Finalize(), copy.length()); 124b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch masm()->RecordComment(copy.start()); 125b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 126b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 127b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 128b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochbool LCodeGen::GeneratePrologue() { 129b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(is_generating()); 130b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 131b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#ifdef DEBUG 132b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (strlen(FLAG_stop_at) > 0 && 133b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 134b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ int3(); 135b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 136b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif 137b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Strict mode functions need to replace the receiver with undefined 139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // when called as functions (without an explicit receiver 140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // object). rcx is zero for method calls and non-zero for function 141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // calls. 1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!info_->is_classic_mode() || info_->is_native()) { 143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testq(rcx, rcx); 145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &ok, Label::kNear); 146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // +1 for return address. 147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; 148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(Operand(rsp, receiver_offset), kScratchRegister); 150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&ok); 151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 153b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ push(rbp); // Caller's frame pointer. 154b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ movq(rbp, rsp); 155b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ push(rsi); // Callee's context. 156b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ push(rdi); // Callee's JS function. 157b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 158b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Reserve space for the stack slots needed by the code. 159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int slots = GetStackSlotCount(); 160b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (slots > 0) { 161b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (FLAG_debug_code) { 1628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Set(rax, slots); 163b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ movq(kScratchRegister, kSlotsZapValue, RelocInfo::NONE); 164b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label loop; 165b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&loop); 166b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ push(kScratchRegister); 167b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ decl(rax); 168b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ j(not_zero, &loop); 169b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 170b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ subq(rsp, Immediate(slots * kPointerSize)); 171b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#ifdef _MSC_VER 172b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // On windows, you may not access the stack more than one page below 173b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // the most recently mapped page. To make the allocated area randomly 174b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // accessible, we write to each page in turn (the value is irrelevant). 175b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const int kPageSize = 4 * KB; 176b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int offset = slots * kPointerSize - kPageSize; 177b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch offset > 0; 178b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch offset -= kPageSize) { 179b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ movq(Operand(rsp, offset), rax); 180b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 181b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif 182b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 183b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 184b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Possibly allocate a local context. 186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (heap_slots > 0) { 188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Comment(";;; Allocate local context"); 189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Argument to NewContext is the function, which is still in rdi. 190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(rdi); 191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (heap_slots <= FastNewContextStub::kMaximumSlots) { 192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FastNewContextStub stub(heap_slots); 193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallStub(&stub); 194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 1953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CallRuntime(Runtime::kNewFunctionContext, 1); 196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1972b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepoint(Safepoint::kNoLazyDeopt); 198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Context is returned in both rax and rsi. It replaces the context 199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // passed to us. It's saved in the stack and kept live in rsi. 200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy any necessary parameters into the context. 203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int num_parameters = scope()->num_parameters(); 204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < num_parameters; i++) { 205589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = scope()->parameter(i); 206589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int parameter_offset = StandardFrameConstants::kCallerSPOffset + 208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (num_parameters - 1 - i) * kPointerSize; 209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Load parameter from stack. 210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rax, Operand(rbp, parameter_offset)); 211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Store it in the context. 212589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int context_offset = Context::SlotOffset(var->index()); 213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(Operand(rsi, context_offset), rax); 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the write barrier. This clobbers rax and rbx. 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot(rsi, context_offset, rax, rbx, kSaveFPRegs); 216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Comment(";;; End allocate local context"); 219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 221b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Trace the call. 222b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (FLAG_trace) { 223b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ CallRuntime(Runtime::kTraceEnter, 0); 224b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 225b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return !is_aborted(); 226b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 227b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 228b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 229b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochbool LCodeGen::GenerateBody() { 230b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(is_generating()); 231b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch bool emit_instructions = true; 232b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (current_instruction_ = 0; 233b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch !is_aborted() && current_instruction_ < instructions_->length(); 234b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch current_instruction_++) { 235b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LInstruction* instr = instructions_->at(current_instruction_); 236b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (instr->IsLabel()) { 237b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LLabel* label = LLabel::cast(instr); 238b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch emit_instructions = !label->HasReplacement(); 239b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 240b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 241b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (emit_instructions) { 242b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic()); 243b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch instr->CompileToNative(this); 244b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 245b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 2462b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); 247b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return !is_aborted(); 248b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 249b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 250b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool LCodeGen::GenerateJumpTable() { 252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < jump_table_.length(); i++) { 25344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&jump_table_[i].label); 25444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Jump(jump_table_[i].address, RelocInfo::RUNTIME_ENTRY); 255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 256e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return !is_aborted(); 257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 260b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochbool LCodeGen::GenerateDeferredCode() { 261b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(is_generating()); 2623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (deferred_.length() > 0) { 2633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 2643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LDeferredCode* code = deferred_[i]; 2653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(code->entry()); 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Comment(";;; Deferred code @%d: %s.", 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch code->instruction_index(), 2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch code->instr()->Mnemonic()); 2693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch code->Generate(); 2703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(code->exit()); 2713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 272b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 273b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 274b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Deferred code is the last part of the instruction sequence. Mark 275b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // the generated code as done unless we bailed out. 276b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (!is_aborted()) status_ = DONE; 277b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return !is_aborted(); 278b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 279b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 280b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 281b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochbool LCodeGen::GenerateSafepointTable() { 282b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(is_done()); 283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch safepoints_.Emit(masm(), GetStackSlotCount()); 284b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return !is_aborted(); 285b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 286b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 287b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 288b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochRegister LCodeGen::ToRegister(int index) const { 289b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return Register::FromAllocationIndex(index); 290b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 291b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 292b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 293b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochXMMRegister LCodeGen::ToDoubleRegister(int index) const { 294b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return XMMRegister::FromAllocationIndex(index); 295b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 296b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 297b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 298b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochRegister LCodeGen::ToRegister(LOperand* op) const { 299b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(op->IsRegister()); 300b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return ToRegister(op->index()); 301b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 302b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 303b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 304b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochXMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { 305b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(op->IsDoubleRegister()); 306b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return ToDoubleRegister(op->index()); 307b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 308b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 309b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 310b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochbool LCodeGen::IsInteger32Constant(LConstantOperand* op) const { 311b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return op->IsConstantOperand() && 312b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch chunk_->LookupLiteralRepresentation(op).IsInteger32(); 313b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 314b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 315b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 316b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochbool LCodeGen::IsTaggedConstant(LConstantOperand* op) const { 317b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return op->IsConstantOperand() && 318b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch chunk_->LookupLiteralRepresentation(op).IsTagged(); 319b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 320b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 321b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 322b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochint LCodeGen::ToInteger32(LConstantOperand* op) const { 323b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<Object> value = chunk_->LookupLiteral(op); 324b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32()); 325b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) == 326b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch value->Number()); 327b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return static_cast<int32_t>(value->Number()); 328b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 329b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 330b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochdouble LCodeGen::ToDouble(LConstantOperand* op) const { 3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> value = chunk_->LookupLiteral(op); 3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return value->Number(); 3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 337b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochHandle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { 338b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<Object> literal = chunk_->LookupLiteral(op); 339e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged()); 340b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return literal; 341b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 342b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 343b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 344b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochOperand LCodeGen::ToOperand(LOperand* op) const { 345b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Does not handle registers. In X64 assembler, plain registers are not 346b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // representable as an Operand. 347b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); 348b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int index = op->index(); 349b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index >= 0) { 350b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Local or spill slot. Skip the frame pointer, function, and 351b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // context in the fixed part of the frame. 352b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return Operand(rbp, -(index + 3) * kPointerSize); 353b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 354b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Incoming parameter. Skip the return address. 355b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return Operand(rbp, -(index - 1) * kPointerSize); 356b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 357b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 358b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 359b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 360b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::WriteTranslation(LEnvironment* environment, 361b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Translation* translation) { 362b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (environment == NULL) return; 363b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 364b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // The translation includes one command per value in the environment. 365b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int translation_size = environment->values()->length(); 366b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // The output frame height does not include the parameters. 367b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int height = translation_size - environment->parameter_count(); 368b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 369b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch WriteTranslation(environment->outer(), translation); 370b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int closure_id = DefineDeoptimizationLiteral(environment->closure()); 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch switch (environment->frame_type()) { 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case JS_FUNCTION: 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch translation->BeginJSFrame(environment->ast_id(), closure_id, height); 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case JS_CONSTRUCT: 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch translation->BeginConstructStubFrame(closure_id, translation_size); 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case ARGUMENTS_ADAPTOR: 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); 3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch default: 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 384b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = 0; i < translation_size; ++i) { 385b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* value = environment->values()->at(i); 386b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // spilled_registers_ and spilled_double_registers_ are either 387b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // both NULL or both set. 388b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (environment->spilled_registers() != NULL && value != NULL) { 389b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (value->IsRegister() && 390b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch environment->spilled_registers()[value->index()] != NULL) { 391b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->MarkDuplicate(); 392b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AddToTranslation(translation, 393b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch environment->spilled_registers()[value->index()], 394b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch environment->HasTaggedValueAt(i)); 395b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if ( 396b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch value->IsDoubleRegister() && 397b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch environment->spilled_double_registers()[value->index()] != NULL) { 398b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->MarkDuplicate(); 399b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AddToTranslation( 400b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation, 401b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch environment->spilled_double_registers()[value->index()], 402b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch false); 403b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 404b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 405b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 406b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch AddToTranslation(translation, value, environment->HasTaggedValueAt(i)); 407b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 408b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 409b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 410b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 411b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::AddToTranslation(Translation* translation, 412b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* op, 413b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch bool is_tagged) { 414b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (op == NULL) { 415b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // TODO(twuerthinger): Introduce marker operands to indicate that this value 416b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // is not present and must be reconstructed from the deoptimizer. Currently 417b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // this is only used for the arguments object. 418b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreArgumentsObject(); 419b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (op->IsStackSlot()) { 420b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (is_tagged) { 421b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreStackSlot(op->index()); 422b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 423b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreInt32StackSlot(op->index()); 424b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 425b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (op->IsDoubleStackSlot()) { 426b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreDoubleStackSlot(op->index()); 427b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (op->IsArgument()) { 428b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(is_tagged); 429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int src_index = GetStackSlotCount() + op->index(); 430b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreStackSlot(src_index); 431b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (op->IsRegister()) { 432b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register reg = ToRegister(op); 433b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (is_tagged) { 434b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreRegister(reg); 435b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 436b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreInt32Register(reg); 437b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 438b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (op->IsDoubleRegister()) { 439b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch XMMRegister reg = ToDoubleRegister(op); 440b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreDoubleRegister(reg); 441b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (op->IsConstantOperand()) { 442b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<Object> literal = chunk()->LookupLiteral(LConstantOperand::cast(op)); 443b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int src_index = DefineDeoptimizationLiteral(literal); 444b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch translation->StoreLiteral(src_index); 445b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 446b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch UNREACHABLE(); 447b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 448b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 449b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 450b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::CallCodeGeneric(Handle<Code> code, 4528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::Mode mode, 4538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch LInstruction* instr, 4548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SafepointMode safepoint_mode, 4558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int argc) { 4562b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch EnsureSpaceForLazyDeopt(Deoptimizer::patch_size() - masm()->CallSize(code)); 4571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr != NULL); 4581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LPointerMap* pointers = instr->pointer_map(); 4591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RecordPosition(pointers->position()); 4601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ call(code, mode); 4612b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepointWithLazyDeopt(instr, safepoint_mode, argc); 462b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 463b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Signal that we don't inline smi code before these stubs in the 464b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // optimizing code generator. 465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (code->kind() == Code::BINARY_OP_IC || 466b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch code->kind() == Code::COMPARE_IC) { 467b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ nop(); 468b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 469b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 470b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 471b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::CallCode(Handle<Code> code, 4738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::Mode mode, 4748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch LInstruction* instr) { 4758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, 0); 4768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 4778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 4788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 47944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::CallRuntime(const Runtime::Function* function, 480b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int num_arguments, 481b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LInstruction* instr) { 4821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr != NULL); 4831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->HasPointerMap()); 4841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LPointerMap* pointers = instr->pointer_map(); 4851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RecordPosition(pointers->position()); 4861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CallRuntime(function, num_arguments); 4882b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); 4898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 4908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 4918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 4928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, 4938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int argc, 4948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch LInstruction* instr) { 4958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 4968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ CallRuntimeSaveDoubles(id); 4978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RecordSafepointWithRegisters( 4982b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); 499b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 500b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 501b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 5022b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdochvoid LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, 5032b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Safepoint::DeoptMode mode) { 504b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (!environment->HasBeenRegistered()) { 505b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Physical stack frame layout: 506b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // -x ............. -4 0 ..................................... y 507b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // [incoming arguments] [spill slots] [pushed outgoing arguments] 508b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 509b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Layout of the environment: 510b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // 0 ..................................................... size-1 511b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // [parameters] [locals] [expression stack including arguments] 512b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 513b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Layout of the translation: 514b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // 0 ........................................................ size - 1 + 4 515b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // [expression stack including arguments] [locals] [4 words] [parameters] 516b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // |>------------ translation_size ------------<| 517b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 518b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int frame_count = 0; 5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int jsframe_count = 0; 520b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (LEnvironment* e = environment; e != NULL; e = e->outer()) { 521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ++frame_count; 5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (e->frame_type() == JS_FUNCTION) { 5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++jsframe_count; 5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 525b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Translation translation(&translations_, frame_count, jsframe_count); 527b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch WriteTranslation(environment, &translation); 528b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int deoptimization_index = deoptimizations_.length(); 5292b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch int pc_offset = masm()->pc_offset(); 5302b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch environment->Register(deoptimization_index, 5312b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch translation.index(), 5322b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); 533b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch deoptimizations_.Add(environment); 534b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 535b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 536b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 537b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 538b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) { 5392b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 5401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(environment->HasBeenRegistered()); 5411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int id = environment->deoptimization_index(); 5421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER); 5431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (entry == NULL) { 5441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Abort("bailout was not prepared"); 5451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return; 5461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 5471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 5481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (cc == no_condition) { 5491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Jump(entry, RelocInfo::RUNTIME_ENTRY); 5501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 551e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // We often have several deopts to the same entry, reuse the last 552e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // jump entry if this is the case. 55344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (jump_table_.is_empty() || 55444f0eee88ff00398ff7f715fab053374d808c90dSteve Block jump_table_.last().address != entry) { 5558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch jump_table_.Add(JumpTableEntry(entry)); 556e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 55744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(cc, &jump_table_.last().label); 5581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 559b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 560b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 561b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 562b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { 563b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int length = deoptimizations_.length(); 564b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (length == 0) return; 565b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<DeoptimizationInputData> data = 56644f0eee88ff00398ff7f715fab053374d808c90dSteve Block factory()->NewDeoptimizationInputData(length, TENURED); 567b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<ByteArray> translations = translations_.CreateByteArray(); 569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch data->SetTranslationByteArray(*translations); 570b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); 571b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 572b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<FixedArray> literals = 57344f0eee88ff00398ff7f715fab053374d808c90dSteve Block factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); 574b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = 0; i < deoptimization_literals_.length(); i++) { 575b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch literals->set(i, *deoptimization_literals_[i]); 576b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 577b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data->SetLiteralArray(*literals); 578b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 579b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id())); 580b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_)); 581b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 582b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Populate the deoptimization entries. 583b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = 0; i < length; i++) { 584b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LEnvironment* env = deoptimizations_[i]; 585b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data->SetAstId(i, Smi::FromInt(env->ast_id())); 586b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data->SetTranslationIndex(i, Smi::FromInt(env->translation_index())); 587b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch data->SetArgumentsStackHeight(i, 588b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Smi::FromInt(env->arguments_stack_height())); 5892b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch data->SetPc(i, Smi::FromInt(env->pc_offset())); 590b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 591b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch code->set_deoptimization_data(*data); 592b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 593b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 594b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 595b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochint LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) { 596b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int result = deoptimization_literals_.length(); 597b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = 0; i < deoptimization_literals_.length(); ++i) { 598b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (deoptimization_literals_[i].is_identical_to(literal)) return i; 599b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 600b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch deoptimization_literals_.Add(literal); 601b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return result; 602b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 603b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 604b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 605b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() { 606b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(deoptimization_literals_.length() == 0); 607b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 608b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const ZoneList<Handle<JSFunction> >* inlined_closures = 609b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch chunk()->inlined_closures(); 610b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 611b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = 0, length = inlined_closures->length(); 612b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch i < length; 613b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch i++) { 614b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch DefineDeoptimizationLiteral(inlined_closures->at(i)); 615b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 616b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 617b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch inlined_function_count_ = deoptimization_literals_.length(); 618b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 619b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 620b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 6212b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdochvoid LCodeGen::RecordSafepointWithLazyDeopt( 6222b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch LInstruction* instr, SafepointMode safepoint_mode, int argc) { 6232b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { 6242b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt); 6252b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch } else { 6262b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS); 6272b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepointWithRegisters( 6282b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch instr->pointer_map(), argc, Safepoint::kLazyDeopt); 6292b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch } 6302b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch} 6312b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch 6322b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch 6331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::RecordSafepoint( 6341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LPointerMap* pointers, 6351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Safepoint::Kind kind, 6361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int arguments, 6372b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Safepoint::DeoptMode deopt_mode) { 6388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(kind == expected_safepoint_kind_); 6398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 6403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands(); 6411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 642b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Safepoint safepoint = safepoints_.DefineSafepoint(masm(), 6432b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch kind, arguments, deopt_mode); 644b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = 0; i < operands->length(); i++) { 645b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* pointer = operands->at(i); 646b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (pointer->IsStackSlot()) { 647b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch safepoint.DefinePointerSlot(pointer->index()); 6481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { 6491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block safepoint.DefinePointerRegister(ToRegister(pointer)); 650b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 651b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 6521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (kind & Safepoint::kWithRegisters) { 6531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Register rsi always contains a pointer to the context. 6541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block safepoint.DefinePointerRegister(rsi); 6551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 6561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 6571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::RecordSafepoint(LPointerMap* pointers, 6602b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Safepoint::DeoptMode deopt_mode) { 6612b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); 662b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 663b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 664b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 6652b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdochvoid LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { 666e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LPointerMap empty_pointers(RelocInfo::kNoPosition); 6672b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepoint(&empty_pointers, deopt_mode); 668e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 669e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 670e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 671b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, 672b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int arguments, 6732b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Safepoint::DeoptMode deopt_mode) { 6742b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, deopt_mode); 675b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 676b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 677b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 678b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::RecordPosition(int position) { 6793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (position == RelocInfo::kNoPosition) return; 680b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch masm()->positions_recorder()->RecordPosition(position); 681b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 682b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 683b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 684b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLabel(LLabel* label) { 685b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (label->is_loop_header()) { 686b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Comment(";;; B%d - LOOP entry", label->block_id()); 687b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 688b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Comment(";;; B%d", label->block_id()); 689b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 690b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(label->label()); 691b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch current_block_ = label->block_id(); 692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DoGap(label); 693b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 694b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 695b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 696b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoParallelMove(LParallelMove* move) { 6971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block resolver_.Resolve(move); 698b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 699b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 700b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 701b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoGap(LGap* gap) { 702b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = LGap::FIRST_INNER_POSITION; 703b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch i <= LGap::LAST_INNER_POSITION; 704b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch i++) { 705b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); 706b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LParallelMove* move = gap->GetParallelMove(inner_pos); 707b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (move != NULL) DoParallelMove(move); 708b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 709b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 710b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 711b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoInstructionGap(LInstructionGap* instr) { 713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DoGap(instr); 714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 717b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoParameter(LParameter* instr) { 718b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Nothing to do. 719b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 720b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 721b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 722b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallStub(LCallStub* instr) { 7231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 7241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->hydrogen()->major_key()) { 7251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case CodeStub::RegExpConstructResult: { 7261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RegExpConstructResultStub stub; 7271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 7281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 7291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case CodeStub::RegExpExec: { 7311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RegExpExecStub stub; 7321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 7331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 7341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case CodeStub::SubString: { 7361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SubStringStub stub; 7371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 7381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 7391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case CodeStub::NumberToString: { 7411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block NumberToStringStub stub; 7421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 7431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 7441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case CodeStub::StringAdd: { 7461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block StringAddStub stub(NO_STRING_ADD_FLAGS); 7471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 7481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 7491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case CodeStub::StringCompare: { 7511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block StringCompareStub stub; 7521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 7531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 7541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case CodeStub::TranscendentalCache: { 756e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub stub(instr->transcendental_type(), 757e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub::TAGGED); 7581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 7591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 7601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 7621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 7631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 764b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 765b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 766b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 767b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 768b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Nothing to do. 769b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 770b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 771b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 772b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoModI(LModI* instr) { 77344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->HasPowerOf2Divisor()) { 77444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register dividend = ToRegister(instr->InputAt(0)); 775e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 77644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t divisor = 77744f0eee88ff00398ff7f715fab053374d808c90dSteve Block HConstant::cast(instr->hydrogen()->right())->Integer32Value(); 778e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 77944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (divisor < 0) divisor = -divisor; 780e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label positive_dividend, done; 78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ testl(dividend, dividend); 783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_sign, &positive_dividend, Label::kNear); 78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ negl(dividend); 78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ andl(dividend, Immediate(divisor - 1)); 78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ negl(dividend); 78744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &done, Label::kNear); 78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(no_condition, instr->environment()); 7907d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } else { 791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 79244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 79344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&positive_dividend); 79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ andl(dividend, Immediate(divisor - 1)); 79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 79644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, remainder_eq_dividend, slow, do_subtraction, both_positive; 798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left_reg = ToRegister(instr->InputAt(0)); 799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right_reg = ToRegister(instr->InputAt(1)); 800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result_reg = ToRegister(instr->result()); 801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(left_reg.is(rax)); 803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(result_reg.is(rdx)); 80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!right_reg.is(rax)); 80544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!right_reg.is(rdx)); 806e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 80744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check for x % 0. 80844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ testl(right_reg, right_reg); 81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(zero, instr->environment()); 81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 812e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testl(left_reg, left_reg); 814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &remainder_eq_dividend, Label::kNear); 815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(sign, &slow, Label::kNear); 816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testl(right_reg, right_reg); 818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_sign, &both_positive, Label::kNear); 819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The sign of the divisor doesn't matter. 820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ neg(right_reg); 821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&both_positive); 823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the dividend is smaller than the nonnegative 824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // divisor, the dividend is the result. 825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpl(left_reg, right_reg); 826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(less, &remainder_eq_dividend, Label::kNear); 827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the divisor is a PowerOfTwo integer. 829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch = ToRegister(instr->TempAt(0)); 830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movl(scratch, right_reg); 831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subl(scratch, Immediate(1)); 832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testl(scratch, right_reg); 833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &do_subtraction, Label::kNear); 834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ andl(left_reg, scratch); 835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&remainder_eq_dividend, Label::kNear); 836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&do_subtraction); 838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kUnfolds = 3; 839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Try a few subtractions of the dividend. 840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movl(scratch, left_reg); 841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < kUnfolds; i++) { 842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Reduce the dividend by the divisor. 843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subl(left_reg, right_reg); 844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the dividend is less than the divisor. 845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpl(left_reg, right_reg); 846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(less, &remainder_eq_dividend, Label::kNear); 847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movl(left_reg, scratch); 849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Slow case, using idiv instruction. 851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 85244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Sign extend eax to edx. 85344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (We are using only the low 32 bits of the values.) 85444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cdq(); 85544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 85644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check for (0 % -x) that will produce negative zero. 85744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label positive_left; 859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testl(left_reg, left_reg); 861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_sign, &positive_left, Label::kNear); 86244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ idivl(right_reg); 86344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 86444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Test the remainder for 0, because then the result would be -0. 865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testl(result_reg, result_reg); 866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &done, Label::kNear); 86744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(no_condition, instr->environment()); 86944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&positive_left); 87044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ idivl(right_reg); 87144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 87244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 87344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ idivl(right_reg); 87444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&remainder_eq_dividend); 878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movl(result_reg, left_reg); 879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 881e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 882b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 883b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 884b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 885b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoDivI(LDivI* instr) { 8861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* right = instr->InputAt(1); 8871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 8881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->InputAt(0)).is(rax)); 8891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!ToRegister(instr->InputAt(1)).is(rax)); 8901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!ToRegister(instr->InputAt(1)).is(rdx)); 8911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register left_reg = rax; 8931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for x / 0. 8951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register right_reg = ToRegister(right); 8961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 8971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(right_reg, right_reg); 8981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(zero, instr->environment()); 8991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for (0 / -x) that will produce negative zero. 9021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label left_not_zero; 9041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(left_reg, left_reg); 905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &left_not_zero, Label::kNear); 9061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(right_reg, right_reg); 9071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(sign, instr->environment()); 9081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&left_not_zero); 9091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for (-kMinInt / -1). 9121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label left_not_min_int; 9141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpl(left_reg, Immediate(kMinInt)); 915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &left_not_min_int, Label::kNear); 9161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpl(right_reg, Immediate(-1)); 9171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(zero, instr->environment()); 9181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&left_not_min_int); 9191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Sign extend to rdx. 9221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cdq(); 9231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ idivl(right_reg); 9241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Deoptimize if remainder is not 0. 9261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(rdx, rdx); 9271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_zero, instr->environment()); 9281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 929b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 930b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 931b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMulI(LMulI* instr) { 9321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register left = ToRegister(instr->InputAt(0)); 9331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* right = instr->InputAt(1); 9341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 9361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movl(kScratchRegister, left); 9371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 93944f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool can_overflow = 94044f0eee88ff00398ff7f715fab053374d808c90dSteve Block instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 9411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (right->IsConstantOperand()) { 9421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int right_value = ToInteger32(LConstantOperand::cast(right)); 94344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (right_value == -1) { 94444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ negl(left); 94544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (right_value == 0) { 94644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ xorl(left, left); 94744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (right_value == 2) { 94844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ addl(left, left); 94944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (!can_overflow) { 95044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If the multiplication is known to not overflow, we 95144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // can use operations that don't set the overflow flag 95244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // correctly. 95344f0eee88ff00398ff7f715fab053374d808c90dSteve Block switch (right_value) { 95444f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 1: 95544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Do nothing. 95644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 95744f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 3: 95844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ leal(left, Operand(left, left, times_2, 0)); 95944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 96044f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 4: 96144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ shll(left, Immediate(2)); 96244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 96344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 5: 96444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ leal(left, Operand(left, left, times_4, 0)); 96544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 96644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 8: 96744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ shll(left, Immediate(3)); 96844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 96944f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 9: 97044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ leal(left, Operand(left, left, times_8, 0)); 97144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 97244f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 16: 97344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ shll(left, Immediate(4)); 97444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 97544f0eee88ff00398ff7f715fab053374d808c90dSteve Block default: 97644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ imull(left, left, Immediate(right_value)); 97744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 97844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 97944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 98044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ imull(left, left, Immediate(right_value)); 98144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 9821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (right->IsStackSlot()) { 9831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ imull(left, ToOperand(right)); 9841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 9851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ imull(left, ToRegister(right)); 9861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 98844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (can_overflow) { 9891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(overflow, instr->environment()); 9901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 9931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Bail out if the result is supposed to be negative zero. 994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 9951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(left, left); 996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &done, Label::kNear); 9971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (right->IsConstantOperand()) { 9981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (ToInteger32(LConstantOperand::cast(right)) <= 0) { 9991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(no_condition, instr->environment()); 10001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (right->IsStackSlot()) { 10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ orl(kScratchRegister, ToOperand(right)); 10031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(sign, instr->environment()); 10041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 10051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Test the non-zero operand for negative sign. 10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ orl(kScratchRegister, ToRegister(right)); 10071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(sign, instr->environment()); 10081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 10101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 1012b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1013b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1014b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoBitI(LBitI* instr) { 10151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* left = instr->InputAt(0); 10161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* right = instr->InputAt(1); 10171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(left->Equals(instr->result())); 10181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(left->IsRegister()); 10191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (right->IsConstantOperand()) { 10211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int right_operand = ToInteger32(LConstantOperand::cast(right)); 10221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->op()) { 10231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_AND: 10241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ andl(ToRegister(left), Immediate(right_operand)); 10251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_OR: 10271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orl(ToRegister(left), Immediate(right_operand)); 10281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_XOR: 10301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ xorl(ToRegister(left), Immediate(right_operand)); 10311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 10331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 10341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (right->IsStackSlot()) { 10371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->op()) { 10381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_AND: 10391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ andl(ToRegister(left), ToOperand(right)); 10401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_OR: 10421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orl(ToRegister(left), ToOperand(right)); 10431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_XOR: 10451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ xorl(ToRegister(left), ToOperand(right)); 10461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 10481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 10491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 10521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(right->IsRegister()); 10531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->op()) { 10541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_AND: 10551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ andl(ToRegister(left), ToRegister(right)); 10561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_OR: 10581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ orl(ToRegister(left), ToRegister(right)); 10591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::BIT_XOR: 10611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ xorl(ToRegister(left), ToRegister(right)); 10621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 10641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 10651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 1069b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1070b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1071b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoShiftI(LShiftI* instr) { 10721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* left = instr->InputAt(0); 10731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* right = instr->InputAt(1); 10741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(left->Equals(instr->result())); 10751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(left->IsRegister()); 10761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (right->IsRegister()) { 10771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(right).is(rcx)); 10781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->op()) { 10801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::SAR: 10811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ sarl_cl(ToRegister(left)); 10821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::SHR: 10841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ shrl_cl(ToRegister(left)); 10851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->can_deopt()) { 10861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(ToRegister(left), ToRegister(left)); 10871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(negative, instr->environment()); 10881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::SHL: 10911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ shll_cl(ToRegister(left)); 10921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 10941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 10951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 10961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 10971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 10981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int value = ToInteger32(LConstantOperand::cast(right)); 10991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); 11001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block switch (instr->op()) { 11011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::SAR: 11021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (shift_count != 0) { 11031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ sarl(ToRegister(left), Immediate(shift_count)); 11041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 11051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 11061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::SHR: 11071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (shift_count == 0 && instr->can_deopt()) { 11081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(ToRegister(left), ToRegister(left)); 11091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(negative, instr->environment()); 11101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 11111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ shrl(ToRegister(left), Immediate(shift_count)); 11121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 11131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 11141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case Token::SHL: 11151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (shift_count != 0) { 11161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ shll(ToRegister(left), Immediate(shift_count)); 11171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 11181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 11191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 11201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 11211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 11221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 11231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1124b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1125b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1126b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1127b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoSubI(LSubI* instr) { 11281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* left = instr->InputAt(0); 11291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* right = instr->InputAt(1); 11301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(left->Equals(instr->result())); 11311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 11321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (right->IsConstantOperand()) { 11331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ subl(ToRegister(left), 11341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(ToInteger32(LConstantOperand::cast(right)))); 11351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (right->IsRegister()) { 11361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ subl(ToRegister(left), ToRegister(right)); 11371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 11381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ subl(ToRegister(left), ToOperand(right)); 11391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 11401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 11411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 11421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(overflow, instr->environment()); 11431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1144b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1145b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1146b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1147b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoConstantI(LConstantI* instr) { 1148b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(instr->result()->IsRegister()); 11498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Set(ToRegister(instr->result()), instr->value()); 1150b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1151b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1152b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1153b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoConstantD(LConstantD* instr) { 1154b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(instr->result()->IsDoubleRegister()); 1155b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch XMMRegister res = ToDoubleRegister(instr->result()); 1156b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch double v = instr->value(); 1157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch uint64_t int_val = BitCast<uint64_t, double>(v); 1158b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Use xor to produce +0.0 in a fast and compact way, but avoid to 1159b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // do so if the constant is -0.0. 1160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (int_val == 0) { 1161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(res, res); 1162b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 1163b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register tmp = ToRegister(instr->TempAt(0)); 1164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Set(tmp, int_val); 1165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(res, tmp); 1166b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1167b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1168b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1169b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1170b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoConstantT(LConstantT* instr) { 11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> value = instr->value(); 11723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (value->IsSmi()) { 11733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(ToRegister(instr->result()), value); 11743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 11753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(ToRegister(instr->result()), 11763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<HeapObject>::cast(value)); 11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1178b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1179b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1180b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1181b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { 11821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 11831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register array = ToRegister(instr->InputAt(0)); 11841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, FieldOperand(array, JSArray::kLengthOffset)); 1185b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1186b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1187b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 118869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { 11891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 11901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register array = ToRegister(instr->InputAt(0)); 119169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movq(result, FieldOperand(array, FixedArrayBase::kLengthOffset)); 1192b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1193b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1194b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 11953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoElementsKind(LElementsKind* instr) { 11963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register result = ToRegister(instr->result()); 11973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register input = ToRegister(instr->InputAt(0)); 11983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 11993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Load map into |result|. 12003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(result, FieldOperand(input, HeapObject::kMapOffset)); 12013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Load the map's "bit field 2" into |result|. We only need the first byte. 12023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movzxbq(result, FieldOperand(result, Map::kBitField2Offset)); 12033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Retrieve elements_kind from bit field 2. 12043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ and_(result, Immediate(Map::kElementsKindMask)); 12053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ shr(result, Immediate(Map::kElementsKindShift)); 12063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 12073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 12083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1209b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoValueOf(LValueOf* instr) { 1210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register input = ToRegister(instr->InputAt(0)); 1211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 1212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(input.is(result)); 1213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 1214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If the object is a smi return the object. 1215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(input, &done, Label::kNear); 1216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If the object is not a value type, return the object. 1218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); 1219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &done, Label::kNear); 1220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, FieldOperand(input, JSValue::kValueOffset)); 1221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 1223b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1224b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1225b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 12263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDateField(LDateField* instr) { 12273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object = ToRegister(instr->InputAt(0)); 12283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result = ToRegister(instr->result()); 12293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi* index = instr->index(); 12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label runtime, done; 12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(object.is(result)); 12323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(object.is(rax)); 12333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 12343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG 12353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AbortIfSmi(object); 12363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister); 12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(equal, "Trying to get date field from non-date."); 12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (index->value() == 0) { 12413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(result, FieldOperand(object, JSDate::kValueOffset)); 12423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 12433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (index->value() < JSDate::kFirstUncachedField) { 12443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 12453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(kScratchRegister, stamp); 12463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(kScratchRegister, FieldOperand(object, 12473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSDate::kCacheStampOffset)); 12483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &runtime, Label::kNear); 12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(result, FieldOperand(object, JSDate::kValueOffset + 12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kPointerSize * index->value())); 12513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&runtime); 12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(2); 12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef _WIN64 12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rcx, object); 12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdx, index, RelocInfo::NONE); 12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#else 12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, object); 12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rsi, index, RelocInfo::NONE); 12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 12623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1269b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoBitNotI(LBitNotI* instr) { 12701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* input = instr->InputAt(0); 12711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(input->Equals(instr->result())); 12721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ not_(ToRegister(input)); 1273b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1274b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1275b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1276b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoThrow(LThrow* instr) { 12771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(ToRegister(instr->InputAt(0))); 12781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallRuntime(Runtime::kThrow, 1, instr); 12791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_debug_code) { 12811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Comment("Unreachable code."); 12821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ int3(); 12831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1284b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1285b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1286b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1287b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoAddI(LAddI* instr) { 1288b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* left = instr->InputAt(0); 1289b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* right = instr->InputAt(1); 1290b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(left->Equals(instr->result())); 1291b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1292b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (right->IsConstantOperand()) { 1293b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ addl(ToRegister(left), 1294b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Immediate(ToInteger32(LConstantOperand::cast(right)))); 1295b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (right->IsRegister()) { 1296b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ addl(ToRegister(left), ToRegister(right)); 1297b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 1298b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ addl(ToRegister(left), ToOperand(right)); 1299b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1300b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1301b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1302b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch DeoptimizeIf(overflow, instr->environment()); 1303b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1304b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1305b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1306b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1307b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoArithmeticD(LArithmeticD* instr) { 1308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister left = ToDoubleRegister(instr->InputAt(0)); 1309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister right = ToDoubleRegister(instr->InputAt(1)); 1310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister result = ToDoubleRegister(instr->result()); 1311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // All operations except MOD are computed in-place. 1312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(instr->op() == Token::MOD || left.is(result)); 1313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch switch (instr->op()) { 1314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::ADD: 1315e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ addsd(left, right); 1316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::SUB: 1318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ subsd(left, right); 1319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::MUL: 1321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mulsd(left, right); 1322e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::DIV: 1324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ divsd(left, right); 1325e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1326e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case Token::MOD: 1327e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ PrepareCallCFunction(2); 1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movaps(xmm0, left); 1329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(right.is(xmm1)); 133044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CallCFunction( 133144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::double_fp_operation(Token::MOD, isolate()), 2); 1332e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movaps(result, xmm0); 1334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1335e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch default: 1336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UNREACHABLE(); 1337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 1338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1339b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1340b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1341b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1342b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoArithmeticT(LArithmeticT* instr) { 1343b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(ToRegister(instr->InputAt(0)).is(rdx)); 1344b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(ToRegister(instr->InputAt(1)).is(rax)); 1345b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(ToRegister(instr->result()).is(rax)); 1346b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch BinaryOpStub stub(instr->op(), NO_OVERWRITE); 1348b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 134918a6f57610d404676fb0db2114fd7ad91e0402b0Ben Murdoch __ nop(); // Signals no inlined code. 1350b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1351b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1352b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1353b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochint LCodeGen::GetNextEmittedBlock(int block) { 1354b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int i = block + 1; i < graph()->blocks()->length(); ++i) { 1355b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LLabel* label = chunk_->GetLabel(i); 1356b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (!label->HasReplacement()) return i; 1357b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1358b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return -1; 1359b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1360b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1361b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1362b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::EmitBranch(int left_block, int right_block, Condition cc) { 13631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int next_block = GetNextEmittedBlock(current_block_); 13641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block right_block = chunk_->LookupDestination(right_block); 13651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block left_block = chunk_->LookupDestination(left_block); 13661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 13671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (right_block == left_block) { 13681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitGoto(left_block); 13691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (left_block == next_block) { 13701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); 13711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (right_block == next_block) { 13721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(cc, chunk_->GetAssemblyLabel(left_block)); 13731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 13741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(cc, chunk_->GetAssemblyLabel(left_block)); 13751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (cc != always) { 13761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ jmp(chunk_->GetAssemblyLabel(right_block)); 13771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 13781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1379b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1380b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1381b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1382b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoBranch(LBranch* instr) { 13831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 13841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 13851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 13863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Representation r = instr->hydrogen()->value()->representation(); 13871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (r.IsInteger32()) { 13881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->InputAt(0)); 13891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(reg, reg); 13901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, not_zero); 13911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (r.IsDouble()) { 13921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); 1393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(xmm0, xmm0); 13941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ucomisd(reg, xmm0); 13951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, not_equal); 13961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 13971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(r.IsTagged()); 13981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->InputAt(0)); 13993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HType type = instr->hydrogen()->value()->type(); 14001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (type.IsBoolean()) { 140144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareRoot(reg, Heap::kTrueValueRootIndex); 14021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, equal); 14031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (type.IsSmi()) { 14041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiCompare(reg, Smi::FromInt(0)); 14051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, not_equal); 14061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 14071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* true_label = chunk_->GetAssemblyLabel(true_block); 14081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* false_label = chunk_->GetAssemblyLabel(false_block); 14091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 141069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); 141169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Avoid deopts in the case where we've never executed this path before. 141269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); 141369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 141469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::UNDEFINED)) { 141569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // undefined -> false. 141669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); 141769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, false_label); 141869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 141969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::BOOLEAN)) { 142069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // true -> true. 142169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(reg, Heap::kTrueValueRootIndex); 142269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, true_label); 142369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // false -> false. 142469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(reg, Heap::kFalseValueRootIndex); 142569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, false_label); 142669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 142769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::NULL_TYPE)) { 142869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // 'null' -> false. 142969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(reg, Heap::kNullValueRootIndex); 143069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, false_label); 143169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 143269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 143369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::SMI)) { 143469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Smis: 0 -> false, all other -> true. 143569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Cmp(reg, Smi::FromInt(0)); 143669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, false_label); 143769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ JumpIfSmi(reg, true_label); 143869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (expected.NeedsMap()) { 143969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // If we need a map later and have a Smi -> deopt. 144069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ testb(reg, Immediate(kSmiTagMask)); 144169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(zero, instr->environment()); 144269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 144369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 144469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch const Register map = kScratchRegister; 144569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.NeedsMap()) { 144669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movq(map, FieldOperand(reg, HeapObject::kMapOffset)); 144769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 144869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.CanBeUndetectable()) { 144969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Undetectable -> false. 145069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ testb(FieldOperand(map, Map::kBitFieldOffset), 145169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Immediate(1 << Map::kIsUndetectable)); 145269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(not_zero, false_label); 145369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 145469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 145569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 145669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { 145769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // spec object -> true. 145869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); 145969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(above_equal, true_label); 146069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 146169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 146269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::STRING)) { 146369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // String value -> false iff empty. 146469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label not_string; 146569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); 146669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(above_equal, ¬_string, Label::kNear); 146769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmpq(FieldOperand(reg, String::kLengthOffset), Immediate(0)); 146869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(not_zero, true_label); 146969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ jmp(false_label); 147069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(¬_string); 147169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 147269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 147369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { 147469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // heap number -> false iff +0, -0, or NaN. 147569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label not_heap_number; 147669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); 147769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(not_equal, ¬_heap_number, Label::kNear); 147869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ xorps(xmm0, xmm0); 147969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); 148069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(zero, false_label); 148169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ jmp(true_label); 148269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(¬_heap_number); 148369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 148469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 148569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // We've seen something for the first time -> deopt. 148669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(no_condition, instr->environment()); 14871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 14881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1489b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1490b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1491b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 14923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::EmitGoto(int block) { 1493b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch block = chunk_->LookupDestination(block); 1494b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int next_block = GetNextEmittedBlock(current_block_); 1495b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (block != next_block) { 14963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(chunk_->GetAssemblyLabel(block)); 1497b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1498b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1499b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1500b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1501b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoGoto(LGoto* instr) { 15023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitGoto(instr->block_id()); 1503b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1504b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1505b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 15061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockinline Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { 1507b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Condition cond = no_condition; 1508b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch switch (op) { 1509b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::EQ: 1510b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::EQ_STRICT: 1511b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch cond = equal; 1512b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch break; 1513b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::LT: 1514b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch cond = is_unsigned ? below : less; 1515b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch break; 1516b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::GT: 1517b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch cond = is_unsigned ? above : greater; 1518b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch break; 1519b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::LTE: 1520b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch cond = is_unsigned ? below_equal : less_equal; 1521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch break; 1522b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::GTE: 1523b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch cond = is_unsigned ? above_equal : greater_equal; 1524b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch break; 1525b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::IN: 1526b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch case Token::INSTANCEOF: 1527b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch default: 1528b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch UNREACHABLE(); 1529b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1530b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return cond; 1531b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1532b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1533b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1534b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 15351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* left = instr->InputAt(0); 15361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* right = instr->InputAt(1); 15371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 15381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc = TokenToCondition(instr->op(), instr->is_double()); 15401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (left->IsConstantOperand() && right->IsConstantOperand()) { 15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We can statically evaluate the comparison. 15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch double left_val = ToDouble(LConstantOperand::cast(left)); 15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch double right_val = ToDouble(LConstantOperand::cast(right)); 15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int next_block = 15463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EvalComparison(instr->op(), left_val, right_val) ? true_block 15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : false_block; 15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitGoto(next_block); 15491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->is_double()) { 15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Don't base result on EFLAGS when a NaN is involved. Instead 15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // jump to the false block. 15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); 15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); 15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int32_t value; 15573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (right->IsConstantOperand()) { 15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = ToInteger32(LConstantOperand::cast(right)); 15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpl(ToRegister(left), Immediate(value)); 15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (left->IsConstantOperand()) { 15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = ToInteger32(LConstantOperand::cast(left)); 15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (right->IsRegister()) { 15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpl(ToRegister(right), Immediate(value)); 15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpl(ToOperand(right), Immediate(value)); 15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We transposed the operands. Reverse the condition. 15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cc = ReverseCondition(cc); 15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (right->IsRegister()) { 15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpl(ToRegister(left), ToRegister(right)); 15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpl(ToRegister(left), ToOperand(right)); 15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitBranch(true_block, false_block, cc); 15781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1579b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1580b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1581b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 15823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { 15831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register left = ToRegister(instr->InputAt(0)); 15841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register right = ToRegister(instr->InputAt(1)); 15851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 15861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 15871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 15881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpq(left, right); 15891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, equal); 1590b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1591b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1592b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 15933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { 1594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left = ToRegister(instr->InputAt(0)); 1595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 15963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 15983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmpq(left, Immediate(instr->hydrogen()->right())); 1599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitBranch(true_block, false_block, equal); 1600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 16033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { 16041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->InputAt(0)); 16051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 16061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the expression is known to be untagged or a smi, then it's definitely 16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // not null, and it can't be a an undetectable object. 16091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->representation().IsSpecialization() || 16101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block instr->hydrogen()->type().IsSmi()) { 16111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitGoto(false_block); 16121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return; 16131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 16141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::RootListIndex nil_value = instr->nil() == kNullValue ? 16173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kNullValueRootIndex : 16183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kUndefinedValueRootIndex; 16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(reg, nil_value); 16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->kind() == kStrictEquality) { 16211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, equal); 16221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::RootListIndex other_nil_value = instr->nil() == kNullValue ? 16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kUndefinedValueRootIndex : 16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kNullValueRootIndex; 16261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* true_label = chunk_->GetAssemblyLabel(true_block); 16271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* false_label = chunk_->GetAssemblyLabel(false_block); 16281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, true_label); 16293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(reg, other_nil_value); 16301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, true_label); 16311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(reg, false_label); 16321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for undetectable objects by looking in the bit field in 16331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the map. The object has already been smi checked. 16341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register scratch = ToRegister(instr->TempAt(0)); 16351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 16361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(FieldOperand(scratch, Map::kBitFieldOffset), 16371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(1 << Map::kIsUndetectable)); 16381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, not_zero); 16391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1640b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1641b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1642b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1643b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochCondition LCodeGen::EmitIsObject(Register input, 1644b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* is_not_object, 1645b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* is_object) { 16461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!input.is(kScratchRegister)); 16471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, is_not_object); 16491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(input, Heap::kNullValueRootIndex); 16511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, is_object); 16521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); 16541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Undetectable objects behave like undefined. 16551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), 16561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(1 << Map::kIsUndetectable)); 16571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_zero, is_not_object); 16581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movzxbl(kScratchRegister, 16601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); 16613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 16621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(below, is_not_object); 16633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 1664b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return below_equal; 1665b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1666b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1667b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1668b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { 16691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->InputAt(0)); 16701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 16721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 16731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* true_label = chunk_->GetAssemblyLabel(true_block); 16741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* false_label = chunk_->GetAssemblyLabel(false_block); 16751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition true_cond = EmitIsObject(reg, false_label, true_label); 16771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 16781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, true_cond); 1679b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1680b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1681b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 16823ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochCondition LCodeGen::EmitIsString(Register input, 16833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register temp1, 16843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* is_not_string) { 16853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(input, is_not_string); 16863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cond = masm_->IsObjectStringType(input, temp1, temp1); 16873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cond; 16893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 16903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { 16933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = ToRegister(instr->InputAt(0)); 16943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register temp = ToRegister(instr->TempAt(0)); 16953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 16973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 16983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* false_label = chunk_->GetAssemblyLabel(false_block); 16993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition true_cond = EmitIsString(reg, temp, false_label); 17013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitBranch(true_block, false_block, true_cond); 17033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 17043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1706b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 17071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 17081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 17091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition is_smi; 17111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->InputAt(0)->IsRegister()) { 17121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 17131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block is_smi = masm()->CheckSmi(input); 17141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 17151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand input = ToOperand(instr->InputAt(0)); 17161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block is_smi = masm()->CheckSmi(input); 17171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 17181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, is_smi); 17191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 17201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { 1723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register input = ToRegister(instr->InputAt(0)); 1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register temp = ToRegister(instr->TempAt(0)); 1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 1727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); 1730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); 1731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testb(FieldOperand(temp, Map::kBitFieldOffset), 1732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Immediate(1 << Map::kIsUndetectable)); 1733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitBranch(true_block, false_block, not_zero); 1734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 17373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { 17383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Token::Value op = instr->op(); 17393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 17403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 17413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = CompareIC::GetUninitialized(op); 17433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 17443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition condition = TokenToCondition(op, false); 17463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testq(rax, rax); 17473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitBranch(true_block, false_block, condition); 17493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 17503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic InstanceType TestType(HHasInstanceTypeAndBranch* instr) { 17531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block InstanceType from = instr->from(); 17541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block InstanceType to = instr->to(); 17551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (from == FIRST_TYPE) return to; 17561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(from == to || to == LAST_TYPE); 17571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return from; 17581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 17591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { 17621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block InstanceType from = instr->from(); 17631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block InstanceType to = instr->to(); 17641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (from == to) return equal; 17651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (to == LAST_TYPE) return above_equal; 17661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (from == FIRST_TYPE) return below_equal; 17671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 17681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return equal; 1769b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1770b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1771b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1772b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 17731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 17741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 17761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 17771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* false_label = chunk_->GetAssemblyLabel(false_block); 17791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, false_label); 17811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 17821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); 17831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); 1784b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1785b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1786b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1787e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { 1788e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register input = ToRegister(instr->InputAt(0)); 1789e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 1790e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1791e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (FLAG_debug_code) { 1792e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ AbortIfNotString(input); 1793e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1794e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movl(result, FieldOperand(input, String::kHashFieldOffset)); 1796e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(String::kHashShift >= kSmiTagSize); 1797e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ IndexFromHash(result, result); 1798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 1799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1801b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoHasCachedArrayIndexAndBranch( 1802b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LHasCachedArrayIndexAndBranch* instr) { 18031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 18041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 18061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 18071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(FieldOperand(input, String::kHashFieldOffset), 18091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(String::kContainsCachedArrayIndexMask)); 1810e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitBranch(true_block, false_block, equal); 1811b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1812b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1813b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 18141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Branches to a label or falls through with the answer in the z flag. 18153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Trashes the temp register. 1816b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::EmitClassOfTest(Label* is_true, 1817b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* is_false, 18181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<String> class_name, 1819b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register input, 18203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register temp, 18213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register temp2) { 18223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!input.is(temp)); 18233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!input.is(temp2)); 18243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!temp.is(temp2)); 18253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 18261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, is_false); 18271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (class_name->IsEqualTo(CStrVector("Function"))) { 18293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assuming the following assertions, we can use the same compares to test 18303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for both being a function type and being in the object type range. 18313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 18323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == 18333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FIRST_SPEC_OBJECT_TYPE + 1); 18343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == 18353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LAST_SPEC_OBJECT_TYPE - 1); 18363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 18373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp); 18383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(below, is_false); 18393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, is_true); 18403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE); 18413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, is_true); 18421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 18433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Faster code path to avoid two compares: subtract lower bound from the 18443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // actual type and do a signed compare with the width of the type range. 18453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); 18463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movzxbl(temp2, FieldOperand(temp, Map::kInstanceTypeOffset)); 18473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ subq(temp2, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(temp2, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - 18493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 18503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above, is_false); 18511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 18521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. 18541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check if the constructor in the map is a function. 18551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(temp, FieldOperand(temp, Map::kConstructorOffset)); 18561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Objects with a non-function constructor have class 'Object'. 18581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CmpObjectType(temp, JS_FUNCTION_TYPE, kScratchRegister); 18591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (class_name->IsEqualTo(CStrVector("Object"))) { 18601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_equal, is_true); 18611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 18621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_equal, is_false); 18631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 18641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // temp now contains the constructor function. Grab the 18661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // instance class name from there. 18671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset)); 18681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(temp, FieldOperand(temp, 18691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SharedFunctionInfo::kInstanceClassNameOffset)); 18701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The class name we are testing against is a symbol because it's a literal. 18711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The name in the constructor is a symbol because of the way the context is 18721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // booted. This routine isn't expected to work for random API-created 18731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // classes and it doesn't have to because you can't access it with natives 18741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // syntax. Since both sides are symbols it is sufficient to use an identity 18751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // comparison. 18761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(class_name->IsSymbol()); 18771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Cmp(temp, class_name); 18781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // End with the answer in the z flag. 1879b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1880b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1881b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1882b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 18831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 18841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register temp = ToRegister(instr->TempAt(0)); 18853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register temp2 = ToRegister(instr->TempAt(1)); 18861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<String> class_name = instr->hydrogen()->class_name(); 18871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 18891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 18901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* true_label = chunk_->GetAssemblyLabel(true_block); 18921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* false_label = chunk_->GetAssemblyLabel(false_block); 18931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); 18951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 18961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, equal); 1897b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1898b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1899b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1900b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { 19011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->InputAt(0)); 19021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = instr->true_block_id(); 19031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = instr->false_block_id(); 19041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 19051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); 19061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, equal); 1907b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1908b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1909b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1910b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoInstanceOf(LInstanceOf* instr) { 1911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InstanceofStub stub(InstanceofStub::kNoFlags); 1912e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(ToRegister(instr->InputAt(0))); 1913e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(ToRegister(instr->InputAt(1))); 1914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 1915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label true_value, done; 1916e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testq(rax, rax); 1917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &true_value, Label::kNear); 1918e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); 1919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 1920e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&true_value); 1921e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); 1922e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 1923b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1924b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1925b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1926b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 1927e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch class DeferredInstanceOfKnownGlobal: public LDeferredCode { 1928e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public: 1929e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeferredInstanceOfKnownGlobal(LCodeGen* codegen, 1930e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LInstanceOfKnownGlobal* instr) 1931e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch : LDeferredCode(codegen), instr_(instr) { } 1932e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual void Generate() { 19332b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); 1934e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 19353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 193644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* map_check() { return &map_check_; } 1937e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private: 1938e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LInstanceOfKnownGlobal* instr_; 193944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label map_check_; 1940e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch }; 1941e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1942e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeferredInstanceOfKnownGlobal* deferred; 1944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch deferred = new DeferredInstanceOfKnownGlobal(this, instr); 1945e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 194644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label done, false_result; 1947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register object = ToRegister(instr->InputAt(0)); 1948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // A Smi is not an instance of anything. 1950e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(object, &false_result); 1951e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 195244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // This is the inlined call site instanceof cache. The two occurences of the 195344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // hole value will be patched to the last map/result pair generated by the 195444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // instanceof stub. 1955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label cache_miss; 195644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Use a temp register to avoid memory operands with variable lengths. 195744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register map = ToRegister(instr->TempAt(0)); 195844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); 195944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(deferred->map_check()); // Label for calculating code patching. 19603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cache_cell = 19613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); 19623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(kScratchRegister, cache_cell, RelocInfo::GLOBAL_PROPERTY_CELL); 19633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(map, Operand(kScratchRegister, 0)); 1964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &cache_miss, Label::kNear); 196544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Patched to load either true or false. 196644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); 196744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG 196844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the code size between patch label and patch sites is invariant. 196944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label end_of_patched_code; 197044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&end_of_patched_code); 197144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(true); 197244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 197344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&done); 197444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 197544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The inlined call site cache did not match. Check for null and string 197644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // before calling the deferred code. 197744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&cache_miss); // Null is not an instance of anything. 1978e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(object, Heap::kNullValueRootIndex); 1979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &false_result, Label::kNear); 1980e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1981e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // String values are not instances of anything. 1982e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfNotString(object, kScratchRegister, deferred->entry()); 1983e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1984e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&false_result); 1985e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); 1986e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1987e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(deferred->exit()); 198844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 1989b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 1990b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 1991b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 19922b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdochvoid LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, 19932b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Label* map_check) { 19948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch { 19958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 19968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( 19978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); 19988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch InstanceofStub stub(flags); 1999e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 20008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ push(ToRegister(instr->InputAt(0))); 20013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushHeapObject(instr->function()); 20028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 20038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static const int kAdditionalDelta = 10; 20048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int delta = 20058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; 20068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(delta >= 0); 20078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ push_imm32(delta); 20088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 20098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // We are pushing three values on the stack but recording a 20108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // safepoint with two arguments because stub is going to 20118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // remove the third argument from the stack before jumping 20128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // to instanceof builtin on the slow path. 20138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallCodeGeneric(stub.GetCode(), 20148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::CODE_TARGET, 20158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr, 20168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RECORD_SAFEPOINT_WITH_REGISTERS, 20178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2); 20188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(delta == masm_->SizeOfCodeGeneratedSince(map_check)); 20192b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(instr->HasDeoptimizationEnvironment()); 20202b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch LEnvironment* env = instr->deoptimization_environment(); 20212b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 20228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Move result to a register that survives the end of the 20238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // PushSafepointRegisterScope. 20248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(kScratchRegister, rax); 20258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 2026e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testq(kScratchRegister, kScratchRegister); 2027e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label load_false; 2028e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label done; 2029e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(not_zero, &load_false); 2030e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(rax, Heap::kTrueValueRootIndex); 2031e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&done); 2032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&load_false); 2033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(rax, Heap::kFalseValueRootIndex); 2034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 2035b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2036b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2037b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2038b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCmpT(LCmpT* instr) { 20391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Token::Value op = instr->op(); 20401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 20411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Code> ic = CompareIC::GetUninitialized(op); 20421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(ic, RelocInfo::CODE_TARGET, instr); 20431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 20441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition condition = TokenToCondition(op, false); 2045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label true_value, done; 20461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testq(rax, rax); 2047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(condition, &true_value, Label::kNear); 20481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); 2049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 20501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&true_value); 20511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); 20521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 2053b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2054b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2055b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2056b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoReturn(LReturn* instr) { 2057b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (FLAG_trace) { 2058b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Preserve the return value on the stack and rely on the runtime 2059b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // call to return the value in the same register. 2060b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ push(rax); 2061b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ CallRuntime(Runtime::kTraceExit, 1); 2062b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 2063b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ movq(rsp, rbp); 2064b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ pop(rbp); 2065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret((GetParameterCount() + 1) * kPointerSize, rcx); 2066b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2067b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2068b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 20698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { 20701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 20713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadGlobalCell(result, instr->hydrogen()->cell()); 20723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 20731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 20741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(equal, instr->environment()); 20751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2076b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2077b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2078b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 20798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { 20808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(ToRegister(instr->global_object()).is(rax)); 20818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(ToRegister(instr->result()).is(rax)); 20828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 20838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Move(rcx, instr->name()); 20848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : 20858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::CODE_TARGET_CONTEXT; 20868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 20878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallCode(ic, mode, instr); 20888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 20898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 20908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 20918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { 20923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value = ToRegister(instr->value()); 20933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell_handle = instr->hydrogen()->cell(); 20943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 20951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If the cell we are storing to contains the hole it could have 20961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // been deleted from the property dictionary. In that case, we need 20971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to update the property details in the property dictionary to mark 20981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // it as no longer deleted. We deoptimize in that case. 20993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 21003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We have a temp because CompareRoot might clobber kScratchRegister. 21013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register cell = ToRegister(instr->TempAt(0)); 21023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!value.is(cell)); 21033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(cell, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); 21043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); 21051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(equal, instr->environment()); 21063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 21073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(Operand(cell, 0), value); 21083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 21093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 21103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(kScratchRegister, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); 21113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(Operand(kScratchRegister, 0), value); 21121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 21133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Cells are always rescanned, so no write barrier here. 2114b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2115b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2116b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 21178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { 21188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(ToRegister(instr->global_object()).is(rdx)); 21198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(ToRegister(instr->value()).is(rax)); 21208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 21218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Move(rcx, instr->name()); 21223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) 21238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ? isolate()->builtins()->StoreIC_Initialize_Strict() 21248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : isolate()->builtins()->StoreIC_Initialize(); 21258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); 21268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 21278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 21288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2129b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register context = ToRegister(instr->context()); 2131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 2132e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, ContextOperand(context, instr->slot_index())); 21333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 21343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 21353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->DeoptimizesOnHole()) { 21363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(equal, instr->environment()); 21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 21383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label is_not_hole; 21393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &is_not_hole, Label::kNear); 21403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 21413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&is_not_hole); 21423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 21433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 2148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register context = ToRegister(instr->context()); 2149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register value = ToRegister(instr->value()); 21503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand target = ContextOperand(context, instr->slot_index()); 21523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label skip_assignment; 21543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 21553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(target, Heap::kTheHoleValueRootIndex); 21563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->DeoptimizesOnHole()) { 21573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(equal, instr->environment()); 21583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 21593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &skip_assignment); 21603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 21613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 21623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(target, value); 21633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->NeedsWriteBarrier()) { 21653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HType type = instr->hydrogen()->value()->type(); 21663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck check_needed = 21673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 2168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int offset = Context::SlotOffset(instr->slot_index()); 2169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register scratch = ToRegister(instr->TempAt(0)); 21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot(context, 21713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 21723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 21743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kSaveFPRegs, 21753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 21763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch check_needed); 2177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 21783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&skip_assignment); 2180b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2181b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2182b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2183b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 21841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register object = ToRegister(instr->InputAt(0)); 21851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 21861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->is_in_object()) { 21871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); 21881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 21891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); 21901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, FieldOperand(result, instr->hydrogen()->offset())); 21911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2192b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2193b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2194b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::EmitLoadFieldOrConstantFunction(Register result, 2196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register object, 2197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Map> type, 2198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<String> name) { 21993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 220044f0eee88ff00398ff7f715fab053374d808c90dSteve Block type->LookupInDescriptors(NULL, *name, &lookup); 22013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(lookup.IsFound() && 2202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION)); 2203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (lookup.type() == FIELD) { 2204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int index = lookup.GetLocalFieldIndexFromMap(*type); 2205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int offset = index * kPointerSize; 2206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (index < 0) { 2207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Negative property indices are in-object properties, indexed 2208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // from the end of the fixed part of the object. 2209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(result, FieldOperand(object, offset + type->instance_size())); 2210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Non-negative property indices are in the properties array. 2212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); 2213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(result, FieldOperand(result, offset + FixedArray::kHeaderSize)); 2214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 221544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 2216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type)); 22173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(result, function); 221844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 221944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 222044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 222144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 222244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { 222344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register object = ToRegister(instr->object()); 222444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result = ToRegister(instr->result()); 222544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 222644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int map_count = instr->hydrogen()->types()->length(); 222744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<String> name = instr->hydrogen()->name(); 222844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 222944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (map_count == 0) { 223044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(instr->hydrogen()->need_generic()); 223144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(rcx, instr->hydrogen()->name()); 223244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 223344f0eee88ff00398ff7f715fab053374d808c90dSteve Block CallCode(ic, RelocInfo::CODE_TARGET, instr); 223444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 2235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 223644f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < map_count - 1; ++i) { 223744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Map> map = instr->hydrogen()->types()->at(i); 2238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label next; 223944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); 2240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &next, Label::kNear); 2241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitLoadFieldOrConstantFunction(result, object, map, name); 2242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 224344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&next); 224444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 224544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Map> map = instr->hydrogen()->types()->last(); 224644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); 224744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->need_generic()) { 2248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label generic; 2249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &generic, Label::kNear); 2250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitLoadFieldOrConstantFunction(result, object, map, name); 2251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 225244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&generic); 225344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(rcx, instr->hydrogen()->name()); 225444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 225544f0eee88ff00398ff7f715fab053374d808c90dSteve Block CallCode(ic, RelocInfo::CODE_TARGET, instr); 225644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 225744f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(not_equal, instr->environment()); 2258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitLoadFieldOrConstantFunction(result, object, map, name); 225944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 226044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 226144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 226244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 226344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 226444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2265b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { 22661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->object()).is(rax)); 22671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 22681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 22691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(rcx, instr->name()); 227044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 22711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(ic, RelocInfo::CODE_TARGET, instr); 2272b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2273b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2274b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2275b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { 22761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register function = ToRegister(instr->function()); 22771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 22781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 22791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the function really is a function. 22801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CmpObjectType(function, JS_FUNCTION_TYPE, result); 22811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_equal, instr->environment()); 22821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 22831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check whether the function has an instance prototype. 2284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label non_instance; 22851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(FieldOperand(result, Map::kBitFieldOffset), 22861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(1 << Map::kHasNonInstancePrototype)); 2287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &non_instance, Label::kNear); 22881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 22891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Get the prototype or initial map from the function. 22901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, 22911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 22921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 22931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the function has a prototype or an initial map. 22941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 22951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(equal, instr->environment()); 22961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 22971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If the function does not have an initial map, we're done. 2298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 22991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CmpObjectType(result, MAP_TYPE, kScratchRegister); 2300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &done, Label::kNear); 23011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 23021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Get the prototype from the initial map. 23031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, FieldOperand(result, Map::kPrototypeOffset)); 2304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 23051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 23061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Non-instance prototype: Fetch prototype from constructor field 23071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // in the function's map. 23081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&non_instance); 23091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, FieldOperand(result, Map::kConstructorOffset)); 23101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 23111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // All done. 23121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 2313b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2314b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2315b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2316b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadElements(LLoadElements* instr) { 23171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 23181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 23191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, FieldOperand(input, JSObject::kElementsOffset)); 23201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_debug_code) { 23213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label done, ok, fail; 232244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), 232344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::kFixedArrayMapRootIndex); 2324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &done, Label::kNear); 232544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), 232644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::kFixedCOWArrayMapRootIndex); 2327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &done, Label::kNear); 232844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register temp((result.is(rax)) ? rbx : rax); 232944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ push(temp); 233044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(temp, FieldOperand(result, HeapObject::kMapOffset)); 23313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movzxbq(temp, FieldOperand(temp, Map::kBitField2Offset)); 23323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ and_(temp, Immediate(Map::kElementsKindMask)); 23333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ shr(temp, Immediate(Map::kElementsKindShift)); 2334589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ cmpl(temp, Immediate(FAST_ELEMENTS)); 23353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(equal, &ok, Label::kNear); 2336589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ cmpl(temp, Immediate(FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND)); 23373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(less, &fail, Label::kNear); 2338589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ cmpl(temp, Immediate(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND)); 23393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(less_equal, &ok, Label::kNear); 23403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&fail); 23413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Abort("Check for fast or external elements failed"); 23423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&ok); 234344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ pop(temp); 23441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 23451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 23461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 23471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 23481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 234944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoLoadExternalArrayPointer( 235044f0eee88ff00398ff7f715fab053374d808c90dSteve Block LLoadExternalArrayPointer* instr) { 23511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 23521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 235344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(result, FieldOperand(input, 235444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalPixelArray::kExternalPointerOffset)); 2355b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2356b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2357b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2358b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { 2359e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register arguments = ToRegister(instr->arguments()); 2360e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register length = ToRegister(instr->length()); 2361e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 2362e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2363e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->index()->IsRegister()) { 2364e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ subl(length, ToRegister(instr->index())); 2365e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2366e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ subl(length, ToOperand(instr->index())); 2367e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2368e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(below_equal, instr->environment()); 2369e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2370e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // There are two words between the frame pointer and the last argument. 2371e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Subtracting from length accounts for one of them add one more. 2372e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, Operand(arguments, length, times_pointer_size, kPointerSize)); 2373b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2374b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2375b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2376b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { 23771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 23781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 23791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Load the result. 238069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movq(result, 238169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch BuildFastArrayOperand(instr->elements(), instr->key(), 2382589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch FAST_ELEMENTS, 238369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch FixedArray::kHeaderSize - kHeapObjectTag)); 23841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 23851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for the hole value. 2386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 2387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 2388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(equal, instr->environment()); 2389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 23933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoLoadKeyedFastDoubleElement( 23943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LLoadKeyedFastDoubleElement* instr) { 23953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch XMMRegister result(ToDoubleRegister(instr->result())); 23963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 23973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + 23983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sizeof(kHoleNanLower32); 23993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand hole_check_operand = BuildFastArrayOperand( 24003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->elements(), 24013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->key(), 24023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FAST_DOUBLE_ELEMENTS, 24033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset); 24043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); 24053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(equal, instr->environment()); 24063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 24073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand double_load_operand = BuildFastArrayOperand( 2408589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS, 24093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedDoubleArray::kHeaderSize - kHeapObjectTag); 24103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movsd(result, double_load_operand); 24113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 24123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 24133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 24143fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochOperand LCodeGen::BuildFastArrayOperand( 241569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch LOperand* elements_pointer, 24163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LOperand* key, 2417589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind, 24183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t offset) { 241969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register elements_pointer_reg = ToRegister(elements_pointer); 24203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int shift_size = ElementsKindToShiftSize(elements_kind); 2421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (key->IsConstantOperand()) { 2422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int constant_value = ToInteger32(LConstantOperand::cast(key)); 2423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (constant_value & 0xF0000000) { 2424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Abort("array index constant value too big"); 2425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 242669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return Operand(elements_pointer_reg, 24273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch constant_value * (1 << shift_size) + offset); 2428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); 243069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return Operand(elements_pointer_reg, ToRegister(key), 24313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch scale_factor, offset); 2432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 24331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 24341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 24351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 243644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoLoadKeyedSpecializedArrayElement( 243744f0eee88ff00398ff7f715fab053374d808c90dSteve Block LLoadKeyedSpecializedArrayElement* instr) { 2438589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = instr->elements_kind(); 24393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand operand(BuildFastArrayOperand(instr->external_pointer(), 24403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->key(), elements_kind, 0)); 2441589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 244244f0eee88ff00398ff7f715fab053374d808c90dSteve Block XMMRegister result(ToDoubleRegister(instr->result())); 2443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movss(result, operand); 244444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cvtss2sd(result, result); 2445589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 2446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsd(ToDoubleRegister(instr->result()), operand); 244744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 244844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result(ToRegister(instr->result())); 24493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 2450589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 2451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsxbq(result, operand); 245244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2453589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 2454589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 2455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movzxbq(result, operand); 245644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2457589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 2458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsxwq(result, operand); 245944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2460589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 2461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movzxwq(result, operand); 246244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2463589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 2464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsxlq(result, operand); 246544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2466589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 2467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movl(result, operand); 246844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ testl(result, result); 246944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // TODO(danno): we could be more clever here, perhaps having a special 247044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // version of the stub that detects if the overflow case actually 247144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // happens, and generate code that returns a double rather than int. 247244f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(negative, instr->environment()); 247344f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2474589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 2475589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 2476589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 24773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 2478589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 2479589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 2480589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 248144f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 248244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 248344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 248444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 2485b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2486b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2487b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2488b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { 2489e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->object()).is(rdx)); 2490e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->key()).is(rax)); 2491e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 249244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2493e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 2494b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2495b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2496b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2497b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { 2498e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 2499e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2500e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check for arguments adapter frame. 2501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, adapted; 2502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 250344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(Operand(result, StandardFrameConstants::kContextOffset), 250444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &adapted, Label::kNear); 2506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // No arguments adaptor frame. 2508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, rbp); 2509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 2510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2511e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Arguments adaptor frame present. 2512e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&adapted); 2513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2514e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2515e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Result is the frame pointer for the frame if not adapted and for the real 2516e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // frame below the adaptor frame if adapted. 2517e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 2518b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2519b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2520b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { 2522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 2523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 2525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If no arguments adaptor frame the number of arguments is fixed. 2527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->InputAt(0)->IsRegister()) { 2528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmpq(rbp, ToRegister(instr->InputAt(0))); 2529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmpq(rbp, ToOperand(instr->InputAt(0))); 2531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 25328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movl(result, Immediate(scope()->num_parameters())); 2533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &done, Label::kNear); 2534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Arguments adaptor frame present. Get argument length from there. 2536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 25378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ SmiToInteger32(result, 25388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Operand(result, 25398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ArgumentsAdaptorFrameConstants::kLengthOffset)); 2540e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2541e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Argument length is in result register. 2542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 2543b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2544b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2545b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 25463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { 2547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register receiver = ToRegister(instr->receiver()); 2548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register function = ToRegister(instr->function()); 2549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 25503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // If the receiver is null or undefined, we have to pass the global 25513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // object as a receiver to normal functions. Values have to be 25523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // passed unchanged to builtins and strict-mode functions. 2553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label global_object, receiver_ok; 25543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 25553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Do not transform the receiver to object for strict mode 25563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // functions. 25573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(kScratchRegister, 25583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); 25593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ testb(FieldOperand(kScratchRegister, 25603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SharedFunctionInfo::kStrictModeByteOffset), 25613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte)); 25623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(not_equal, &receiver_ok, Label::kNear); 25633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 25643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Do not transform the receiver to object for builtins. 25653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ testb(FieldOperand(kScratchRegister, 25663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SharedFunctionInfo::kNativeByteOffset), 25673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); 25683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(not_equal, &receiver_ok, Label::kNear); 25693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 25703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Normal function. Replace undefined or null with global receiver. 2571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(receiver, Heap::kNullValueRootIndex); 2572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &global_object, Label::kNear); 2573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); 2574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &global_object, Label::kNear); 2575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2576e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The receiver should be a JS object. 2577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Condition is_smi = __ CheckSmi(receiver); 2578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(is_smi, instr->environment()); 25793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); 2580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(below, instr->environment()); 2581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&receiver_ok, Label::kNear); 2582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&global_object); 2584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // TODO(kmillikin): We have a hydrogen value for the global object. See 2585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // if it's better to use it than to explicitly fetch it from the context 2586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // here. 2587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(receiver, ContextOperand(rsi, Context::GLOBAL_INDEX)); 2588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(receiver, 2589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset)); 2590e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&receiver_ok); 25913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 25923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 25933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 25943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoApplyArguments(LApplyArguments* instr) { 25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver = ToRegister(instr->receiver()); 25963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register function = ToRegister(instr->function()); 25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register length = ToRegister(instr->length()); 25983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements = ToRegister(instr->elements()); 25993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(receiver.is(rax)); // Used for parameter count. 26003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(function.is(rdi)); // Required by InvokeFunction. 26013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToRegister(instr->result()).is(rax)); 2602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2603e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy the arguments to this function possibly from the 2604e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // adaptor frame below it. 2605e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const uint32_t kArgumentsLimit = 1 * KB; 2606e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cmpq(length, Immediate(kArgumentsLimit)); 2607e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(above, instr->environment()); 2608e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2609e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(receiver); 2610e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(receiver, length); 2611e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Loop through the arguments pushing them onto the execution 2613e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // stack. 2614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label invoke, loop; 2615e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // length is a small non-negative integer, due to the test above. 2616e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testl(length, length); 2617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &invoke, Label::kNear); 2618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&loop); 2619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); 2620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ decl(length); 2621e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(not_zero, &loop); 2622e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Invoke the function. 2624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&invoke); 2625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 2626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LPointerMap* pointers = instr->pointer_map(); 2627e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch RecordPosition(pointers->position()); 26282b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch SafepointGenerator safepoint_generator( 26292b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch this, pointers, Safepoint::kLazyDeopt); 26303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ParameterCount actual(rax); 2631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, actual, CALL_FUNCTION, 2632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch safepoint_generator, CALL_AS_METHOD); 2633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2634b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2635b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2636b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2637b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoPushArgument(LPushArgument* instr) { 26381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* argument = instr->InputAt(0); 2639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(argument); 26401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 26411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 26421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 26433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoThisFunction(LThisFunction* instr) { 26443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register result = ToRegister(instr->result()); 26453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(result, instr->hydrogen()->closure()); 26463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 26473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 26483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 26491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::DoContext(LContext* instr) { 26501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 2651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(result, rsi); 2652b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2653b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2654b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2655e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoOuterContext(LOuterContext* instr) { 2656e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register context = ToRegister(instr->context()); 2657e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 2658e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, 26593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); 2660e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2661e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2662e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { 26643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(rsi); // The context is the first argument. 26653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushHeapObject(instr->hydrogen()->pairs()); 26663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Smi::FromInt(instr->hydrogen()->flags())); 26673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntime(Runtime::kDeclareGlobals, 3, instr); 26683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 26693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2671b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoGlobalObject(LGlobalObject* instr) { 26721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 26731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(result, GlobalObjectOperand()); 2674b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2675b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2676b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2677b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { 267844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register global = ToRegister(instr->global()); 26791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 268044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset)); 2681b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2682b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2683b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2684b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::CallKnownFunction(Handle<JSFunction> function, 2685b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int arity, 2686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LInstruction* instr, 2687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind) { 26883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool can_invoke_directly = !function->NeedsArgumentsAdaption() || 26893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function->shared()->formal_parameter_count() == arity; 26901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 26911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LPointerMap* pointers = instr->pointer_map(); 26921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RecordPosition(pointers->position()); 26931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 26943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (can_invoke_directly) { 26953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(rdi, function); 26963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Change context if needed. 26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool change_context = 26993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (info()->closure()->context() != function->context()) || 27003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scope()->contains_with() || 27013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (scope()->num_heap_slots() > 0); 27023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (change_context) { 27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 27043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 27053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set rax to arguments count if adaption is not needed. Assumes that rax 27073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // is available to write to at this point. 27083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!function->NeedsArgumentsAdaption()) { 27093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Set(rax, arity); 27103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 27113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke function. 27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SetCallKind(rcx, call_kind); 27143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (*function == *info()->closure()) { 27153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallSelf(); 27163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 27173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); 27183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up deoptimization. 27213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); 27221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 27233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We need to adapt arguments. 27243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SafepointGenerator generator( 27253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this, pointers, Safepoint::kLazyDeopt); 27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ParameterCount count(arity); 27273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind); 27281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 27291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 27301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Restore context. 27311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2732b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2733b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2734b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2735b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { 27361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 2737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKnownFunction(instr->function(), 2738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->arity(), 2739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr, 2740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CALL_AS_METHOD); 2741b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2742b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2743b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2744b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { 2745e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register input_reg = ToRegister(instr->InputAt(0)); 2746e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 2747e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Heap::kHeapNumberMapRootIndex); 2748e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(not_equal, instr->environment()); 2749e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2750e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label done; 2751e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register tmp = input_reg.is(rax) ? rcx : rax; 2752e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; 2753e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2754e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Preserve the value of all registers. 27558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 2756e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2757e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label negative; 2758e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movl(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 2759e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check the sign of the argument. If the argument is positive, just 2760e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // return it. We do not need to patch the stack since |input| and 2761e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // |result| are the same register and |input| will be restored 2762e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // unchanged by popping safepoint registers. 2763e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testl(tmp, Immediate(HeapNumber::kSignMask)); 2764e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(not_zero, &negative); 2765e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&done); 2766e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2767e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&negative); 2768e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2769e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label allocated, slow; 2770e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ AllocateHeapNumber(tmp, tmp2, &slow); 2771e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&allocated); 2772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2773e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Slow case: Call the runtime system to do the number allocation. 2774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&slow); 2775e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 27768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); 2777e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Set the pointer to the new heap number in tmp. 2778e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!tmp.is(rax)) { 2779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(tmp, rax); 2780e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2781e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2782e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Restore input_reg after call to runtime. 2783e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadFromSafepointRegisterSlot(input_reg, input_reg); 2784e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2785e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&allocated); 2786e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); 2787e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ shl(tmp2, Immediate(1)); 2788e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ shr(tmp2, Immediate(1)); 2789e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); 2790e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ StoreToSafepointRegisterSlot(input_reg, tmp); 2791e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2792e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 2793e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2794e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2796e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { 2797e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register input_reg = ToRegister(instr->InputAt(0)); 2798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testl(input_reg, input_reg); 2799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label is_positive; 2800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(not_sign, &is_positive); 2801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ negl(input_reg); // Sets flags. 2802e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(negative, instr->environment()); 2803e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&is_positive); 2804b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2805b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2806b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2807b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { 2808e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Class for deferred case. 2809e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { 2810e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public: 2811e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, 2812e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LUnaryMathOperation* instr) 2813e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch : LDeferredCode(codegen), instr_(instr) { } 2814e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual void Generate() { 2815e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); 2816e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 28173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 2818e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private: 2819e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LUnaryMathOperation* instr_; 2820e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch }; 2821e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2822e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(instr->InputAt(0)->Equals(instr->result())); 2823e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Representation r = instr->hydrogen()->value()->representation(); 2824e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2825e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (r.IsDouble()) { 2826e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister scratch = xmm0; 2827e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(scratch, scratch); 2829e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ subsd(scratch, input_reg); 2830e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ andpd(input_reg, scratch); 2831e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (r.IsInteger32()) { 2832e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitIntegerMathAbs(instr); 2833e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { // Tagged case. 2834e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeferredMathAbsTaggedHeapNumber* deferred = 2835e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch new DeferredMathAbsTaggedHeapNumber(this, instr); 2836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register input_reg = ToRegister(instr->InputAt(0)); 2837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Smi check. 2838e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfNotSmi(input_reg, deferred->entry()); 28397d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch __ SmiToInteger32(input_reg, input_reg); 2840e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitIntegerMathAbs(instr); 28417d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch __ Integer32ToSmi(input_reg, input_reg); 2842e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(deferred->exit()); 2843e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2844b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2845b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2846b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2847b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { 2848e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister xmm_scratch = xmm0; 2849e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register output_reg = ToRegister(instr->result()); 2850e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 285169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label done; 2852e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(SSE4_1)) { 2854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(SSE4_1); 2855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 2856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Deoptimize if minus zero. 2857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(output_reg, input_reg); 2858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subq(output_reg, Immediate(1)); 2859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(overflow, instr->environment()); 2860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); 2862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvttsd2si(output_reg, xmm_scratch); 2863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpl(output_reg, Immediate(0x80000000)); 2864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(equal, instr->environment()); 2865e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 286669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Deoptimize on negative inputs. 2867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(xmm_scratch, xmm_scratch); // Zero the register. 2868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ucomisd(input_reg, xmm_scratch); 286969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(below, instr->environment()); 2870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 287169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Check for negative zero. 287269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label positive_sign; 287369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(above, &positive_sign, Label::kNear); 287469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movmskpd(output_reg, input_reg); 287569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ testq(output_reg, Immediate(1)); 287669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(not_zero, instr->environment()); 287769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Set(output_reg, 0); 287869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ jmp(&done); 287969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&positive_sign); 2880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 28818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use truncating instruction (OK because input is positive). 2883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvttsd2si(output_reg, input_reg); 2884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Overflow is signalled with minint. 2886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpl(output_reg, Immediate(0x80000000)); 2887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(equal, instr->environment()); 2888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 288969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&done); 2890b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2891b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2892b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2893b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathRound(LUnaryMathOperation* instr) { 2894e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const XMMRegister xmm_scratch = xmm0; 2895e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register output_reg = ToRegister(instr->result()); 2896e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2897e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 2899e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // xmm_scratch = 0.5 2900e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); 2901e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(xmm_scratch, kScratchRegister); 2902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label below_half; 2903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ucomisd(xmm_scratch, input_reg); 2904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If input_reg is NaN, this doesn't jump. 2905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above, &below_half, Label::kNear); 2906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // input = input + 0.5 2907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This addition might give a result that isn't the correct for 2908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // rounding, due to loss of precision, but only for a number that's 2909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // so big that the conversion below will overflow anyway. 2910692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ addsd(xmm_scratch, input_reg); 2911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute Math.floor(input). 2912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use truncating instruction (OK because input is positive). 2913692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ cvttsd2si(output_reg, xmm_scratch); 2914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Overflow is signalled with minint. 2915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpl(output_reg, Immediate(0x80000000)); 2916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(equal, instr->environment()); 2917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done); 2918e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&below_half); 2920e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 2921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Bailout if negative (including -0). 2922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(output_reg, input_reg); 2923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testq(output_reg, output_reg); 2924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(negative, instr->environment()); 2925e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Bailout if below -0.5, otherwise round to (positive) zero, even 2927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // if negative. 2928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // xmm_scrach = -0.5 2929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(kScratchRegister, V8_INT64_C(0xBFE0000000000000), RelocInfo::NONE); 2930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(xmm_scratch, kScratchRegister); 2931e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ucomisd(input_reg, xmm_scratch); 2932e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(below, instr->environment()); 2933e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorl(output_reg, output_reg); 2935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 2937b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2938b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2939b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2940b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { 2941e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2942e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); 2943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ sqrtsd(input_reg, input_reg); 2944b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2945b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2946b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2947b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { 2948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister xmm_scratch = xmm0; 2949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2950e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); 29513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Note that according to ECMA-262 15.8.2.13: 29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Math.pow(-Infinity, 0.5) == Infinity 29543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Math.sqrt(-Infinity) == NaN 29553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done, sqrt; 29563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check base for -Infinity. According to IEEE-754, double-precision 29573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. 29583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000), RelocInfo::NONE); 29593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(xmm_scratch, kScratchRegister); 29603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ucomisd(xmm_scratch, input_reg); 29613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Comparing -Infinity with NaN results in "unordered", which sets the 29623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // zero flag as if both were equal. However, it also sets the carry flag. 29633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &sqrt, Label::kNear); 29643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(carry, &sqrt, Label::kNear); 29653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If input is -Infinity, return Infinity. 29663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xorps(input_reg, input_reg); 29673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ subsd(input_reg, xmm_scratch); 29683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done, Label::kNear); 29693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Square root. 29713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&sqrt); 2972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(xmm_scratch, xmm_scratch); 2973e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. 2974e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ sqrtsd(input_reg, input_reg); 29753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 2976b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2977b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2978b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2979b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoPower(LPower* instr) { 2980e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Representation exponent_type = instr->hydrogen()->right()->representation(); 29813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Having marked this as a call, we can use any registers. 29823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Just make sure that the input/output registers are the expected ones. 29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Choose register conforming to calling convention (when bailing out). 2985c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch#ifdef _WIN64 29863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register exponent = rdx; 2987c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch#else 29883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register exponent = rdi; 2989c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch#endif 29903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!instr->InputAt(1)->IsRegister() || 29913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ToRegister(instr->InputAt(1)).is(exponent)); 29923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!instr->InputAt(1)->IsDoubleRegister() || 29933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ToDoubleRegister(instr->InputAt(1)).is(xmm1)); 29943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToDoubleRegister(instr->InputAt(0)).is(xmm2)); 29953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(xmm3)); 29963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (exponent_type.IsTagged()) { 29983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label no_deopt; 29993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(exponent, &no_deopt); 30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, rcx); 30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(not_equal, instr->environment()); 30023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&no_deopt); 30033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MathPowStub stub(MathPowStub::TAGGED); 30043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 30053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (exponent_type.IsInteger32()) { 30063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MathPowStub stub(MathPowStub::INTEGER); 30073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 300885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } else { 30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(exponent_type.IsDouble()); 30103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MathPowStub stub(MathPowStub::DOUBLE); 30113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 30123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 30133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3014c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 3015b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 30163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoRandom(LRandom* instr) { 30173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch class DeferredDoRandom: public LDeferredCode { 30183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public: 30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeferredDoRandom(LCodeGen* codegen, LRandom* instr) 30203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : LDeferredCode(codegen), instr_(instr) { } 30213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual void Generate() { codegen()->DoDeferredRandom(instr_); } 30223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 30233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 30243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LRandom* instr_; 30253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch }; 3026b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 30273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeferredDoRandom* deferred = new DeferredDoRandom(this, instr); 30283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Having marked this instruction as a call we can use any 30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // registers. 30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 30323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Choose the right register for the first argument depending on 30343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // calling convention. 30353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef _WIN64 30363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToRegister(instr->InputAt(0)).is(rcx)); 30373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register global_object = rcx; 30383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#else 30393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToRegister(instr->InputAt(0)).is(rdi)); 30403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register global_object = rdi; 30413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 30423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kSeedSize = sizeof(uint32_t); 30443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kPointerSize == 2 * kSeedSize); 30453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(global_object, 30473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldOperand(global_object, GlobalObject::kGlobalContextOffset)); 30483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kRandomSeedOffset = 30493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; 30503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, FieldOperand(global_object, kRandomSeedOffset)); 30513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rbx: FixedArray of the global context's random seeds 30523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load state[0]. 30543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movl(rax, FieldOperand(rbx, ByteArray::kHeaderSize)); 30553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If state[0] == 0, call runtime to initialize seeds. 30563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testl(rax, rax); 30573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(zero, deferred->entry()); 30583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load state[1]. 30593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movl(rcx, FieldOperand(rbx, ByteArray::kHeaderSize + kSeedSize)); 30603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16) 30623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Only operate on the lower 32 bit of rax. 30633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movl(rdx, rax); 30643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ andl(rdx, Immediate(0xFFFF)); 30653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ imull(rdx, rdx, Immediate(18273)); 30663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ shrl(rax, Immediate(16)); 30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addl(rax, rdx); 30683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save state[0]. 30693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movl(FieldOperand(rbx, ByteArray::kHeaderSize), rax); 30703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16) 30723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movl(rdx, rcx); 30733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ andl(rdx, Immediate(0xFFFF)); 30743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ imull(rdx, rdx, Immediate(36969)); 30753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ shrl(rcx, Immediate(16)); 30763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addl(rcx, rdx); 30773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save state[1]. 30783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movl(FieldOperand(rbx, ByteArray::kHeaderSize + kSeedSize), rcx); 30793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF) 30813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ shll(rax, Immediate(14)); 30823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ andl(rcx, Immediate(0x3FFFF)); 30833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addl(rax, rcx); 30843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(deferred->exit()); 30863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Convert 32 random bits in rax to 0.(32 random bits) in a double 30873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // by computing: 30883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 30893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. 30903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movd(xmm2, rcx); 30913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movd(xmm1, rax); 30923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cvtss2sd(xmm2, xmm2); 30933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xorps(xmm1, xmm2); 30943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ subsd(xmm1, xmm2); 30953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 30963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredRandom(LRandom* instr) { 30993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(1); 31003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); 31015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 31023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Return value is in rax. 31035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 31045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 31055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 3106b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathLog(LUnaryMathOperation* instr) { 3107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 3108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub stub(TranscendentalCache::LOG, 3109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub::UNTAGGED); 3110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3111b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3112b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3113b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 31143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoMathTan(LUnaryMathOperation* instr) { 31153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 31163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TranscendentalCacheStub stub(TranscendentalCache::TAN, 31173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TranscendentalCacheStub::UNTAGGED); 31183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 31193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 31203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3122b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathCos(LUnaryMathOperation* instr) { 3123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 312444f0eee88ff00398ff7f715fab053374d808c90dSteve Block TranscendentalCacheStub stub(TranscendentalCache::COS, 3125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub::UNTAGGED); 3126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3127b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3128b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3129b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3130b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoMathSin(LUnaryMathOperation* instr) { 3131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 313244f0eee88ff00398ff7f715fab053374d808c90dSteve Block TranscendentalCacheStub stub(TranscendentalCache::SIN, 3133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranscendentalCacheStub::UNTAGGED); 3134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3135b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3136b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3137b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3138b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { 3139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch switch (instr->op()) { 3140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathAbs: 3141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathAbs(instr); 3142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 3143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathFloor: 3144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathFloor(instr); 3145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 3146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathRound: 3147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathRound(instr); 3148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 3149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathSqrt: 3150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathSqrt(instr); 3151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 3152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathPowHalf: 3153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathPowHalf(instr); 3154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 3155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathCos: 3156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathCos(instr); 3157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 3158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathSin: 3159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathSin(instr); 3160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 31613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case kMathTan: 31623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoMathTan(instr); 31633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 3164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case kMathLog: 3165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoMathLog(instr); 3166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 3167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch default: 3169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UNREACHABLE(); 3170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3171b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3172b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3173b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { 3175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(ToRegister(instr->function()).is(rdi)); 3176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->HasPointerMap()); 3177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->HasDeoptimizationEnvironment()); 3178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LPointerMap* pointers = instr->pointer_map(); 3179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RecordPosition(pointers->position()); 31802b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); 3181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ParameterCount count(instr->arity()); 3182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); 3183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3187b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallKeyed(LCallKeyed* instr) { 3188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->key()).is(rcx)); 3189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->result()).is(rax)); 3190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int arity = instr->arity(); 3192589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Handle<Code> ic = 3193589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); 3194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 3195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3196b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3197b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3198b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3199b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallNamed(LCallNamed* instr) { 32001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 32011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int arity = instr->arity(); 3203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RelocInfo::Mode mode = RelocInfo::CODE_TARGET; 3204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = 3205589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeCallInitialize(arity, mode); 32061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(rcx, instr->name()); 3207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallCode(ic, mode, instr); 32081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3209b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3210b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3211b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3212b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallFunction(LCallFunction* instr) { 32133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToRegister(instr->function()).is(rdi)); 3214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->result()).is(rax)); 3215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int arity = instr->arity(); 32173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); 3218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3220b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3221b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3222b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3223b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallGlobal(LCallGlobal* instr) { 32241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 32251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int arity = instr->arity(); 3226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; 3227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = 3228589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeCallInitialize(arity, mode); 32291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(rcx, instr->name()); 3230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallCode(ic, mode, instr); 32311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3232b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3233b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3234b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3235b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { 32361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 3237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); 3238b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3239b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3240b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3241b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallNew(LCallNew* instr) { 32421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->InputAt(0)).is(rdi)); 32431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->result()).is(rax)); 32441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); 32461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Set(rax, instr->arity()); 32473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); 3248b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3249b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3250b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3251b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCallRuntime(LCallRuntime* instr) { 3252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallRuntime(instr->function(), instr->arity(), instr); 3253b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3254b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3255b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3256b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { 32571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register object = ToRegister(instr->object()); 32581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register value = ToRegister(instr->value()); 32591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offset = instr->offset(); 32601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!instr->transition().is_null()) { 32621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); 32631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 32641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Do the store. 32663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HType type = instr->hydrogen()->value()->type(); 32673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck check_needed = 32683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 32691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->is_in_object()) { 32701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(FieldOperand(object, offset), value); 32713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->NeedsWriteBarrier()) { 32721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register temp = ToRegister(instr->TempAt(0)); 32731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Update the write barrier for the object for in-object properties. 32743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(object, 32753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 32763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 32773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch temp, 32783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kSaveFPRegs, 32793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 32803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch check_needed); 32811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 32821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 32831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register temp = ToRegister(instr->TempAt(0)); 32841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset)); 32851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(FieldOperand(temp, offset), value); 32863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->NeedsWriteBarrier()) { 32871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Update the write barrier for the properties array. 32881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // object is used as a scratch register. 32893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(temp, 32903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 32913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 32923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, 32933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kSaveFPRegs, 32943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 32953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch check_needed); 32961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 32971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3298b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3299b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3300b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3301b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 3302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->object()).is(rdx)); 3303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->value()).is(rax)); 3304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Move(rcx, instr->hydrogen()->name()); 33063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) 330744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? isolate()->builtins()->StoreIC_Initialize_Strict() 330844f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate()->builtins()->StoreIC_Initialize(); 3309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 3310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 3311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 331344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoStoreKeyedSpecializedArrayElement( 331444f0eee88ff00398ff7f715fab053374d808c90dSteve Block LStoreKeyedSpecializedArrayElement* instr) { 3315589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = instr->elements_kind(); 33163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand operand(BuildFastArrayOperand(instr->external_pointer(), 33173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->key(), elements_kind, 0)); 3318589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 331944f0eee88ff00398ff7f715fab053374d808c90dSteve Block XMMRegister value(ToDoubleRegister(instr->value())); 332044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cvtsd2ss(value, value); 3321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movss(operand, value); 3322589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsd(operand, ToDoubleRegister(instr->value())); 332444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 332544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register value(ToRegister(instr->value())); 33263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3327589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3328589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3329589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movb(operand, value); 333144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3332589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3333589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movw(operand, value); 333544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3336589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3337589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movl(operand, value); 333944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3340589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3341589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3342589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 33433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3344589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3345589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3346589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 334744f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 334844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 334944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 3350e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3351b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3352b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3353b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3354b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { 33553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->length()->IsRegister()) { 33563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = ToRegister(instr->length()); 33573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 33583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AbortIfNotZeroExtended(reg); 33593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 33603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->index()->IsConstantOperand()) { 33613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(reg, 336269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Immediate(ToInteger32(LConstantOperand::cast(instr->index())))); 336369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else { 33643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg2 = ToRegister(instr->index()); 33653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 33663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AbortIfNotZeroExtended(reg2); 33673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 33683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(reg, reg2); 336985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 337085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } else { 33713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->index()->IsConstantOperand()) { 33723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(ToOperand(instr->length()), 33733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(ToInteger32(LConstantOperand::cast(instr->index())))); 337469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else { 337569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmpq(ToOperand(instr->length()), ToRegister(instr->index())); 337669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 33771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 337869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(below_equal, instr->environment()); 3379b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3380b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3381b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3382b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { 33831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register value = ToRegister(instr->value()); 33841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register elements = ToRegister(instr->object()); 33851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; 33861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Do the store. 33881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->key()->IsConstantOperand()) { 33891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); 33901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); 33911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offset = 33921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; 33931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(FieldOperand(elements, offset), value); 33941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 33951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(FieldOperand(elements, 33961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block key, 33971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block times_pointer_size, 33981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FixedArray::kHeaderSize), 33991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block value); 34001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->NeedsWriteBarrier()) { 34033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HType type = instr->hydrogen()->value()->type(); 34043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck check_needed = 34053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 34061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Compute address of modified element and store it into key register. 34071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ lea(key, FieldOperand(elements, 34081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block key, 34091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block times_pointer_size, 34101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FixedArray::kHeaderSize)); 34113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(elements, 34123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch key, 34133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 34143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kSaveFPRegs, 34153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 34163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch check_needed); 34171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3418b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3419b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3420b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 34213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoStoreKeyedFastDoubleElement( 34223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LStoreKeyedFastDoubleElement* instr) { 34233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch XMMRegister value = ToDoubleRegister(instr->value()); 34243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label have_value; 34253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ucomisd(value, value); 34273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(parity_odd, &have_value); // NaN. 34283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Set(kScratchRegister, BitCast<uint64_t>( 34303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedDoubleArray::canonical_not_the_hole_nan_as_double())); 34313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(value, kScratchRegister); 34323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&have_value); 34343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand double_store_operand = BuildFastArrayOperand( 3435589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS, 34363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedDoubleArray::kHeaderSize - kHeapObjectTag); 34373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movsd(double_store_operand, value); 34383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 34393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3440b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { 3441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->object()).is(rdx)); 3442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->key()).is(rcx)); 3443e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ToRegister(instr->value()).is(rax)); 3444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 34453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) 344644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 344744f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate()->builtins()->KeyedStoreIC_Initialize(); 3448e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 3449e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 3450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 34523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { 34533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object_reg = ToRegister(instr->object()); 34543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register new_map_reg = ToRegister(instr->new_map_reg()); 34553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> from_map = instr->original_map(); 34573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> to_map = instr->transitioned_map(); 34583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind from_kind = from_map->elements_kind(); 34593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind to_kind = to_map->elements_kind(); 34603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label not_applicable; 34623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); 34633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, ¬_applicable); 34643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); 34653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) { 34663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); 34673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Write barrier. 34683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_NE(instr->temp_reg(), NULL); 34693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, 34703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ToRegister(instr->temp_reg()), kDontSaveFPRegs); 34713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (from_kind == FAST_SMI_ONLY_ELEMENTS && 34723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch to_kind == FAST_DOUBLE_ELEMENTS) { 34733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register fixed_object_reg = ToRegister(instr->temp_reg()); 34743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(fixed_object_reg.is(rdx)); 34753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(new_map_reg.is(rbx)); 34763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(fixed_object_reg, object_reg); 34773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), 34783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo::CODE_TARGET, instr); 34793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { 34803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register fixed_object_reg = ToRegister(instr->temp_reg()); 34813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(fixed_object_reg.is(rdx)); 34823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(new_map_reg.is(rbx)); 34833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(fixed_object_reg, object_reg); 34843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), 34853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo::CODE_TARGET, instr); 34863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 34873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 34883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 34893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(¬_applicable); 34903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 34913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoStringAdd(LStringAdd* instr) { 3494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(instr->left()); 3495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(instr->right()); 3496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringAddStub stub(NO_STRING_CHECK_IN_STUB); 3497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3501e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 3502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch class DeferredStringCharCodeAt: public LDeferredCode { 3503e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public: 3504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) 3505e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch : LDeferredCode(codegen), instr_(instr) { } 3506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } 35073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 3508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private: 3509e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LStringCharCodeAt* instr_; 3510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch }; 3511e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3512e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeferredStringCharCodeAt* deferred = 3513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch new DeferredStringCharCodeAt(this, instr); 3514e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 35153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharLoadGenerator::Generate(masm(), 35163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ToRegister(instr->string()), 35173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ToRegister(instr->index()), 35183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ToRegister(instr->result()), 35193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch deferred->entry()); 3520e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(deferred->exit()); 3521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 3522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { 3525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register string = ToRegister(instr->string()); 3526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 3527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // TODO(3095996): Get rid of this. For now, we need to make the 3529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // result register contain a valid pointer because it is already 3530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // contained in the register pointer map. 3531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Set(result, 0); 3532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 35338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 3534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(string); 3535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Push the index as a smi. This is safe because of the checks in 3536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // DoStringCharCodeAt above. 3537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); 3538e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->index()->IsConstantOperand()) { 3539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int const_index = ToInteger32(LConstantOperand::cast(instr->index())); 3540e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(Smi::FromInt(const_index)); 3541e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 3542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register index = ToRegister(instr->index()); 3543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Integer32ToSmi(index, index); 3544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(index); 3545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 35468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); 3547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (FLAG_debug_code) { 3548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ AbortIfNotSmi(rax); 3549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3550e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiToInteger32(rax, rax); 3551e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ StoreToSafepointRegisterSlot(result, rax); 3552e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 3553e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 355544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { 355644f0eee88ff00398ff7f715fab053374d808c90dSteve Block class DeferredStringCharFromCode: public LDeferredCode { 355744f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 355844f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) 355944f0eee88ff00398ff7f715fab053374d808c90dSteve Block : LDeferredCode(codegen), instr_(instr) { } 356044f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } 35613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 356244f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 356344f0eee88ff00398ff7f715fab053374d808c90dSteve Block LStringCharFromCode* instr_; 356444f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 356544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 356644f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeferredStringCharFromCode* deferred = 356744f0eee88ff00398ff7f715fab053374d808c90dSteve Block new DeferredStringCharFromCode(this, instr); 356844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 356944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); 357044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register char_code = ToRegister(instr->char_code()); 357144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result = ToRegister(instr->result()); 357244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!char_code.is(result)); 357344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 357444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpl(char_code, Immediate(String::kMaxAsciiCharCode)); 357544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(above, deferred->entry()); 357644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex); 357744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(result, FieldOperand(result, 357844f0eee88ff00398ff7f715fab053374d808c90dSteve Block char_code, times_pointer_size, 357944f0eee88ff00398ff7f715fab053374d808c90dSteve Block FixedArray::kHeaderSize)); 358044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareRoot(result, Heap::kUndefinedValueRootIndex); 358144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(equal, deferred->entry()); 358244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(deferred->exit()); 358344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 358444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 358544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 358644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { 358744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register char_code = ToRegister(instr->char_code()); 358844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result = ToRegister(instr->result()); 358944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 359044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // TODO(3095996): Get rid of this. For now, we need to make the 359144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // result register contain a valid pointer because it is already 359244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // contained in the register pointer map. 359344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(result, 0); 359444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 35958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 359644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Integer32ToSmi(char_code, char_code); 359744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ push(char_code); 35988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); 359944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ StoreToSafepointRegisterSlot(result, rax); 360044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 360144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 360244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3603e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoStringLength(LStringLength* instr) { 3604e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register string = ToRegister(instr->string()); 3605e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 3606e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(result, FieldOperand(string, String::kLengthOffset)); 3607b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3608b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3609b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3610b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { 36111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* input = instr->InputAt(0); 36121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(input->IsRegister() || input->IsStackSlot()); 36131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* output = instr->result(); 36141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(output->IsDoubleRegister()); 3615e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (input->IsRegister()) { 3616e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cvtlsi2sd(ToDoubleRegister(output), ToRegister(input)); 3617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 3618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cvtlsi2sd(ToDoubleRegister(output), ToOperand(input)); 3619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3620b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3621b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3622b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3623b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoNumberTagI(LNumberTagI* instr) { 36241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* input = instr->InputAt(0); 36251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(input->IsRegister() && input->Equals(instr->result())); 36261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(input); 3627b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 36281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Integer32ToSmi(reg, reg); 3629b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3630b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3631b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3632b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoNumberTagD(LNumberTagD* instr) { 36331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block class DeferredNumberTagD: public LDeferredCode { 36341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public: 36351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) 36361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block : LDeferredCode(codegen), instr_(instr) { } 36371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } 36383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 36391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private: 36401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LNumberTagD* instr_; 36411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block }; 36421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 36441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->result()); 36451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register tmp = ToRegister(instr->TempAt(0)); 36461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); 36481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_inline_new) { 36491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(reg, tmp, deferred->entry()); 36501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 36511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ jmp(deferred->entry()); 36521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 36531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(deferred->exit()); 36541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); 3655b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3656b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3657b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3658b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { 36591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // TODO(3095996): Get rid of this. For now, we need to make the 36601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // result register contain a valid pointer because it is already 36611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // contained in the register pointer map. 36621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->result()); 36631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Move(reg, Smi::FromInt(0)); 36641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch { 36668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 36678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); 36688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Ensure that value in rax survives popping registers. 36698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(kScratchRegister, rax); 36708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 36711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(reg, kScratchRegister); 3672b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3673b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3674b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3675b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoSmiTag(LSmiTag* instr) { 36761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->InputAt(0)->Equals(instr->result())); 36771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 36781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); 36791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Integer32ToSmi(input, input); 3680b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3681b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3682b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3683b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoSmiUntag(LSmiUntag* instr) { 36841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->InputAt(0)->Equals(instr->result())); 36851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 36861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->needs_check()) { 36871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition is_smi = __ CheckSmi(input); 36881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(NegateCondition(is_smi), instr->environment()); 36891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 36901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiToInteger32(input, input); 3691b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3692b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3693b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3694b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::EmitNumberUntagD(Register input_reg, 3695b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch XMMRegister result_reg, 36967d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch bool deoptimize_on_undefined, 36973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool deoptimize_on_minus_zero, 3698b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LEnvironment* env) { 3699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label load_smi, done; 37001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Smi check. 3702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(input_reg, &load_smi, Label::kNear); 37031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Heap number map check. 37051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 37061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Heap::kHeapNumberMapRootIndex); 37077d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch if (deoptimize_on_undefined) { 37087d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch DeoptimizeIf(not_equal, env); 37097d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } else { 3710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label heap_number; 3711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &heap_number, Label::kNear); 3712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 37137d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); 37147d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch DeoptimizeIf(not_equal, env); 37151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37167d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch // Convert undefined to NaN. Compute NaN as 0/0. 3717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(result_reg, result_reg); 37187d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch __ divsd(result_reg, result_reg); 3719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 37201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37217d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch __ bind(&heap_number); 37227d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } 37231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Heap number to XMM conversion. 37241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); 37253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (deoptimize_on_minus_zero) { 37263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch XMMRegister xmm_scratch = xmm0; 37273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xorps(xmm_scratch, xmm_scratch); 37283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ucomisd(xmm_scratch, result_reg); 37293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &done, Label::kNear); 37303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movmskpd(kScratchRegister, result_reg); 37313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ testq(kScratchRegister, Immediate(1)); 37323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(not_zero, env); 37333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 37351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Smi to XMM conversion 37371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&load_smi); 3738e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ SmiToInteger32(kScratchRegister, input_reg); 37391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cvtlsi2sd(result_reg, kScratchRegister); 37401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 3741b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3742b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3743b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3744b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { 3745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, heap_number; 37461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input_reg = ToRegister(instr->InputAt(0)); 37471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Heap number map check. 37491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 37501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Heap::kHeapNumberMapRootIndex); 37511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->truncating()) { 3753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &heap_number, Label::kNear); 37541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for undefined. Undefined is converted to zero for truncating 37551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // conversions. 37561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); 37571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_equal, instr->environment()); 37588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Set(input_reg, 0); 3759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 37601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&heap_number); 37621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 37641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cvttsd2siq(input_reg, xmm0); 37651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); 37668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ cmpq(input_reg, kScratchRegister); 37671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(equal, instr->environment()); 37681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 37691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Deoptimize if we don't have a heap number. 37701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_equal, instr->environment()); 37711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); 37731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 37741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cvttsd2si(input_reg, xmm0); 37751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cvtlsi2sd(xmm_temp, input_reg); 37761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ucomisd(xmm0, xmm_temp); 37771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_equal, instr->environment()); 37781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(parity_even, instr->environment()); // NaN. 37791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 37801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testl(input_reg, input_reg); 37811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_zero, &done); 37821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movmskpd(input_reg, xmm0); 37831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ andl(input_reg, Immediate(1)); 37841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_zero, instr->environment()); 37851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 37861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 37871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 3788b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3789b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3790b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3791b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoTaggedToI(LTaggedToI* instr) { 37923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch class DeferredTaggedToI: public LDeferredCode { 37933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public: 37943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 37953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : LDeferredCode(codegen), instr_(instr) { } 37963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } 37973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 37983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 37993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LTaggedToI* instr_; 38003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch }; 38013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* input = instr->InputAt(0); 38031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(input->IsRegister()); 38041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(input->Equals(instr->result())); 38051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 38061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input_reg = ToRegister(input); 38071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); 38081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfNotSmi(input_reg, deferred->entry()); 38091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiToInteger32(input_reg, input_reg); 38101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(deferred->exit()); 3811b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3812b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3813b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3814b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { 3815e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* input = instr->InputAt(0); 3816e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(input->IsRegister()); 3817e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* result = instr->result(); 3818e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(result->IsDoubleRegister()); 3819e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3820e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register input_reg = ToRegister(input); 3821e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister result_reg = ToDoubleRegister(result); 3822e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 38237d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch EmitNumberUntagD(input_reg, result_reg, 38247d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch instr->hydrogen()->deoptimize_on_undefined(), 38253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->hydrogen()->deoptimize_on_minus_zero(), 38267d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch instr->environment()); 3827b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3828b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3829b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3830b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoDoubleToI(LDoubleToI* instr) { 3831e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* input = instr->InputAt(0); 3832e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(input->IsDoubleRegister()); 3833e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* result = instr->result(); 3834e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(result->IsRegister()); 3835e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister input_reg = ToDoubleRegister(input); 3837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result_reg = ToRegister(result); 3838e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3839e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->truncating()) { 3840e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Performs a truncating conversion of a floating point number as used by 3841e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the JS bitwise operations. 3842e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cvttsd2siq(result_reg, input_reg); 3843e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(kScratchRegister, V8_INT64_C(0x8000000000000000), RelocInfo::NONE); 38448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ cmpq(result_reg, kScratchRegister); 3845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(equal, instr->environment()); 3846e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 3847e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cvttsd2si(result_reg, input_reg); 3848e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ cvtlsi2sd(xmm0, result_reg); 3849e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ucomisd(xmm0, input_reg); 3850e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(not_equal, instr->environment()); 3851e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(parity_even, instr->environment()); // NaN. 3852e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 3854e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The integer converted back is equal to the original. We 3855e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // only have to test if we got -0 as an input. 3856e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ testl(result_reg, result_reg); 3857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &done, Label::kNear); 3858e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movmskpd(result_reg, input_reg); 3859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Bit 0 contains the sign of the double in input_reg. 3860e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If input was positive, we are ok and return 0, otherwise 3861e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // deoptimize. 3862e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ andl(result_reg, Immediate(1)); 3863e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizeIf(not_zero, instr->environment()); 3864e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&done); 3865e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3866e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3867b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3868b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3869b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3870b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCheckSmi(LCheckSmi* instr) { 38711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* input = instr->InputAt(0); 38721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition cc = masm()->CheckSmi(ToRegister(input)); 387344f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(NegateCondition(cc), instr->environment()); 387444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 387544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 387644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 387744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 387844f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOperand* input = instr->InputAt(0); 387944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Condition cc = masm()->CheckSmi(ToRegister(input)); 38801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(cc, instr->environment()); 3881b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3882b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3883b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3884b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 38851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 38861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 38871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); 38881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (instr->hydrogen()->is_interval_check()) { 3890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InstanceType first; 3891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InstanceType last; 3892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->hydrogen()->GetCheckInterval(&first, &last); 3893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 38941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 38951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(static_cast<int8_t>(first))); 3896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If there is only one type in the interval check for equality. 3898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (first == last) { 3899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 3900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(below, instr->environment()); 3902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Omit check for the last type. 3903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (last != LAST_TYPE) { 3904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 3905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Immediate(static_cast<int8_t>(last))); 3906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(above, instr->environment()); 3907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 39091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 3910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint8_t mask; 3911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint8_t tag; 3912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); 3913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (IsPowerOf2(mask)) { 3915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(tag == 0 || IsPowerOf2(tag)); 3916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 3917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Immediate(mask)); 3918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment()); 3919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movzxbl(kScratchRegister, 3921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); 3922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ andb(kScratchRegister, Immediate(mask)); 3923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpb(kScratchRegister, Immediate(tag)); 3924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 39251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 39261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3927b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3928b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3929b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3930b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCheckFunction(LCheckFunction* instr) { 39313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = ToRegister(instr->value()); 39323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> target = instr->hydrogen()->target(); 39333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate()->heap()->InNewSpace(*target)) { 39343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 39353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewJSGlobalPropertyCell(target); 39363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL); 39373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(reg, Operand(kScratchRegister, 0)); 39383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 39393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(reg, target); 39403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 39411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(not_equal, instr->environment()); 3942b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3943b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3944b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 39453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckMapCommon(Register reg, 39463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map, 39473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareMapMode mode, 39483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LEnvironment* env) { 39493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label success; 39503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareMap(reg, map, &success, mode); 39513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(not_equal, env); 39523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&success); 39533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 39543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3956b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCheckMap(LCheckMap* instr) { 39571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* input = instr->InputAt(0); 39581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(input->IsRegister()); 39591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(input); 39603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map = instr->hydrogen()->map(); 39613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoCheckMapCommon(reg, map, instr->hydrogen()->mode(), instr->environment()); 3962b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 3963b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3964b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 3965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 3966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); 3967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result_reg = ToRegister(instr->result()); 3968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register temp_reg = ToRegister(instr->TempAt(0)); 3969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ClampDoubleToUint8(value_reg, xmm0, result_reg, temp_reg); 3970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { 3974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->unclamped()->Equals(instr->result())); 3975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register value_reg = ToRegister(instr->result()); 3976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ClampUint8(value_reg); 3977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { 3981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->unclamped()->Equals(instr->result())); 3982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register input_reg = ToRegister(instr->unclamped()); 3983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register temp_reg = ToRegister(instr->TempAt(0)); 3984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch XMMRegister temp_xmm_reg = ToDoubleRegister(instr->TempAt(1)); 3985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label is_smi, done, heap_number; 3986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(input_reg, &is_smi); 3988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for heap number 3990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 3991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch factory()->heap_number_map()); 3992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &heap_number, Label::kNear); 3993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for undefined. Undefined is converted to zero for clamping 3995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // conversions. 3996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Cmp(input_reg, factory()->undefined_value()); 3997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 3998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(input_reg, Immediate(0)); 3999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 4000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Heap number 4002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&heap_number); 4003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 4004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ClampDoubleToUint8(xmm0, temp_xmm_reg, input_reg, temp_reg); 4005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 4006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // smi 4008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&is_smi); 4009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiToInteger32(input_reg, input_reg); 4010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ClampUint8(input_reg); 4011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 4013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 4014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4016b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { 40171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = ToRegister(instr->TempAt(0)); 40181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 40191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<JSObject> holder = instr->holder(); 40201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<JSObject> current_prototype = instr->prototype(); 40211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 40221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Load prototype object. 40233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(reg, current_prototype); 40241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 40251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check prototype maps up to the holder. 40261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block while (!current_prototype.is_identical_to(holder)) { 40273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), 40283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); 40291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block current_prototype = 40301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); 40311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Load next prototype object. 40323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(reg, current_prototype); 40331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 40341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 40351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check the holder map. 40363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), 40373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); 40383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoAllocateObject(LAllocateObject* instr) { 40423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch class DeferredAllocateObject: public LDeferredCode { 40433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public: 40443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr) 40453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : LDeferredCode(codegen), instr_(instr) { } 40463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } 40473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 40483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 40493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LAllocateObject* instr_; 40503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch }; 40513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeferredAllocateObject* deferred = new DeferredAllocateObject(this, instr); 40533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result = ToRegister(instr->result()); 40553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = ToRegister(instr->TempAt(0)); 40563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> constructor = instr->hydrogen()->constructor(); 40573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> initial_map(constructor->initial_map()); 40583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int instance_size = initial_map->instance_size(); 40593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(initial_map->pre_allocated_property_fields() + 40603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch initial_map->unused_property_fields() - 40613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch initial_map->inobject_properties() == 0); 40623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate memory for the object. The initial map might change when 40643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the constructor's prototype changes, but instance size and property 40653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // counts remain unchanged (if slack tracking finished). 40663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress()); 40673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(instance_size, 40683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 40693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch no_reg, 40703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 40713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch deferred->entry(), 40723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TAG_OBJECT); 40733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the initial map. 40753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map = scratch; 40763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(scratch, constructor); 40773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(map, FieldOperand(scratch, JSFunction::kPrototypeOrInitialMapOffset)); 40783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 40803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AbortIfSmi(map); 40813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpb(FieldOperand(map, Map::kInstanceSizeOffset), 40823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(instance_size >> kPointerSizeLog2)); 40833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(equal, "Unexpected instance size"); 40843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpb(FieldOperand(map, Map::kPreAllocatedPropertyFieldsOffset), 40853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(initial_map->pre_allocated_property_fields())); 40863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(equal, "Unexpected pre-allocated property fields count"); 40873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpb(FieldOperand(map, Map::kUnusedPropertyFieldsOffset), 40883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(initial_map->unused_property_fields())); 40893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(equal, "Unexpected unused property fields count"); 40903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpb(FieldOperand(map, Map::kInObjectPropertiesOffset), 40913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(initial_map->inobject_properties())); 40923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(equal, "Unexpected in-object property fields count"); 40933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 40943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize map and fields of the newly allocated object. 40963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); 40973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(result, JSObject::kMapOffset), map); 40983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex); 40993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(result, JSObject::kElementsOffset), scratch); 41003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(result, JSObject::kPropertiesOffset), scratch); 41013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (initial_map->inobject_properties() != 0) { 41023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); 41033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < initial_map->inobject_properties(); i++) { 41043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int property_offset = JSObject::kHeaderSize + i * kPointerSize; 41053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(result, property_offset), scratch); 41063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 41073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 41083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 41093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(deferred->exit()); 41103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 41113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 41123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 41133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) { 41143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result = ToRegister(instr->result()); 41153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> constructor = instr->hydrogen()->constructor(); 41163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 41173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // TODO(3095996): Get rid of this. For now, we need to make the 41183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // result register contain a valid pointer because it is already 41193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // contained in the register pointer map. 41203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Set(result, 0); 41213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 41223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PushSafepointRegistersScope scope(this); 41233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushHeapObject(constructor); 41243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntimeFromDeferred(Runtime::kNewObject, 1, instr); 41253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ StoreToSafepointRegisterSlot(result, rax); 41265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 41275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 41285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 4129b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { 41303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap* heap = isolate()->heap(); 41313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind boilerplate_elements_kind = 41323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->hydrogen()->boilerplate_elements_kind(); 41333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 41343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Deopt if the array literal boilerplate ElementsKind is of a type different 41353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // than the expected one. The check isn't necessary if the boilerplate has 41363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // already been converted to FAST_ELEMENTS. 41373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (boilerplate_elements_kind != FAST_ELEMENTS) { 41383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object()); 41393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 41403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the map's "bit field 2". 41413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); 41423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Retrieve elements_kind from bit field 2. 41433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ and_(rbx, Immediate(Map::kElementsKindMask)); 41443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpb(rbx, Immediate(boilerplate_elements_kind << 41453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Map::kElementsKindShift)); 41463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(not_equal, instr->environment()); 41473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 41483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 41493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the parameters to the stub/runtime call. 41501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 41511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); 41521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); 41533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Boilerplate already exists, constant elements are never accessed. 41543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Pass an empty fixed array. 41553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Handle<FixedArray>(heap->empty_fixed_array())); 41561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 41571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Pick the right runtime function or stub to call. 41581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int length = instr->hydrogen()->length(); 41591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->IsCopyOnWrite()) { 41601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->hydrogen()->depth() == 1); 41611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FastCloneShallowArrayStub::Mode mode = 41621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; 41631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FastCloneShallowArrayStub stub(mode, length); 41641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 41651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (instr->hydrogen()->depth() > 1) { 41661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallRuntime(Runtime::kCreateArrayLiteral, 3, instr); 41671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 41681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr); 41691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 41701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FastCloneShallowArrayStub::Mode mode = 41713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch boilerplate_elements_kind == FAST_DOUBLE_ELEMENTS 41723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS 41733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : FastCloneShallowArrayStub::CLONE_ELEMENTS; 41741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FastCloneShallowArrayStub stub(mode, length); 41751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 41761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 4177b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4178b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4179b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 41803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EmitDeepCopy(Handle<JSObject> object, 41813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result, 41823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register source, 41833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int* offset) { 41843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!source.is(rcx)); 41853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!result.is(rcx)); 41863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 41873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Only elements backing stores for non-COW arrays need to be copied. 41883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArrayBase> elements(object->elements()); 41893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool has_elements = elements->length() > 0 && 41903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements->map() != isolate()->heap()->fixed_cow_array_map(); 41913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 41923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increase the offset so that subsequent objects end up right after 41933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // this object and its backing store. 41943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int object_offset = *offset; 41953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int object_size = object->map()->instance_size(); 41963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int elements_offset = *offset + object_size; 41973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int elements_size = has_elements ? elements->Size() : 0; 41983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *offset += object_size + elements_size; 41993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy object header. 42013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(object->properties()->length() == 0); 42023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int inobject_properties = object->map()->inobject_properties(); 42033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int header_size = object_size - inobject_properties * kPointerSize; 42043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < header_size; i += kPointerSize) { 42053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (has_elements && i == JSObject::kElementsOffset) { 42063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(rcx, Operand(result, elements_offset)); 42073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 42083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rcx, FieldOperand(source, i)); 42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(result, object_offset + i), rcx); 42113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy in-object properties. 42143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < inobject_properties; i++) { 42153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int total_offset = object_offset + object->GetInObjectPropertyOffset(i); 42163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> value = Handle<Object>(object->InObjectPropertyAt(i)); 42173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (value->IsJSObject()) { 42183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> value_object = Handle<JSObject>::cast(value); 42193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(rcx, Operand(result, *offset)); 42203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(result, total_offset), rcx); 42213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(source, value_object); 42223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitDeepCopy(value_object, result, source, offset); 42233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (value->IsHeapObject()) { 42243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(rcx, Handle<HeapObject>::cast(value)); 42253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(result, total_offset), rcx); 42263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 42273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rcx, value, RelocInfo::NONE); 42283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(result, total_offset), rcx); 42293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (has_elements) { 42333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy elements backing store header. 42343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(source, elements); 42353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < FixedArray::kHeaderSize; i += kPointerSize) { 42363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rcx, FieldOperand(source, i)); 42373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(result, elements_offset + i), rcx); 42383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy elements backing store content. 42413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int elements_length = elements->length(); 42423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements->IsFixedDoubleArray()) { 42433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedDoubleArray> double_array = 42443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedDoubleArray>::cast(elements); 42453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < elements_length; i++) { 42463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int64_t value = double_array->get_representation(i); 42473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int total_offset = 42483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements_offset + FixedDoubleArray::OffsetOfElementAt(i); 42493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rcx, value, RelocInfo::NONE); 42503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(result, total_offset), rcx); 42513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (elements->IsFixedArray()) { 42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < elements_length; i++) { 42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i); 42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> value = JSObject::GetElement(object, i); 42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (value->IsJSObject()) { 42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> value_object = Handle<JSObject>::cast(value); 42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(rcx, Operand(result, *offset)); 42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(result, total_offset), rcx); 42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(source, value_object); 42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitDeepCopy(value_object, result, source, offset); 42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (value->IsHeapObject()) { 42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(rcx, Handle<HeapObject>::cast(value)); 42643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(result, total_offset), rcx); 42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 42663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rcx, value, RelocInfo::NONE); 42673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(result, total_offset), rcx); 42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoFastLiteral(LFastLiteral* instr) { 42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = instr->hydrogen()->total_size(); 42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate all objects that are part of the literal in one big 42813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allocation. This avoids multiple limit checks. 42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label allocated, runtime_allocate; 42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); 42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&allocated); 42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&runtime_allocate); 42873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Smi::FromInt(size)); 42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); 42893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&allocated); 42913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset = 0; 42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); 42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitDeepCopy(instr->hydrogen()->boilerplate(), rax, rbx, &offset); 42943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(size, offset); 42953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 42963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { 42993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> literals(instr->environment()->closure()->literals()); 43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> constant_properties = 43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->hydrogen()->constant_properties(); 43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the parameters to the stub/runtime call. 43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushHeapObject(literals); 43051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); 43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(constant_properties); 43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int flags = instr->hydrogen()->fast_elements() 43083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? ObjectLiteral::kFastElements 43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : ObjectLiteral::kNoFlags; 43103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch flags |= instr->hydrogen()->has_function() 43113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? ObjectLiteral::kHasFunction 43123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : ObjectLiteral::kNoFlags; 43133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Smi::FromInt(flags)); 43141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 43153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Pick the right runtime function or stub to call. 43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int properties_count = constant_properties->length() / 2; 43171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->hydrogen()->depth() > 1) { 43181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallRuntime(Runtime::kCreateObjectLiteral, 4, instr); 43193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (flags != ObjectLiteral::kFastElements || 43203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { 432185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); 43223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 43233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastCloneShallowObjectStub stub(properties_count); 43243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 43251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 4326b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4327b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4328b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 432944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoToFastProperties(LToFastProperties* instr) { 433044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(ToRegister(instr->InputAt(0)).is(rax)); 433144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ push(rax); 433244f0eee88ff00398ff7f715fab053374d808c90dSteve Block CallRuntime(Runtime::kToFastProperties, 1, instr); 433344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 433444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 433544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4336b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { 4337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label materialized; 4338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Registers will be used as follows: 4339e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // rdi = JS function. 4340e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // rcx = literals array. 4341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // rbx = regexp literal. 4342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // rax = regexp literal clone. 4343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 4344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 4345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int literal_offset = FixedArray::kHeaderSize + 4346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch instr->hydrogen()->literal_index() * kPointerSize; 4347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rbx, FieldOperand(rcx, literal_offset)); 4348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); 4349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &materialized, Label::kNear); 4350e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4351e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Create regexp literal using runtime function 4352e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Result will be in rax. 4353e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(rcx); 4354e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); 4355e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(instr->hydrogen()->pattern()); 4356e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(instr->hydrogen()->flags()); 4357e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); 4358e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rbx, rax); 4359e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4360e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&materialized); 4361e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 4362e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Label allocated, runtime_allocate; 4363e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); 4364e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(&allocated); 4365e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4366e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&runtime_allocate); 4367e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(rbx); 4368e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(Smi::FromInt(size)); 4369e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); 4370e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ pop(rbx); 4371e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4372e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&allocated); 4373e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy the content into the newly allocated memory. 4374e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // (Unroll copy loop once for better throughput). 4375e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { 4376e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rdx, FieldOperand(rbx, i)); 4377e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rcx, FieldOperand(rbx, i + kPointerSize)); 4378e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(FieldOperand(rax, i), rdx); 4379e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(FieldOperand(rax, i + kPointerSize), rcx); 4380e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if ((size % (2 * kPointerSize)) != 0) { 4382e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(rdx, FieldOperand(rbx, size - kPointerSize)); 4383e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(FieldOperand(rax, size - kPointerSize), rdx); 4384e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4385b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4386b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4387b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4388b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { 43891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Use the fast case closure allocation code that allocates in new 43901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // space for nested functions that don't need literals cloning. 43911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<SharedFunctionInfo> shared_info = instr->shared_info(); 43921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool pretenure = instr->hydrogen()->pretenure(); 439344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!pretenure && shared_info->num_literals() == 0) { 43943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastNewClosureStub stub(shared_info->language_mode()); 43951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Push(shared_info); 43961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 43971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 43981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(rsi); 43991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Push(shared_info); 440044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ PushRoot(pretenure ? 440144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::kTrueValueRootIndex : 440244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::kFalseValueRootIndex); 44031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CallRuntime(Runtime::kNewClosure, 3, instr); 44041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 4405b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4406b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4407b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4408b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoTypeof(LTypeof* instr) { 4409e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* input = instr->InputAt(0); 4410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(input); 4411e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallRuntime(Runtime::kTypeof, 1, instr); 4412b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4413b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4414b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::EmitPushTaggedOperand(LOperand* operand) { 4416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!operand->IsDoubleRegister()); 4417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (operand->IsConstantOperand()) { 44183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object = ToHandle(LConstantOperand::cast(operand)); 44193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (object->IsSmi()) { 44203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Handle<Smi>::cast(object)); 44213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 44223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushHeapObject(Handle<HeapObject>::cast(object)); 44233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (operand->IsRegister()) { 4425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(ToRegister(operand)); 4426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 4427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(ToOperand(operand)); 4428e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 44291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 44301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 44311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4432b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 44331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 44341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 44351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 44361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* true_label = chunk_->GetAssemblyLabel(true_block); 44371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* false_label = chunk_->GetAssemblyLabel(false_block); 44381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 44393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition final_branch_condition = 44403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitTypeofIs(true_label, false_label, input, instr->type_literal()); 44413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (final_branch_condition != no_condition) { 44423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitBranch(true_block, false_block, final_branch_condition); 44433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4444b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4445b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4446b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4447b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochCondition LCodeGen::EmitTypeofIs(Label* true_label, 4448b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* false_label, 4449b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register input, 4450b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<String> type_name) { 44511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Condition final_branch_condition = no_condition; 445244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (type_name->Equals(heap()->number_symbol())) { 44531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, true_label); 445444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CompareRoot(FieldOperand(input, HeapObject::kMapOffset), 445544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Heap::kHeapNumberMapRootIndex); 445644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 44571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block final_branch_condition = equal; 44581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 445944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->string_symbol())) { 44601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, false_label); 4461e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); 4462e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(above_equal, false_label); 44631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(FieldOperand(input, Map::kBitFieldOffset), 44641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(1 << Map::kIsUndetectable)); 4465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch final_branch_condition = zero; 44661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 446744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->boolean_symbol())) { 44681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(input, Heap::kTrueValueRootIndex); 44691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, true_label); 44701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(input, Heap::kFalseValueRootIndex); 44711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block final_branch_condition = equal; 44721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 447369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_symbol())) { 447469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(input, Heap::kNullValueRootIndex); 447569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch final_branch_condition = equal; 447669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 447744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->undefined_symbol())) { 44781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CompareRoot(input, Heap::kUndefinedValueRootIndex); 44791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, true_label); 44801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, false_label); 44811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for undetectable objects => true. 44821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(input, FieldOperand(input, HeapObject::kMapOffset)); 44831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(FieldOperand(input, Map::kBitFieldOffset), 44841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(1 << Map::kIsUndetectable)); 44851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block final_branch_condition = not_zero; 44861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 448744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->function_symbol())) { 44883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 44891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, false_label); 44903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(input, JS_FUNCTION_TYPE, input); 44913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, true_label); 44923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE); 44933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch final_branch_condition = equal; 44941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 449544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->object_symbol())) { 44961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ JumpIfSmi(input, false_label); 449769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (!FLAG_harmony_typeof) { 449869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CompareRoot(input, Heap::kNullValueRootIndex); 449969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, true_label); 450069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 45013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); 4502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(below, false_label); 45033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 45043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above, false_label); 45051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check for undetectable objects => false. 45061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(FieldOperand(input, Map::kBitFieldOffset), 45071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(1 << Map::kIsUndetectable)); 4508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch final_branch_condition = zero; 45091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 45101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 45111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ jmp(false_label); 45121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 45131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 45141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return final_branch_condition; 4515b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4516b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4517b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 4519e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register temp = ToRegister(instr->TempAt(0)); 4520e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 4521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 4522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitIsConstructCall(temp); 4524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitBranch(true_block, false_block, equal); 4525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 4526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::EmitIsConstructCall(Register temp) { 4529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Get the frame pointer for the calling frame. 4530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 4531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Skip the arguments adaptor frame if it exists. 4533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label check_frame_marker; 453444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), 453544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 4536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &check_frame_marker, Label::kNear); 4537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 4538e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check the marker in the calling frame. 4540e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&check_frame_marker); 454144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), 454244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(StackFrame::CONSTRUCT)); 4543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 4544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 45462b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdochvoid LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { 45472b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // Ensure that we have enough space after the previous lazy-bailout 45482b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // instruction for patching the code here. 45492b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch int current_pc = masm()->pc_offset(); 45502b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch if (current_pc < last_lazy_deopt_pc_ + space_needed) { 45512b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; 45523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Nop(padding_size); 45532b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch } 45542b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch} 45552b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch 45562b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch 4557b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLazyBailout(LLazyBailout* instr) { 45582b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); 45592b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch last_lazy_deopt_pc_ = masm()->pc_offset(); 45602b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(instr->HasEnvironment()); 45612b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch LEnvironment* env = instr->environment(); 45622b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); 45632b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 4564b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4565b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4566b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4567b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoDeoptimize(LDeoptimize* instr) { 4568b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch DeoptimizeIf(no_condition, instr->environment()); 4569b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4570b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4571b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4572b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { 4573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* obj = instr->object(); 4574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* key = instr->key(); 4575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(obj); 4576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(key); 4577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 4578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LPointerMap* pointers = instr->pointer_map(); 4579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch RecordPosition(pointers->position()); 4580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Create safepoint generator that will also ensure enough space in the 4581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // reloc info for patching in deoptimization (since this is invoking a 4582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // builtin) 45832b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch SafepointGenerator safepoint_generator( 45842b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch this, pointers, Safepoint::kLazyDeopt); 4585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(Smi::FromInt(strict_mode_flag())); 4586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); 4587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 4588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoIn(LIn* instr) { 4591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LOperand* obj = instr->object(); 4592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LOperand* key = instr->key(); 4593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(key); 4594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitPushTaggedOperand(obj); 4595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 4596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LPointerMap* pointers = instr->pointer_map(); 4597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RecordPosition(pointers->position()); 45982b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch SafepointGenerator safepoint_generator( 45992b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch this, pointers, Safepoint::kLazyDeopt); 4600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); 4601b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4602b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4603b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 46043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { 46052b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch PushSafepointRegistersScope scope(this); 46062b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 46072b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch __ CallRuntimeSaveDoubles(Runtime::kStackGuard); 46082b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); 46092b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(instr->HasEnvironment()); 46102b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch LEnvironment* env = instr->environment(); 46112b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 46123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 46133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 46143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4615b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoStackCheck(LStackCheck* instr) { 46163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch class DeferredStackCheck: public LDeferredCode { 46173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public: 46183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) 46193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch : LDeferredCode(codegen), instr_(instr) { } 46203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } 46213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 46223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private: 46233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LStackCheck* instr_; 46243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch }; 4625b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 46262b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(instr->HasEnvironment()); 46272b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch LEnvironment* env = instr->environment(); 46282b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // There is no LLazyBailout instruction for stack-checks. We have to 46292b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // prepare for lazy deoptimization explicitly here. 46303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (instr->hydrogen()->is_function_entry()) { 46313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Perform stack overflow check. 46323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label done; 46333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 46343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above_equal, &done, Label::kNear); 46353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch StackCheckStub stub; 46363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 46372b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); 46382b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch last_lazy_deopt_pc_ = masm()->pc_offset(); 46393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&done); 46402b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); 46412b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 46423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 46433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(instr->hydrogen()->is_backwards_branch()); 46443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Perform stack overflow check if this goto needs it before jumping. 46453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DeferredStackCheck* deferred_stack_check = 46463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new DeferredStackCheck(this, instr); 46473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 46483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(below, deferred_stack_check->entry()); 46492b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); 46502b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch last_lazy_deopt_pc_ = masm()->pc_offset(); 46513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(instr->done_label()); 46523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch deferred_stack_check->SetExit(instr->done_label()); 46532b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); 46542b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // Don't record a deoptimization index for the safepoint here. 46552b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // This will be done explicitly when emitting call and the safepoint in 46562b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // the deferred code. 46573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 4658b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4659b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4660b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4661b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoOsrEntry(LOsrEntry* instr) { 4662e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This is a pseudo-instruction that ensures that the environment here is 4663e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // properly registered for deoptimization and records the assembler's PC 4664e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // offset. 4665e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LEnvironment* environment = instr->environment(); 4666e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch environment->SetSpilledRegisters(instr->SpilledRegisterArray(), 4667e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch instr->SpilledDoubleRegisterArray()); 4668e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4669e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If the environment were already registered, we would have no way of 4670e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // backpatching it with the spill slot operands. 4671e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(!environment->HasBeenRegistered()); 46722b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 4673e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(osr_pc_offset_ == -1); 4674e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch osr_pc_offset_ = masm()->pc_offset(); 4675b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 4676b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 46773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 46783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 46793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 46803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(equal, instr->environment()); 46813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 46823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register null_value = rdi; 46833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(null_value, Heap::kNullValueRootIndex); 46843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(rax, null_value); 46853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(equal, instr->environment()); 46863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 46873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc = masm()->CheckSmi(rax); 46883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(cc, instr->environment()); 46893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 46903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 46913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx); 46923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(below_equal, instr->environment()); 46933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 46943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label use_cache, call_runtime; 46953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckEnumCache(null_value, &call_runtime); 46963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 46973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); 46983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&use_cache, Label::kNear); 46993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 47003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the set of properties to enumerate. 47013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&call_runtime); 47023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(rax); 47033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); 47043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 47053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 47063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kMetaMapRootIndex); 47073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(not_equal, instr->environment()); 47083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&use_cache); 47093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 47103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 47113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 47123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 47133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map = ToRegister(instr->map()); 47143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result = ToRegister(instr->result()); 47153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadInstanceDescriptors(map, result); 47163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(result, 47173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldOperand(result, DescriptorArray::kEnumerationIndexOffset)); 47183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(result, 47193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 47203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc = masm()->CheckSmi(result); 47213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(cc, instr->environment()); 47223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 47233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 47243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 47253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 47263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object = ToRegister(instr->value()); 47273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(ToRegister(instr->map()), 47283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldOperand(object, HeapObject::kMapOffset)); 47293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(not_equal, instr->environment()); 47303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 47313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 47323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 47333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { 47343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object = ToRegister(instr->object()); 47353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register index = ToRegister(instr->index()); 47363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 47373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label out_of_object, done; 47383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(index, index); 47393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpl(index, Immediate(0)); 47403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(less, &out_of_object); 47413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(object, FieldOperand(object, 47423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 47433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_pointer_size, 47443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSObject::kHeaderSize)); 47453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done, Label::kNear); 47463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 47473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&out_of_object); 47483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(object, FieldOperand(object, JSObject::kPropertiesOffset)); 47493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ negl(index); 47503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Index is now equal to out of object property index plus 1. 47513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(object, FieldOperand(object, 47523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 47533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_pointer_size, 47543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize - kPointerSize)); 47553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 47563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 47573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 47583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4759b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#undef __ 4760b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4761b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} } // namespace v8::internal 4762b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4763b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif // V8_TARGET_ARCH_X64 4764