13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Redistribution and use in source and binary forms, with or without 3b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// modification, are permitted provided that the following conditions are 4b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// met: 5b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 6b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Redistributions of source code must retain the above copyright 7b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// notice, this list of conditions and the following disclaimer. 8b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Redistributions in binary form must reproduce the above 9b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// copyright notice, this list of conditions and the following 10b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// disclaimer in the documentation and/or other materials provided 11b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// with the distribution. 12b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Neither the name of Google Inc. nor the names of its 13b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// contributors may be used to endorse or promote products derived 14b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// from this software without specific prior written permission. 15b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 16b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 28b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#include "v8.h" 29b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 30b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#if defined(V8_TARGET_ARCH_IA32) 31b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "ia32/lithium-codegen-ia32.h" 33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "code-stubs.h" 3444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "deoptimizer.h" 35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "stub-cache.h" 363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "codegen.h" 37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 38b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 { 39b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal { 40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// When invoking builtins, we need to record the safepoint in the middle of 431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// the invoke instruction sequence generated by the macro assembler. 44257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass SafepointGenerator : public CallWrapper { 45b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 46b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SafepointGenerator(LCodeGen* codegen, 47b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LPointerMap* pointers, 482b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Safepoint::DeoptMode mode) 49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : codegen_(codegen), 50b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pointers_(pointers), 512b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch deopt_mode_(mode) {} 52b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual ~SafepointGenerator() { } 53b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 54257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch virtual void BeforeCall(int call_size) const {} 55257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 56257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch virtual void AfterCall() const { 572b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch codegen_->RecordSafepoint(pointers_, deopt_mode_); 58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 60b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 61b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LCodeGen* codegen_; 62b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LPointerMap* pointers_; 632b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Safepoint::DeoptMode deopt_mode_; 64b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 65b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 66b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 67b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define __ masm()-> 68b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 69b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool LCodeGen::GenerateCode() { 703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("Z_Code generation", chunk()); 71b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(is_unused()); 72b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch status_ = GENERATING; 73b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CpuFeatures::Scope scope(SSE2); 743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeStub::GenerateFPStubs(); 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Open a frame scope to indicate that there is a frame on the stack. The 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // MANUAL indicates that the scope shouldn't actually generate code to set up 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the frame (that is done in GeneratePrologue). 803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm_, StackFrame::MANUAL); 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return GeneratePrologue() && 83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch GenerateBody() && 84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch GenerateDeferredCode() && 85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch GenerateSafepointTable(); 86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::FinishCode(Handle<Code> code) { 90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(is_done()); 91257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch code->set_stack_slots(GetStackSlotCount()); 921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); 93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PopulateDeoptimizationData(code); 9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code); 95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::Abort(const char* format, ...) { 99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_bailout) { 100589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SmartArrayPointer<char> name( 101589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch info()->shared_info()->DebugName()->ToCString()); 102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PrintF("Aborting LCodeGen in @\"%s\": ", *name); 103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_list arguments; 104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_start(arguments, format); 105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch OS::VPrint(format, arguments); 106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_end(arguments); 107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("\n"); 108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch status_ = ABORTED; 110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::Comment(const char* format, ...) { 114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!FLAG_code_comments) return; 115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch char buffer[4 * KB]; 116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StringBuilder builder(buffer, ARRAY_SIZE(buffer)); 117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_list arguments; 118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_start(arguments, format); 119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder.AddFormattedList(format, arguments); 120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_end(arguments); 121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Copy the string before recording it in the assembler to avoid 123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // issues when the stack allocated buffer goes out of scope. 124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch size_t length = builder.position(); 125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Vector<char> copy = Vector<char>::New(length + 1); 126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memcpy(copy.start(), builder.Finalize(), copy.length()); 127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch masm()->RecordComment(copy.start()); 128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool LCodeGen::GeneratePrologue() { 132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(is_generating()); 133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (strlen(FLAG_stop_at) > 0 && 136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ int3(); 138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Strict mode functions and builtins need to replace the receiver 1423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // with undefined when called as functions (without an explicit 1433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // receiver object). ecx is zero for method calls and non-zero for 1443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // function calls. 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!info_->is_classic_mode() || info_->is_native()) { 146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ test(ecx, Operand(ecx)); 148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &ok, Label::kNear); 149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // +1 for return address. 150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; 151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(Operand(esp, receiver_offset), 152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Immediate(isolate()->factory()->undefined_value())); 153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&ok); 154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(ebp); // Caller's frame pointer. 157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ebp, esp); 158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(esi); // Callee's context. 159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(edi); // Callee's JS function. 160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Reserve space for the stack slots needed by the code. 162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int slots = GetStackSlotCount(); 163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (slots > 0) { 164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_debug_code) { 165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(Operand(eax), Immediate(slots)); 166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label loop; 167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&loop); 168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(Immediate(kSlotsZapValue)); 169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ dec(eax); 170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(not_zero, &loop); 171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ sub(Operand(esp), Immediate(slots * kPointerSize)); 173b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#ifdef _MSC_VER 174b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // On windows, you may not access the stack more than one page below 175b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // the most recently mapped page. To make the allocated area randomly 176b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // accessible, we write to each page in turn (the value is irrelevant). 177b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch const int kPageSize = 4 * KB; 178b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch for (int offset = slots * kPointerSize - kPageSize; 179b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch offset > 0; 180b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch offset -= kPageSize) { 181b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ mov(Operand(esp, offset), eax); 182b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 183b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif 184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Possibly allocate a local context. 188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (heap_slots > 0) { 190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Comment(";;; Allocate local context"); 191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Argument to NewContext is the function, which is still in edi. 192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(edi); 193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (heap_slots <= FastNewContextStub::kMaximumSlots) { 194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FastNewContextStub stub(heap_slots); 195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallStub(&stub); 196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 1973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CallRuntime(Runtime::kNewFunctionContext, 1); 198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1992b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepoint(Safepoint::kNoLazyDeopt); 200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Context is returned in both eax and esi. It replaces the context 201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // passed to us. It's saved in the stack and kept live in esi. 202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); 203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Copy parameters into context if necessary. 205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int num_parameters = scope()->num_parameters(); 206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < num_parameters; i++) { 207589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = scope()->parameter(i); 208589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int parameter_offset = StandardFrameConstants::kCallerSPOffset + 210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (num_parameters - 1 - i) * kPointerSize; 211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Load parameter from stack. 212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(eax, Operand(ebp, parameter_offset)); 213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Store it in the context. 214589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int context_offset = Context::SlotOffset(var->index()); 215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(Operand(esi, context_offset), eax); 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the write barrier. This clobbers eax and ebx. 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot(esi, 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context_offset, 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eax, 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ebx, 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 224e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Comment(";;; End allocate local context"); 225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Trace the call. 228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace) { 2291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We have not executed any compiled code yet, so esi still holds the 2301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // incoming context. 231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CallRuntime(Runtime::kTraceEnter, 0); 232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return !is_aborted(); 234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool LCodeGen::GenerateBody() { 238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(is_generating()); 239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool emit_instructions = true; 240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (current_instruction_ = 0; 241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !is_aborted() && current_instruction_ < instructions_->length(); 242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_instruction_++) { 243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LInstruction* instr = instructions_->at(current_instruction_); 244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->IsLabel()) { 245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LLabel* label = LLabel::cast(instr); 246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch emit_instructions = !label->HasReplacement(); 247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (emit_instructions) { 250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic()); 251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->CompileToNative(this); 252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2542b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch EnsureSpaceForLazyDeopt(); 255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return !is_aborted(); 256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool LCodeGen::GenerateDeferredCode() { 260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(is_generating()); 2613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (deferred_.length() > 0) { 2623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 2633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LDeferredCode* code = deferred_[i]; 2643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(code->entry()); 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Comment(";;; Deferred code @%d: %s.", 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch code->instruction_index(), 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch code->instr()->Mnemonic()); 2683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch code->Generate(); 2693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(code->exit()); 2703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Deferred code is the last part of the instruction sequence. Mark 274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the generated code as done unless we bailed out. 275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!is_aborted()) status_ = DONE; 276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return !is_aborted(); 277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool LCodeGen::GenerateSafepointTable() { 281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(is_done()); 282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch safepoints_.Emit(masm(), GetStackSlotCount()); 283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return !is_aborted(); 284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochRegister LCodeGen::ToRegister(int index) const { 288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Register::FromAllocationIndex(index); 289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochXMMRegister LCodeGen::ToDoubleRegister(int index) const { 293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return XMMRegister::FromAllocationIndex(index); 294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochRegister LCodeGen::ToRegister(LOperand* op) const { 298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(op->IsRegister()); 299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return ToRegister(op->index()); 300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochXMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { 304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(op->IsDoubleRegister()); 305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return ToDoubleRegister(op->index()); 306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint LCodeGen::ToInteger32(LConstantOperand* op) const { 310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Object> value = chunk_->LookupLiteral(op); 311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32()); 312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) == 313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->Number()); 314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return static_cast<int32_t>(value->Number()); 315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { 3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> literal = chunk_->LookupLiteral(op); 3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged()); 3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return literal; 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochdouble LCodeGen::ToDouble(LConstantOperand* op) const { 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> value = chunk_->LookupLiteral(op); 3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return value->Number(); 3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool LCodeGen::IsInteger32(LConstantOperand* op) const { 3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return chunk_->LookupLiteralRepresentation(op).IsInteger32(); 333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochOperand LCodeGen::ToOperand(LOperand* op) const { 337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op->IsRegister()) return Operand(ToRegister(op)); 338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op->IsDoubleRegister()) return Operand(ToDoubleRegister(op)); 339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); 340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = op->index(); 341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (index >= 0) { 342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Local or spill slot. Skip the frame pointer, function, and 343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // context in the fixed part of the frame. 344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Operand(ebp, -(index + 3) * kPointerSize); 345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Incoming parameter. Skip the return address. 347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Operand(ebp, -(index - 1) * kPointerSize); 348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 352b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochOperand LCodeGen::HighOperand(LOperand* op) { 353b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(op->IsDoubleStackSlot()); 354b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int index = op->index(); 355b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int offset = (index >= 0) ? index + 3 : index - 1; 356b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return Operand(ebp, -offset * kPointerSize); 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 411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::AddToTranslation(Translation* translation, 412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* op, 413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_tagged) { 414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == NULL) { 415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(twuerthinger): Introduce marker operands to indicate that this value 416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // is not present and must be reconstructed from the deoptimizer. Currently 417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // this is only used for the arguments object. 418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch translation->StoreArgumentsObject(); 419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op->IsStackSlot()) { 420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_tagged) { 421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch translation->StoreStackSlot(op->index()); 422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch translation->StoreInt32StackSlot(op->index()); 424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op->IsDoubleStackSlot()) { 426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch translation->StoreDoubleStackSlot(op->index()); 427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op->IsArgument()) { 428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(is_tagged); 429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int src_index = GetStackSlotCount() + op->index(); 430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch translation->StoreStackSlot(src_index); 431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op->IsRegister()) { 432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register reg = ToRegister(op); 433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_tagged) { 434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch translation->StoreRegister(reg); 435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch translation->StoreInt32Register(reg); 437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op->IsDoubleRegister()) { 439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch XMMRegister reg = ToDoubleRegister(op); 440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch translation->StoreDoubleRegister(reg); 441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op->IsConstantOperand()) { 442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Object> literal = chunk()->LookupLiteral(LConstantOperand::cast(op)); 443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int src_index = DefineDeoptimizationLiteral(literal); 444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch translation->StoreLiteral(src_index); 445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::CallCodeGeneric(Handle<Code> code, 4528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::Mode mode, 4538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch LInstruction* instr, 4548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SafepointMode safepoint_mode) { 4551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr != NULL); 4561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LPointerMap* pointers = instr->pointer_map(); 4571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RecordPosition(pointers->position()); 4581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ call(code, mode); 4592b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepointWithLazyDeopt(instr, safepoint_mode); 460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Signal that we don't inline smi code before these stubs in the 462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // optimizing code generator. 463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (code->kind() == Code::BINARY_OP_IC || 464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch code->kind() == Code::COMPARE_IC) { 465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ nop(); 466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::CallCode(Handle<Code> code, 4718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::Mode mode, 4723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LInstruction* instr) { 4733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); 4748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 4758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 4768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 47744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::CallRuntime(const Runtime::Function* fun, 4781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int argc, 4793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LInstruction* instr) { 480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(instr != NULL); 4811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->HasPointerMap()); 482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LPointerMap* pointers = instr->pointer_map(); 483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RecordPosition(pointers->position()); 484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CallRuntime(fun, argc); 48644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4872b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, 4928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int argc, 4933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LInstruction* instr, 4943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LOperand* context) { 4953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (context->IsRegister()) { 4963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!ToRegister(context).is(esi)) { 4973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(esi, ToRegister(context)); 4983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (context->IsStackSlot()) { 50085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ mov(esi, ToOperand(context)); 5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (context->IsConstantOperand()) { 5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> literal = 5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch chunk_->LookupLiteral(LConstantOperand::cast(context)); 5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(esi, Handle<Context>::cast(literal)); 5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 5073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 5083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 5098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ CallRuntimeSaveDoubles(id); 5108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RecordSafepointWithRegisters( 5112b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); 5128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 5138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5152b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdochvoid LCodeGen::RegisterEnvironmentForDeoptimization( 5162b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch LEnvironment* environment, Safepoint::DeoptMode mode) { 517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!environment->HasBeenRegistered()) { 518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Physical stack frame layout: 519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -x ............. -4 0 ..................................... y 520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // [incoming arguments] [spill slots] [pushed outgoing arguments] 521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Layout of the environment: 523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // 0 ..................................................... size-1 524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // [parameters] [locals] [expression stack including arguments] 525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Layout of the translation: 527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // 0 ........................................................ size - 1 + 4 528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // [expression stack including arguments] [locals] [4 words] [parameters] 529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // |>------------ translation_size ------------<| 530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int frame_count = 0; 5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int jsframe_count = 0; 533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (LEnvironment* e = environment; e != NULL; e = e->outer()) { 534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ++frame_count; 5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (e->frame_type() == JS_FUNCTION) { 5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++jsframe_count; 5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Translation translation(&translations_, frame_count, jsframe_count); 540b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch WriteTranslation(environment, &translation); 541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int deoptimization_index = deoptimizations_.length(); 5422b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch int pc_offset = masm()->pc_offset(); 5432b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch environment->Register(deoptimization_index, 5442b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch translation.index(), 5452b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); 546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch deoptimizations_.Add(environment); 547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) { 5522b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(environment->HasBeenRegistered()); 554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int id = environment->deoptimization_index(); 555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER); 556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (entry == NULL) { 557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Abort("bailout was not prepared"); 558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_deopt_every_n_times != 0) { 562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<SharedFunctionInfo> shared(info_->shared_info()); 563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label no_deopt; 564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pushfd(); 565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(eax); 566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(ebx); 567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ebx, shared); 568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(eax, FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset)); 569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &no_deopt, Label::kNear); 571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trap_on_deopt) __ int3(); 572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(eax, Immediate(Smi::FromInt(FLAG_deopt_every_n_times))); 573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax); 574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(ebx); 575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(eax); 576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ popfd(); 577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ jmp(entry, RelocInfo::RUNTIME_ENTRY); 578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&no_deopt); 580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax); 581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(ebx); 582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(eax); 583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ popfd(); 584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (cc == no_condition) { 587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trap_on_deopt) __ int3(); 588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ jmp(entry, RelocInfo::RUNTIME_ENTRY); 589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trap_on_deopt) { 591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(NegateCondition(cc), &done, Label::kNear); 593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ int3(); 594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ jmp(entry, RelocInfo::RUNTIME_ENTRY); 595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&done); 596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(cc, entry, RelocInfo::RUNTIME_ENTRY); 598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { 604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = deoptimizations_.length(); 605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (length == 0) return; 606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<DeoptimizationInputData> data = 60744f0eee88ff00398ff7f715fab053374d808c90dSteve Block factory()->NewDeoptimizationInputData(length, TENURED); 608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 609e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<ByteArray> translations = translations_.CreateByteArray(); 610e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch data->SetTranslationByteArray(*translations); 611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); 612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<FixedArray> literals = 61444f0eee88ff00398ff7f715fab053374d808c90dSteve Block factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); 615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < deoptimization_literals_.length(); i++) { 616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch literals->set(i, *deoptimization_literals_[i]); 617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data->SetLiteralArray(*literals); 619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id())); 621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_)); 622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Populate the deoptimization entries. 624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < length; i++) { 625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LEnvironment* env = deoptimizations_[i]; 626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data->SetAstId(i, Smi::FromInt(env->ast_id())); 627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data->SetTranslationIndex(i, Smi::FromInt(env->translation_index())); 628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch data->SetArgumentsStackHeight(i, 629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Smi::FromInt(env->arguments_stack_height())); 6302b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch data->SetPc(i, Smi::FromInt(env->pc_offset())); 631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch code->set_deoptimization_data(*data); 633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) { 637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int result = deoptimization_literals_.length(); 638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < deoptimization_literals_.length(); ++i) { 639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (deoptimization_literals_[i].is_identical_to(literal)) return i; 640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch deoptimization_literals_.Add(literal); 642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() { 647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(deoptimization_literals_.length() == 0); 648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<Handle<JSFunction> >* inlined_closures = 650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch chunk()->inlined_closures(); 651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0, length = inlined_closures->length(); 653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch i < length; 654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch i++) { 655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DefineDeoptimizationLiteral(inlined_closures->at(i)); 656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inlined_function_count_ = deoptimization_literals_.length(); 659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6622b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdochvoid LCodeGen::RecordSafepointWithLazyDeopt( 6632b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch LInstruction* instr, SafepointMode safepoint_mode) { 6642b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { 6652b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt); 6662b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch } else { 6672b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); 6682b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepointWithRegisters( 6692b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch instr->pointer_map(), 0, Safepoint::kLazyDeopt); 6702b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch } 6712b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch} 6722b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch 6732b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch 6741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::RecordSafepoint( 6751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LPointerMap* pointers, 6761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Safepoint::Kind kind, 6771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int arguments, 6782b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Safepoint::DeoptMode deopt_mode) { 6798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(kind == expected_safepoint_kind_); 6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands(); 6812b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Safepoint safepoint = 6822b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch safepoints_.DefineSafepoint(masm(), kind, arguments, deopt_mode); 683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < operands->length(); i++) { 684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* pointer = operands->at(i); 685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (pointer->IsStackSlot()) { 686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch safepoint.DefinePointerSlot(pointer->index()); 6871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { 6881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block safepoint.DefinePointerRegister(ToRegister(pointer)); 689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::RecordSafepoint(LPointerMap* pointers, 6952b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Safepoint::DeoptMode mode) { 6962b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepoint(pointers, Safepoint::kSimple, 0, mode); 6971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 6981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7002b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdochvoid LCodeGen::RecordSafepoint(Safepoint::DeoptMode mode) { 701e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LPointerMap empty_pointers(RelocInfo::kNoPosition); 7022b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepoint(&empty_pointers, mode); 703e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 705e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, 707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int arguments, 7082b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Safepoint::DeoptMode mode) { 7092b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, mode); 710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::RecordPosition(int position) { 7143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (position == RelocInfo::kNoPosition) return; 715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch masm()->positions_recorder()->RecordPosition(position); 716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoLabel(LLabel* label) { 720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (label->is_loop_header()) { 721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Comment(";;; B%d - LOOP entry", label->block_id()); 722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Comment(";;; B%d", label->block_id()); 724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(label->label()); 726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_block_ = label->block_id(); 727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DoGap(label); 728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoParallelMove(LParallelMove* move) { 732b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch resolver_.Resolve(move); 733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoGap(LGap* gap) { 737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = LGap::FIRST_INNER_POSITION; 738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch i <= LGap::LAST_INNER_POSITION; 739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch i++) { 740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); 741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LParallelMove* move = gap->GetParallelMove(inner_pos); 742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (move != NULL) DoParallelMove(move); 743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoInstructionGap(LInstructionGap* instr) { 748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DoGap(instr); 749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoParameter(LParameter* instr) { 753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Nothing to do. 754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCallStub(LCallStub* instr) { 7581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->context()).is(esi)); 759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->result()).is(eax)); 760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (instr->hydrogen()->major_key()) { 761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case CodeStub::RegExpConstructResult: { 762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RegExpConstructResultStub stub; 7633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case CodeStub::RegExpExec: { 767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RegExpExecStub stub; 7683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case CodeStub::SubString: { 772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubStringStub stub; 7733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case CodeStub::NumberToString: { 777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch NumberToStringStub stub; 7783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case CodeStub::StringAdd: { 782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StringAddStub stub(NO_STRING_ADD_FLAGS); 7833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case CodeStub::StringCompare: { 787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StringCompareStub stub; 7883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case CodeStub::TranscendentalCache: { 792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TranscendentalCacheStub stub(instr->transcendental_type(), 793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TranscendentalCacheStub::TAGGED); 7943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Nothing to do. 805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoModI(LModI* instr) { 80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->HasPowerOf2Divisor()) { 81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register dividend = ToRegister(instr->InputAt(0)); 811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int32_t divisor = 81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block HConstant::cast(instr->hydrogen()->right())->Integer32Value(); 814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 81544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (divisor < 0) divisor = -divisor; 816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label positive_dividend, done; 81844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ test(dividend, Operand(dividend)); 819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_sign, &positive_dividend, Label::kNear); 82044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ neg(dividend); 82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(dividend, divisor - 1); 82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ neg(dividend); 82344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &done, Label::kNear); 82544f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(no_condition, instr->environment()); 8267d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } else { 827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 82844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 82944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&positive_dividend); 83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ and_(dividend, divisor - 1); 83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 83244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, remainder_eq_dividend, slow, do_subtraction, both_positive; 834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left_reg = ToRegister(instr->InputAt(0)); 835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register right_reg = ToRegister(instr->InputAt(1)); 836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result_reg = ToRegister(instr->result()); 837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(left_reg.is(eax)); 839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(result_reg.is(edx)); 84044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!right_reg.is(eax)); 84144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!right_reg.is(edx)); 842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 84344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check for x % 0. 84444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ test(right_reg, Operand(right_reg)); 84644f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(zero, instr->environment()); 84744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ test(left_reg, Operand(left_reg)); 850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &remainder_eq_dividend, Label::kNear); 851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(sign, &slow, Label::kNear); 852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ test(right_reg, Operand(right_reg)); 854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_sign, &both_positive, Label::kNear); 855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The sign of the divisor doesn't matter. 856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ neg(right_reg); 857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&both_positive); 859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the dividend is smaller than the nonnegative 860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // divisor, the dividend is the result. 861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(left_reg, Operand(right_reg)); 862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(less, &remainder_eq_dividend, Label::kNear); 863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the divisor is a PowerOfTwo integer. 865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch = ToRegister(instr->TempAt(0)); 866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(scratch, right_reg); 867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sub(Operand(scratch), Immediate(1)); 868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ test(scratch, Operand(right_reg)); 869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &do_subtraction, Label::kNear); 870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ and_(left_reg, Operand(scratch)); 871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&remainder_eq_dividend, Label::kNear); 872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&do_subtraction); 874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kUnfolds = 3; 875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Try a few subtractions of the dividend. 876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(scratch, left_reg); 877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < kUnfolds; i++) { 878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Reduce the dividend by the divisor. 879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sub(left_reg, Operand(right_reg)); 880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the dividend is less than the divisor. 881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(left_reg, Operand(right_reg)); 882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(less, &remainder_eq_dividend, Label::kNear); 883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(left_reg, scratch); 885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Slow case, using idiv instruction. 887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Sign extend to edx. 88944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cdq(); 89044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 89144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check for (0 % -x) that will produce negative zero. 89244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label positive_left; 894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ test(left_reg, Operand(left_reg)); 896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_sign, &positive_left, Label::kNear); 89744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ idiv(right_reg); 89844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 89944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Test the remainder for 0, because then the result would be -0. 900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ test(result_reg, Operand(result_reg)); 901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &done, Label::kNear); 90244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 90344f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(no_condition, instr->environment()); 90444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&positive_left); 90544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ idiv(right_reg); 90644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 90744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 90844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ idiv(right_reg); 90944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&remainder_eq_dividend); 913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(result_reg, left_reg); 914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoDivI(LDivI* instr) { 921b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* right = instr->InputAt(1); 922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->result()).is(eax)); 923b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(ToRegister(instr->InputAt(0)).is(eax)); 924b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(!ToRegister(instr->InputAt(1)).is(eax)); 925b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(!ToRegister(instr->InputAt(1)).is(edx)); 926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register left_reg = eax; 928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check for x / 0. 930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register right_reg = ToRegister(right); 931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(right_reg, ToOperand(right)); 933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(zero, instr->environment()); 934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check for (0 / -x) that will produce negative zero. 937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label left_not_zero; 939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(left_reg, Operand(left_reg)); 940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &left_not_zero, Label::kNear); 941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(right_reg, ToOperand(right)); 942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(sign, instr->environment()); 943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&left_not_zero); 944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check for (-kMinInt / -1). 947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label left_not_min_int; 949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(left_reg, kMinInt); 950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &left_not_min_int, Label::kNear); 951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(right_reg, -1); 952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(zero, instr->environment()); 953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&left_not_min_int); 954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Sign extend to edx. 957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cdq(); 958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ idiv(right_reg); 959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Deoptimize if remainder is not 0. 961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(edx, Operand(edx)); 962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(not_zero, instr->environment()); 963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoMulI(LMulI* instr) { 967b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register left = ToRegister(instr->InputAt(0)); 968b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* right = instr->InputAt(1); 969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 971b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ mov(ToRegister(instr->TempAt(0)), left); 972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (right->IsConstantOperand()) { 97544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Try strength reductions on the multiplication. 97644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // All replacement instructions are at most as long as the imul 97744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // and have better latency. 97844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int constant = ToInteger32(LConstantOperand::cast(right)); 97944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (constant == -1) { 98044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ neg(left); 98144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (constant == 0) { 98244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ xor_(left, Operand(left)); 98344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (constant == 2) { 98444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ add(left, Operand(left)); 98544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (!instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 98644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If we know that the multiplication can't overflow, it's safe to 98744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // use instructions that don't set the overflow flag for the 98844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // multiplication. 98944f0eee88ff00398ff7f715fab053374d808c90dSteve Block switch (constant) { 99044f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 1: 99144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Do nothing. 99244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 99344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 3: 99444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ lea(left, Operand(left, left, times_2, 0)); 99544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 99644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 4: 99744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ shl(left, 2); 99844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 99944f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 5: 100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ lea(left, Operand(left, left, times_4, 0)); 100144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 100244f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 8: 100344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ shl(left, 3); 100444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 100544f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 9: 100644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ lea(left, Operand(left, left, times_8, 0)); 100744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 100844f0eee88ff00398ff7f715fab053374d808c90dSteve Block case 16: 100944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ shl(left, 4); 101044f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 101144f0eee88ff00398ff7f715fab053374d808c90dSteve Block default: 101244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ imul(left, left, constant); 101344f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 101444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 101544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 101644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ imul(left, left, constant); 101744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ imul(left, ToOperand(right)); 1020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(overflow, instr->environment()); 1024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Bail out if the result is supposed to be negative zero. 1028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 1029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(left, Operand(left)); 1030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &done, Label::kNear); 1031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (right->IsConstantOperand()) { 10321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (ToInteger32(LConstantOperand::cast(right)) <= 0) { 1033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(no_condition, instr->environment()); 1034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Test the non-zero operand for negative sign. 1037b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ or_(ToRegister(instr->TempAt(0)), ToOperand(right)); 1038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(sign, instr->environment()); 1039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&done); 1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoBitI(LBitI* instr) { 1046b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* left = instr->InputAt(0); 1047b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* right = instr->InputAt(1); 1048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(left->Equals(instr->result())); 1049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(left->IsRegister()); 1050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (right->IsConstantOperand()) { 1052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int right_operand = ToInteger32(LConstantOperand::cast(right)); 1053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (instr->op()) { 1054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::BIT_AND: 1055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ and_(ToRegister(left), right_operand); 1056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::BIT_OR: 1058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ or_(ToRegister(left), right_operand); 1059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::BIT_XOR: 1061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ xor_(ToRegister(left), right_operand); 1062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 1065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (instr->op()) { 1069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::BIT_AND: 1070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ and_(ToRegister(left), ToOperand(right)); 1071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::BIT_OR: 1073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ or_(ToRegister(left), ToOperand(right)); 1074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::BIT_XOR: 1076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ xor_(ToRegister(left), ToOperand(right)); 1077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoShiftI(LShiftI* instr) { 1087b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* left = instr->InputAt(0); 1088b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* right = instr->InputAt(1); 1089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(left->Equals(instr->result())); 1090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(left->IsRegister()); 1091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (right->IsRegister()) { 1092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(right).is(ecx)); 1093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (instr->op()) { 1095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SAR: 1096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ sar_cl(ToRegister(left)); 1097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SHR: 1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ shr_cl(ToRegister(left)); 1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->can_deopt()) { 1101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(ToRegister(left), Immediate(0x80000000)); 1102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(not_zero, instr->environment()); 1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SHL: 1106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ shl_cl(ToRegister(left)); 1107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 1109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int value = ToInteger32(LConstantOperand::cast(right)); 1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); 1115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (instr->op()) { 1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SAR: 1117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (shift_count != 0) { 1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ sar(ToRegister(left), shift_count); 1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SHR: 1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (shift_count == 0 && instr->can_deopt()) { 1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(ToRegister(left), Immediate(0x80000000)); 1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(not_zero, instr->environment()); 1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ shr(ToRegister(left), shift_count); 1127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SHL: 1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (shift_count != 0) { 1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ shl(ToRegister(left), shift_count); 1132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 1136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoSubI(LSubI* instr) { 1143b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* left = instr->InputAt(0); 1144b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* right = instr->InputAt(1); 1145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(left->Equals(instr->result())); 1146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (right->IsConstantOperand()) { 11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(ToOperand(left), ToInteger32Immediate(right)); 1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ sub(ToRegister(left), ToOperand(right)); 1151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(overflow, instr->environment()); 1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoConstantI(LConstantI* instr) { 1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(instr->result()->IsRegister()); 11609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Set(ToRegister(instr->result()), Immediate(instr->value())); 1161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoConstantD(LConstantD* instr) { 1165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(instr->result()->IsDoubleRegister()); 1166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch XMMRegister res = ToDoubleRegister(instr->result()); 1167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double v = instr->value(); 1168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Use xor to produce +0.0 in a fast and compact way, but avoid to 1169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // do so if the constant is -0.0. 1170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (BitCast<uint64_t, double>(v) == 0) { 1171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(res, res); 1172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 11731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register temp = ToRegister(instr->TempAt(0)); 11741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block uint64_t int_val = BitCast<uint64_t, double>(v); 11751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int32_t lower = static_cast<int32_t>(int_val); 11761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); 11778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(SSE4_1)) { 11781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CpuFeatures::Scope scope(SSE4_1); 11791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (lower != 0) { 11801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Set(temp, Immediate(lower)); 11811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movd(res, Operand(temp)); 11821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Set(temp, Immediate(upper)); 11831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pinsrd(res, Operand(temp), 1); 11841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 1185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(res, res); 11861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Set(temp, Immediate(upper)); 11871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pinsrd(res, Operand(temp), 1); 11881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 11901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Set(temp, Immediate(upper)); 11911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movd(res, Operand(temp)); 11921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ psllq(res, 32); 11931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (lower != 0) { 11941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Set(temp, Immediate(lower)); 11951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movd(xmm0, Operand(temp)); 11961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ por(res, xmm0); 11971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoConstantT(LConstantT* instr) { 12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = ToRegister(instr->result()); 12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> handle = instr->value(); 12063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (handle->IsHeapObject()) { 12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(reg, Handle<HeapObject>::cast(handle)); 12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Set(reg, Immediate(handle)); 12103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 12149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { 1215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register result = ToRegister(instr->result()); 1216b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register array = ToRegister(instr->InputAt(0)); 12179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ mov(result, FieldOperand(array, JSArray::kLengthOffset)); 12189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 1219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 122169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid LCodeGen::DoFixedArrayBaseLength( 122269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch LFixedArrayBaseLength* instr) { 12239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register result = ToRegister(instr->result()); 1224b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register array = ToRegister(instr->InputAt(0)); 122569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(result, FieldOperand(array, FixedArrayBase::kLengthOffset)); 12261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 12271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 12293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoElementsKind(LElementsKind* instr) { 12303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register result = ToRegister(instr->result()); 12313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register input = ToRegister(instr->InputAt(0)); 12323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 12333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Load map into |result|. 12343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(result, FieldOperand(input, HeapObject::kMapOffset)); 12353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Load the map's "bit field 2" into |result|. We only need the first byte, 12363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // but the following masking takes care of that anyway. 12373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(result, FieldOperand(result, Map::kBitField2Offset)); 12383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Retrieve elements_kind from bit field 2. 12393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ and_(result, Map::kElementsKindMask); 12403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ shr(result, Map::kElementsKindShift); 12413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 12423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 12433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoValueOf(LValueOf* instr) { 1245b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register input = ToRegister(instr->InputAt(0)); 1246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register result = ToRegister(instr->result()); 1247b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register map = ToRegister(instr->TempAt(0)); 1248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(input.is(result)); 12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 1251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If the object is a smi return the object. 12523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(input, &done, Label::kNear); 1253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If the object is not a value type, return the object. 1255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CmpObjectType(input, JS_VALUE_TYPE, map); 1256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &done, Label::kNear); 1257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result, FieldOperand(input, JSValue::kValueOffset)); 1258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&done); 1260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDateField(LDateField* instr) { 12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object = ToRegister(instr->InputAt(0)); 12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result = ToRegister(instr->result()); 12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = ToRegister(instr->TempAt(0)); 12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi* index = instr->index(); 12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label runtime, done; 12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(object.is(result)); 12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(object.is(eax)); 12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG 12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AbortIfSmi(object); 12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(object, JS_DATE_TYPE, scratch); 12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(equal, "Trying to get date field from non-date."); 12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (index->value() == 0) { 12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(result, FieldOperand(object, JSDate::kValueOffset)); 12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (index->value() < JSDate::kFirstUncachedField) { 12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch, Operand::StaticVariable(stamp)); 12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); 12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &runtime, Label::kNear); 12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(result, FieldOperand(object, JSDate::kValueOffset + 12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kPointerSize * index->value())); 12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&runtime); 12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(2, scratch); 12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(Operand(esp, 0), object); 12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(Operand(esp, 1 * kPointerSize), Immediate(index)); 12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoBitNotI(LBitNotI* instr) { 1301b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* input = instr->InputAt(0); 1302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(input->Equals(instr->result())); 1303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ not_(ToRegister(input)); 1304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoThrow(LThrow* instr) { 13083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ push(ToOperand(instr->value())); 13093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(ToRegister(instr->context()).is(esi)); 13103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallRuntime(Runtime::kThrow, 1, instr); 1311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_debug_code) { 1313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Comment("Unreachable code."); 1314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ int3(); 1315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoAddI(LAddI* instr) { 1320b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* left = instr->InputAt(0); 1321b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* right = instr->InputAt(1); 1322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(left->Equals(instr->result())); 1323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (right->IsConstantOperand()) { 13253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ToOperand(left), ToInteger32Immediate(right)); 1326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(ToRegister(left), ToOperand(right)); 1328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(overflow, instr->environment()); 1332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoArithmeticD(LArithmeticD* instr) { 1337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister left = ToDoubleRegister(instr->InputAt(0)); 1338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister right = ToDoubleRegister(instr->InputAt(1)); 1339e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch XMMRegister result = ToDoubleRegister(instr->result()); 1340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Modulo uses a fixed result register. 1341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(instr->op() == Token::MOD || left.is(result)); 1342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (instr->op()) { 1343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::ADD: 1344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ addsd(left, right); 1345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SUB: 1347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ subsd(left, right); 1348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::MUL: 1350e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mulsd(left, right); 1351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::DIV: 1353e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ divsd(left, right); 1354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::MOD: { 1356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Pass two doubles as arguments on the stack. 1357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ PrepareCallCFunction(4, eax); 1358e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movdbl(Operand(esp, 0 * kDoubleSize), left); 1359e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movdbl(Operand(esp, 1 * kDoubleSize), right); 136044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CallCFunction( 136144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::double_fp_operation(Token::MOD, isolate()), 136244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4); 1363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Return value is in st(0) on ia32. 1365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Store it into the (fixed) result register. 1366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ sub(Operand(esp), Immediate(kDoubleSize)); 1367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ fstp_d(Operand(esp, 0)); 1368e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movdbl(result, Operand(esp, 0)); 1369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(Operand(esp), Immediate(kDoubleSize)); 1370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 1373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 1374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoArithmeticT(LArithmeticT* instr) { 13803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(ToRegister(instr->context()).is(esi)); 13813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(ToRegister(instr->left()).is(edx)); 13823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(ToRegister(instr->right()).is(eax)); 1383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->result()).is(eax)); 1384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch BinaryOpStub stub(instr->op(), NO_OVERWRITE); 13863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 138718a6f57610d404676fb0db2114fd7ad91e0402b0Ben Murdoch __ nop(); // Signals no inlined code. 1388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint LCodeGen::GetNextEmittedBlock(int block) { 1392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = block + 1; i < graph()->blocks()->length(); ++i) { 1393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LLabel* label = chunk_->GetLabel(i); 1394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!label->HasReplacement()) return i; 1395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return -1; 1397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::EmitBranch(int left_block, int right_block, Condition cc) { 1401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int next_block = GetNextEmittedBlock(current_block_); 1402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch right_block = chunk_->LookupDestination(right_block); 1403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch left_block = chunk_->LookupDestination(left_block); 1404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (right_block == left_block) { 1406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EmitGoto(left_block); 1407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (left_block == next_block) { 1408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); 1409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (right_block == next_block) { 1410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(cc, chunk_->GetAssemblyLabel(left_block)); 1411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(cc, chunk_->GetAssemblyLabel(left_block)); 1413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ jmp(chunk_->GetAssemblyLabel(right_block)); 1414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoBranch(LBranch* instr) { 1419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 1420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 14223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Representation r = instr->hydrogen()->value()->representation(); 1423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (r.IsInteger32()) { 1424b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register reg = ToRegister(instr->InputAt(0)); 1425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(reg, Operand(reg)); 1426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EmitBranch(true_block, false_block, not_zero); 1427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (r.IsDouble()) { 1428b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); 1429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(xmm0, xmm0); 1430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ucomisd(reg, xmm0); 1431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EmitBranch(true_block, false_block, not_equal); 1432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(r.IsTagged()); 1434b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register reg = ToRegister(instr->InputAt(0)); 143569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HType type = instr->hydrogen()->value()->type(); 143669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (type.IsBoolean()) { 143744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(reg, factory()->true_value()); 1438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EmitBranch(true_block, false_block, equal); 143969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (type.IsSmi()) { 144069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ test(reg, Operand(reg)); 144169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch EmitBranch(true_block, false_block, not_equal); 1442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* true_label = chunk_->GetAssemblyLabel(true_block); 1444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* false_label = chunk_->GetAssemblyLabel(false_block); 1445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 144669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); 144769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Avoid deopts in the case where we've never executed this path before. 144869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); 144969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 145069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::UNDEFINED)) { 145169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // undefined -> false. 145269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(reg, factory()->undefined_value()); 145369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, false_label); 145469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 145569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::BOOLEAN)) { 145669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // true -> true. 145769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(reg, factory()->true_value()); 145869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, true_label); 145969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // false -> false. 146069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(reg, factory()->false_value()); 146169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, false_label); 146269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 146369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::NULL_TYPE)) { 146469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // 'null' -> false. 146569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(reg, factory()->null_value()); 146669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, false_label); 146769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 146869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 146969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::SMI)) { 147069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Smis: 0 -> false, all other -> true. 147169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ test(reg, Operand(reg)); 147269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, false_label); 147369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ JumpIfSmi(reg, true_label); 147469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (expected.NeedsMap()) { 147569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // If we need a map later and have a Smi -> deopt. 147669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ test(reg, Immediate(kSmiTagMask)); 147769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(zero, instr->environment()); 147869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 147969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 148069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register map = no_reg; // Keep the compiler happy. 148169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.NeedsMap()) { 148269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch map = ToRegister(instr->TempAt(0)); 148369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ASSERT(!map.is(reg)); 148469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); 148569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 148669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.CanBeUndetectable()) { 148769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Undetectable -> false. 148869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ test_b(FieldOperand(map, Map::kBitFieldOffset), 148969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 1 << Map::kIsUndetectable); 149069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(not_zero, false_label); 149169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 149269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 149369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 149469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { 149569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // spec object -> true. 149669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); 149769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(above_equal, true_label); 149869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 149969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 150069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::STRING)) { 150169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // String value -> false iff empty. 150269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label not_string; 150369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); 150469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(above_equal, ¬_string, Label::kNear); 150569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); 150669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(not_zero, true_label); 150769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ jmp(false_label); 150869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(¬_string); 150969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 151069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 151169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { 151269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // heap number -> false iff +0, -0, or NaN. 151369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label not_heap_number; 151469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 151569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch factory()->heap_number_map()); 151669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(not_equal, ¬_heap_number, Label::kNear); 151769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fldz(); 151869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); 151969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ FCmp(); 152069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(zero, false_label); 152169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ jmp(true_label); 152269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(¬_heap_number); 152369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 152469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 152569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // We've seen something for the first time -> deopt. 152669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(no_condition, instr->environment()); 1527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 15323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::EmitGoto(int block) { 1533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block = chunk_->LookupDestination(block); 1534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int next_block = GetNextEmittedBlock(current_block_); 1535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block != next_block) { 15363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(chunk_->GetAssemblyLabel(block)); 1537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoGoto(LGoto* instr) { 15423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitGoto(instr->block_id()); 1543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochCondition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { 1547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Condition cond = no_condition; 1548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (op) { 1549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::EQ: 1550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::EQ_STRICT: 1551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cond = equal; 1552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::LT: 1554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cond = is_unsigned ? below : less; 1555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::GT: 1557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cond = is_unsigned ? above : greater; 1558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::LTE: 1560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cond = is_unsigned ? below_equal : less_equal; 1561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::GTE: 1563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cond = is_unsigned ? above_equal : greater_equal; 1564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::IN: 1566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::INSTANCEOF: 1567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 1568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 1569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return cond; 1571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 1575b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* left = instr->InputAt(0); 1576b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* right = instr->InputAt(1); 1577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cc = TokenToCondition(instr->op(), instr->is_double()); 1580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (left->IsConstantOperand() && right->IsConstantOperand()) { 15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We can statically evaluate the comparison. 15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch double left_val = ToDouble(LConstantOperand::cast(left)); 15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch double right_val = ToDouble(LConstantOperand::cast(right)); 15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int next_block = 15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EvalComparison(instr->op(), left_val, right_val) ? true_block 15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : false_block; 15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitGoto(next_block); 1589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->is_double()) { 15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Don't base result on EFLAGS when a NaN is involved. Instead 15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // jump to the false block. 15933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); 15943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); 15953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (right->IsConstantOperand()) { 15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ToRegister(left), ToInteger32Immediate(right)); 15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (left->IsConstantOperand()) { 15993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ToOperand(right), ToInteger32Immediate(left)); 16003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We transposed the operands. Reverse the condition. 16013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cc = ReverseCondition(cc); 16023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 16033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ToRegister(left), ToOperand(right)); 16043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitBranch(true_block, false_block, cc); 1607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 16113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { 1612b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register left = ToRegister(instr->InputAt(0)); 16133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand right = ToOperand(instr->InputAt(1)); 1614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 1616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(left, Operand(right)); 1618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EmitBranch(true_block, false_block, equal); 1619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 16223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { 1623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register left = ToRegister(instr->InputAt(0)); 1624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 16253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 16273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(left, instr->hydrogen()->right()); 1628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitBranch(true_block, false_block, equal); 1629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 16323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { 1633b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register reg = ToRegister(instr->InputAt(0)); 16343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 16363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the expression is known to be untagged or a smi, then it's definitely 16373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // not null, and it can't be a an undetectable object. 16383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->representation().IsSpecialization() || 16393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->hydrogen()->type().IsSmi()) { 16403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitGoto(false_block); 16413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return; 16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 16453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> nil_value = instr->nil() == kNullValue ? 16463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch factory()->null_value() : 16473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch factory()->undefined_value(); 16483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(reg, nil_value); 16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->kind() == kStrictEquality) { 1650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EmitBranch(true_block, false_block, equal); 1651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 16523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> other_nil_value = instr->nil() == kNullValue ? 16533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch factory()->undefined_value() : 16543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch factory()->null_value(); 1655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* true_label = chunk_->GetAssemblyLabel(true_block); 1656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* false_label = chunk_->GetAssemblyLabel(false_block); 1657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(equal, true_label); 16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(reg, other_nil_value); 1659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(equal, true_label); 16603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(reg, false_label); 1661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check for undetectable objects by looking in the bit field in 1662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the map. The object has already been smi checked. 1663b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register scratch = ToRegister(instr->TempAt(0)); 1664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 1665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); 1666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(scratch, Immediate(1 << Map::kIsUndetectable)); 1667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EmitBranch(true_block, false_block, not_zero); 1668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochCondition LCodeGen::EmitIsObject(Register input, 1673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register temp1, 1674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* is_not_object, 1675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* is_object) { 16763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(input, is_not_object); 1677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 167844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(input, isolate()->factory()->null_value()); 1679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(equal, is_object); 1680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset)); 1682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Undetectable objects behave like undefined. 16833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ test_b(FieldOperand(temp1, Map::kBitFieldOffset), 16843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1 << Map::kIsUndetectable); 1685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(not_zero, is_not_object); 1686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 16873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movzx_b(temp1, FieldOperand(temp1, Map::kInstanceTypeOffset)); 16883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(temp1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); 1689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(below, is_not_object); 16903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 1691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return below_equal; 1692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { 1696b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register reg = ToRegister(instr->InputAt(0)); 1697b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register temp = ToRegister(instr->TempAt(0)); 1698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 1700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* true_label = chunk_->GetAssemblyLabel(true_block); 1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* false_label = chunk_->GetAssemblyLabel(false_block); 1703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 17043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Condition true_cond = EmitIsObject(reg, temp, false_label, true_label); 1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EmitBranch(true_block, false_block, true_cond); 1707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 17103ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochCondition LCodeGen::EmitIsString(Register input, 17113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register temp1, 17123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* is_not_string) { 17133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(input, is_not_string); 17143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition cond = masm_->IsObjectStringType(input, temp1, temp1); 17163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cond; 17183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 17193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { 17223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = ToRegister(instr->InputAt(0)); 17233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register temp = ToRegister(instr->TempAt(0)); 17243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 17263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 17273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* false_label = chunk_->GetAssemblyLabel(false_block); 17283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition true_cond = EmitIsString(reg, temp, false_label); 17303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitBranch(true_block, false_block, true_cond); 17323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 17333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 1736b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Operand input = ToOperand(instr->InputAt(0)); 1737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 1739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(input, Immediate(kSmiTagMask)); 1742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EmitBranch(true_block, false_block, zero); 1743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { 1747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register input = ToRegister(instr->InputAt(0)); 1748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register temp = ToRegister(instr->TempAt(0)); 1749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 1751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 17543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); 1755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 1756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ test_b(FieldOperand(temp, Map::kBitFieldOffset), 1757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1 << Map::kIsUndetectable); 1758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitBranch(true_block, false_block, not_zero); 1759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 17623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic Condition ComputeCompareCondition(Token::Value op) { 17633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch switch (op) { 17643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case Token::EQ_STRICT: 17653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case Token::EQ: 17663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return equal; 17673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case Token::LT: 17683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return less; 17693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case Token::GT: 17703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return greater; 17713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case Token::LTE: 17723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return less_equal; 17733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case Token::GTE: 17743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return greater_equal; 17753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch default: 17763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 17773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return no_condition; 17783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 17793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 17803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { 17833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Token::Value op = instr->op(); 17843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 17853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 17863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = CompareIC::GetUninitialized(op); 17883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 17893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition condition = ComputeCompareCondition(op); 17913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ test(eax, Operand(eax)); 17923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitBranch(true_block, false_block, condition); 17943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 17953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic InstanceType TestType(HHasInstanceTypeAndBranch* instr) { 1798b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch InstanceType from = instr->from(); 1799b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch InstanceType to = instr->to(); 1800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (from == FIRST_TYPE) return to; 1801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(from == to || to == LAST_TYPE); 1802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return from; 1803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 18063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { 1807b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch InstanceType from = instr->from(); 1808b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch InstanceType to = instr->to(); 1809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (from == to) return equal; 1810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (to == LAST_TYPE) return above_equal; 1811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (from == FIRST_TYPE) return below_equal; 1812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 1813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return equal; 1814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 1818b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register input = ToRegister(instr->InputAt(0)); 1819b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register temp = ToRegister(instr->TempAt(0)); 1820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 1822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* false_label = chunk_->GetAssemblyLabel(false_block); 1825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 18263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(input, false_label); 1827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1828b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ CmpObjectType(input, TestType(instr->hydrogen()), temp); 1829b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); 1830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1833e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { 1834e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register input = ToRegister(instr->InputAt(0)); 1835e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register result = ToRegister(instr->result()); 1836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (FLAG_debug_code) { 1838e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ AbortIfNotString(input); 1839e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1840e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1841e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(result, FieldOperand(input, String::kHashFieldOffset)); 1842e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ IndexFromHash(result, result); 1843e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 1844e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1845e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoHasCachedArrayIndexAndBranch( 1847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LHasCachedArrayIndexAndBranch* instr) { 1848b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register input = ToRegister(instr->InputAt(0)); 1849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 1851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(FieldOperand(input, String::kHashFieldOffset), 1854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Immediate(String::kContainsCachedArrayIndexMask)); 1855e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitBranch(true_block, false_block, equal); 1856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Branches to a label or falls through with the answer in the z flag. Trashes 18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// the temp registers, but not the input. 1861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::EmitClassOfTest(Label* is_true, 1862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* is_false, 1863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String>class_name, 1864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register input, 1865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register temp, 1866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register temp2) { 1867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!input.is(temp)); 18683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!input.is(temp2)); 18693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!temp.is(temp2)); 18703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(input, is_false); 1871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (class_name->IsEqualTo(CStrVector("Function"))) { 18733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assuming the following assertions, we can use the same compares to test 18743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for both being a function type and being in the object type range. 18753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 18763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == 18773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FIRST_SPEC_OBJECT_TYPE + 1); 18783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == 18793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LAST_SPEC_OBJECT_TYPE - 1); 18803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 18813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp); 18823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(below, is_false); 18833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, is_true); 18843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE); 18853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, is_true); 1886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 18873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Faster code path to avoid two compares: subtract lower bound from the 18883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // actual type and do a signed compare with the width of the type range. 18893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 18903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movzx_b(temp2, FieldOperand(temp, Map::kInstanceTypeOffset)); 18913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(Operand(temp2), Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 18923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(Operand(temp2), Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - 18933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 18943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above, is_false); 1895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 18973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. 1898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check if the constructor in the map is a function. 1899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(temp, FieldOperand(temp, Map::kConstructorOffset)); 1900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Objects with a non-function constructor have class 'Object'. 1901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CmpObjectType(temp, JS_FUNCTION_TYPE, temp2); 1902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (class_name->IsEqualTo(CStrVector("Object"))) { 1903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(not_equal, is_true); 1904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(not_equal, is_false); 1906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // temp now contains the constructor function. Grab the 1909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // instance class name from there. 1910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset)); 1911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(temp, FieldOperand(temp, 1912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SharedFunctionInfo::kInstanceClassNameOffset)); 1913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The class name we are testing against is a symbol because it's a literal. 1914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The name in the constructor is a symbol because of the way the context is 1915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // booted. This routine isn't expected to work for random API-created 1916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // classes and it doesn't have to because you can't access it with natives 1917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // syntax. Since both sides are symbols it is sufficient to use an identity 1918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // comparison. 1919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(temp, class_name); 1920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // End with the answer in the z flag. 1921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 1925b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register input = ToRegister(instr->InputAt(0)); 1926b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register temp = ToRegister(instr->TempAt(0)); 1927b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register temp2 = ToRegister(instr->TempAt(1)); 19283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> class_name = instr->hydrogen()->class_name(); 1930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 1932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 1933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* true_label = chunk_->GetAssemblyLabel(true_block); 1935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* false_label = chunk_->GetAssemblyLabel(false_block); 1936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); 1938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EmitBranch(true_block, false_block, equal); 1940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { 1944b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register reg = ToRegister(instr->InputAt(0)); 1945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int true_block = instr->true_block_id(); 1946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int false_block = instr->false_block_id(); 1947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); 1949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EmitBranch(true_block, false_block, equal); 1950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoInstanceOf(LInstanceOf* instr) { 1954086aeeaae12517475c22695a200be45495516549Ben Murdoch // Object and function are in fixed registers defined by the stub. 19551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->context()).is(esi)); 1956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InstanceofStub stub(InstanceofStub::kArgsInRegisters); 19573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 1958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label true_value, done; 1960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(eax, Operand(eax)); 1961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &true_value, Label::kNear); 196244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(ToRegister(instr->result()), factory()->false_value()); 1963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 1964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&true_value); 196544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(ToRegister(instr->result()), factory()->true_value()); 1966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&done); 1967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1970086aeeaae12517475c22695a200be45495516549Ben Murdochvoid LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 1971086aeeaae12517475c22695a200be45495516549Ben Murdoch class DeferredInstanceOfKnownGlobal: public LDeferredCode { 1972086aeeaae12517475c22695a200be45495516549Ben Murdoch public: 1973086aeeaae12517475c22695a200be45495516549Ben Murdoch DeferredInstanceOfKnownGlobal(LCodeGen* codegen, 1974086aeeaae12517475c22695a200be45495516549Ben Murdoch LInstanceOfKnownGlobal* instr) 1975086aeeaae12517475c22695a200be45495516549Ben Murdoch : LDeferredCode(codegen), instr_(instr) { } 1976086aeeaae12517475c22695a200be45495516549Ben Murdoch virtual void Generate() { 19772b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); 1978086aeeaae12517475c22695a200be45495516549Ben Murdoch } 19793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 1980086aeeaae12517475c22695a200be45495516549Ben Murdoch Label* map_check() { return &map_check_; } 1981086aeeaae12517475c22695a200be45495516549Ben Murdoch private: 1982086aeeaae12517475c22695a200be45495516549Ben Murdoch LInstanceOfKnownGlobal* instr_; 1983086aeeaae12517475c22695a200be45495516549Ben Murdoch Label map_check_; 1984086aeeaae12517475c22695a200be45495516549Ben Murdoch }; 1985086aeeaae12517475c22695a200be45495516549Ben Murdoch 1986086aeeaae12517475c22695a200be45495516549Ben Murdoch DeferredInstanceOfKnownGlobal* deferred; 1987086aeeaae12517475c22695a200be45495516549Ben Murdoch deferred = new DeferredInstanceOfKnownGlobal(this, instr); 1988086aeeaae12517475c22695a200be45495516549Ben Murdoch 1989086aeeaae12517475c22695a200be45495516549Ben Murdoch Label done, false_result; 19903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register object = ToRegister(instr->InputAt(1)); 1991b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register temp = ToRegister(instr->TempAt(0)); 1992086aeeaae12517475c22695a200be45495516549Ben Murdoch 1993e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // A Smi is not an instance of anything. 19943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(object, &false_result); 1995086aeeaae12517475c22695a200be45495516549Ben Murdoch 1996e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This is the inlined call site instanceof cache. The two occurences of the 1997086aeeaae12517475c22695a200be45495516549Ben Murdoch // hole value will be patched to the last map/result pair generated by the 1998086aeeaae12517475c22695a200be45495516549Ben Murdoch // instanceof stub. 1999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label cache_miss; 2000b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register map = ToRegister(instr->TempAt(0)); 2001086aeeaae12517475c22695a200be45495516549Ben Murdoch __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); 2002086aeeaae12517475c22695a200be45495516549Ben Murdoch __ bind(deferred->map_check()); // Label for calculating code patching. 20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cache_cell = 20043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); 20053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(map, Operand::Cell(cache_cell)); // Patched to cached map. 2006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &cache_miss, Label::kNear); 200744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. 2008086aeeaae12517475c22695a200be45495516549Ben Murdoch __ jmp(&done); 2009086aeeaae12517475c22695a200be45495516549Ben Murdoch 2010e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The inlined call site cache did not match. Check for null and string 2011e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // before calling the deferred code. 2012086aeeaae12517475c22695a200be45495516549Ben Murdoch __ bind(&cache_miss); 2013e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Null is not an instance of anything. 201444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(object, factory()->null_value()); 2015086aeeaae12517475c22695a200be45495516549Ben Murdoch __ j(equal, &false_result); 2016086aeeaae12517475c22695a200be45495516549Ben Murdoch 2017086aeeaae12517475c22695a200be45495516549Ben Murdoch // String values are not instances of anything. 2018086aeeaae12517475c22695a200be45495516549Ben Murdoch Condition is_string = masm_->IsObjectStringType(object, temp, temp); 2019086aeeaae12517475c22695a200be45495516549Ben Murdoch __ j(is_string, &false_result); 2020086aeeaae12517475c22695a200be45495516549Ben Murdoch 2021086aeeaae12517475c22695a200be45495516549Ben Murdoch // Go to the deferred code. 2022086aeeaae12517475c22695a200be45495516549Ben Murdoch __ jmp(deferred->entry()); 2023086aeeaae12517475c22695a200be45495516549Ben Murdoch 2024086aeeaae12517475c22695a200be45495516549Ben Murdoch __ bind(&false_result); 202544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(ToRegister(instr->result()), factory()->false_value()); 2026086aeeaae12517475c22695a200be45495516549Ben Murdoch 2027086aeeaae12517475c22695a200be45495516549Ben Murdoch // Here result has either true or false. Deferred code also produces true or 2028086aeeaae12517475c22695a200be45495516549Ben Murdoch // false object. 2029086aeeaae12517475c22695a200be45495516549Ben Murdoch __ bind(deferred->exit()); 2030086aeeaae12517475c22695a200be45495516549Ben Murdoch __ bind(&done); 2031086aeeaae12517475c22695a200be45495516549Ben Murdoch} 2032086aeeaae12517475c22695a200be45495516549Ben Murdoch 2033086aeeaae12517475c22695a200be45495516549Ben Murdoch 20342b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdochvoid LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, 20352b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Label* map_check) { 20368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 2037086aeeaae12517475c22695a200be45495516549Ben Murdoch 2038086aeeaae12517475c22695a200be45495516549Ben Murdoch InstanceofStub::Flags flags = InstanceofStub::kNoFlags; 2039086aeeaae12517475c22695a200be45495516549Ben Murdoch flags = static_cast<InstanceofStub::Flags>( 2040086aeeaae12517475c22695a200be45495516549Ben Murdoch flags | InstanceofStub::kArgsInRegisters); 2041086aeeaae12517475c22695a200be45495516549Ben Murdoch flags = static_cast<InstanceofStub::Flags>( 2042086aeeaae12517475c22695a200be45495516549Ben Murdoch flags | InstanceofStub::kCallSiteInlineCheck); 2043086aeeaae12517475c22695a200be45495516549Ben Murdoch flags = static_cast<InstanceofStub::Flags>( 2044086aeeaae12517475c22695a200be45495516549Ben Murdoch flags | InstanceofStub::kReturnTrueFalseObject); 2045086aeeaae12517475c22695a200be45495516549Ben Murdoch InstanceofStub stub(flags); 2046086aeeaae12517475c22695a200be45495516549Ben Murdoch 20478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Get the temp register reserved by the instruction. This needs to be a 20488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // register which is pushed last by PushSafepointRegisters as top of the 20498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // stack is used to pass the offset to the location of the map check to 20508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // the stub. 2051b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register temp = ToRegister(instr->TempAt(0)); 20528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0); 20533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(InstanceofStub::right(), instr->function()); 20543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static const int kAdditionalDelta = 13; 2055086aeeaae12517475c22695a200be45495516549Ben Murdoch int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; 2056086aeeaae12517475c22695a200be45495516549Ben Murdoch __ mov(temp, Immediate(delta)); 2057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ StoreToSafepointRegisterSlot(temp, temp); 20588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CallCodeGeneric(stub.GetCode(), 20598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::CODE_TARGET, 20608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr, 20618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); 20622b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(instr->HasDeoptimizationEnvironment()); 20632b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch LEnvironment* env = instr->deoptimization_environment(); 20642b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 20652b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch 2066086aeeaae12517475c22695a200be45495516549Ben Murdoch // Put the result value into the eax slot and restore all registers. 2067e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ StoreToSafepointRegisterSlot(eax, eax); 2068086aeeaae12517475c22695a200be45495516549Ben Murdoch} 2069086aeeaae12517475c22695a200be45495516549Ben Murdoch 2070086aeeaae12517475c22695a200be45495516549Ben Murdoch 2071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCmpT(LCmpT* instr) { 2072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Token::Value op = instr->op(); 2073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Code> ic = CompareIC::GetUninitialized(op); 20753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 2076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Condition condition = ComputeCompareCondition(op); 2078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label true_value, done; 2079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(eax, Operand(eax)); 2080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(condition, &true_value, Label::kNear); 208144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(ToRegister(instr->result()), factory()->false_value()); 2082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 2083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&true_value); 208444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(ToRegister(instr->result()), factory()->true_value()); 2085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&done); 2086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoReturn(LReturn* instr) { 2090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace) { 20911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Preserve the return value on the stack and rely on the runtime call 20921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to return the value in the same register. We're leaving the code 20931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // managed by the register allocator and tearing down the frame, it's 20941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // safe to write to the context register. 2095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(eax); 20961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CallRuntime(Runtime::kTraceExit, 1); 2098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(esp, ebp); 2100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(ebp); 2101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret((GetParameterCount() + 1) * kPointerSize, ecx); 2102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 21058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { 2106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register result = ToRegister(instr->result()); 2107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result, Operand::Cell(instr->hydrogen()->cell())); 21083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 210944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(result, factory()->the_hole_value()); 2110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(equal, instr->environment()); 2111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 21158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { 21168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(ToRegister(instr->context()).is(esi)); 21178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(ToRegister(instr->global_object()).is(eax)); 21188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(ToRegister(instr->result()).is(eax)); 21198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 21208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ mov(ecx, instr->name()); 21218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : 21228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo::CODE_TARGET_CONTEXT; 21238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 21243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(ic, mode, instr); 21258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 21268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 21278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 21288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { 21293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register value = ToRegister(instr->value()); 21303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell_handle = instr->hydrogen()->cell(); 21311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 21321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If the cell we are storing to contains the hole it could have 21331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // been deleted from the property dictionary. In that case, we need 21341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to update the property details in the property dictionary to mark 21351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // it as no longer deleted. We deoptimize in that case. 21363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(Operand::Cell(cell_handle), factory()->the_hole_value()); 21381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(equal, instr->environment()); 21391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 21401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 21411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Store the value. 21423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(Operand::Cell(cell_handle), value); 21433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Cells are always rescanned, so no write barrier here. 2144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 21478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { 21488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(ToRegister(instr->context()).is(esi)); 21498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(ToRegister(instr->global_object()).is(edx)); 21508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(ToRegister(instr->value()).is(eax)); 21518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 21528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ mov(ecx, instr->name()); 21533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) 21548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ? isolate()->builtins()->StoreIC_Initialize_Strict() 21558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : isolate()->builtins()->StoreIC_Initialize(); 21563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); 21578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 21588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 21598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2160b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 21611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register context = ToRegister(instr->context()); 2162b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register result = ToRegister(instr->result()); 21631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(result, ContextOperand(context, instr->slot_index())); 21643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 21663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(result, factory()->the_hole_value()); 21673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->DeoptimizesOnHole()) { 21683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(equal, instr->environment()); 21693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label is_not_hole; 21713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &is_not_hole, Label::kNear); 21723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(result, factory()->undefined_value()); 21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&is_not_hole); 21743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 21753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 21761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 21771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 21781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 21791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 21801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register context = ToRegister(instr->context()); 21811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register value = ToRegister(instr->value()); 21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label skip_assignment; 21843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand target = ContextOperand(context, instr->slot_index()); 21863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 21873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(target, factory()->the_hole_value()); 21883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->DeoptimizesOnHole()) { 21893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(equal, instr->environment()); 21903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 21913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &skip_assignment, Label::kNear); 21923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 21933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 21943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(target, value); 21963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->NeedsWriteBarrier()) { 21973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HType type = instr->hydrogen()->value()->type(); 21983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck check_needed = 21993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 22001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register temp = ToRegister(instr->TempAt(0)); 22011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offset = Context::SlotOffset(instr->slot_index()); 22023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot(context, 22033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 22043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 22053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch temp, 22063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kSaveFPRegs, 22073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 22083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch check_needed); 22091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 22103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&skip_assignment); 2212b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch} 2213b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2214b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 2215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 221644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register object = ToRegister(instr->object()); 2217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register result = ToRegister(instr->result()); 2218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->hydrogen()->is_in_object()) { 2219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result, FieldOperand(object, instr->hydrogen()->offset())); 2220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); 2222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result, FieldOperand(result, instr->hydrogen()->offset())); 2223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::EmitLoadFieldOrConstantFunction(Register result, 2228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register object, 2229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Map> type, 2230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<String> name) { 22313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 223244f0eee88ff00398ff7f715fab053374d808c90dSteve Block type->LookupInDescriptors(NULL, *name, &lookup); 22333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(lookup.IsFound() && 2234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION)); 2235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (lookup.type() == FIELD) { 2236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int index = lookup.GetLocalFieldIndexFromMap(*type); 2237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int offset = index * kPointerSize; 2238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (index < 0) { 2239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Negative property indices are in-object properties, indexed 2240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // from the end of the fixed part of the object. 2241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(result, FieldOperand(object, offset + type->instance_size())); 2242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Non-negative property indices are in the properties array. 2244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); 2245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(result, FieldOperand(result, offset + FixedArray::kHeaderSize)); 2246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 224744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 2248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type)); 22493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(result, function); 22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 22523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EmitPushTaggedOperand(LOperand* operand) { 22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!operand->IsDoubleRegister()); 22563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (operand->IsConstantOperand()) { 22573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object = ToHandle(LConstantOperand::cast(operand)); 22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (object->IsSmi()) { 22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Handle<Smi>::cast(object)); 22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushHeapObject(Handle<HeapObject>::cast(object)); 22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (operand->IsRegister()) { 22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(ToRegister(operand)); 22653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 22663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(ToOperand(operand)); 226744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 226844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 226944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 227044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 227144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { 227244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register object = ToRegister(instr->object()); 227344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result = ToRegister(instr->result()); 227444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 227544f0eee88ff00398ff7f715fab053374d808c90dSteve Block int map_count = instr->hydrogen()->types()->length(); 227644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<String> name = instr->hydrogen()->name(); 227744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (map_count == 0) { 227844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(instr->hydrogen()->need_generic()); 227944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(ecx, name); 228044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 22813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 228244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 2283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 228444f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < map_count - 1; ++i) { 228544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Map> map = instr->hydrogen()->types()->at(i); 2286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label next; 228744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); 2288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &next, Label::kNear); 2289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitLoadFieldOrConstantFunction(result, object, map, name); 2290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 229144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&next); 229244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 229344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Map> map = instr->hydrogen()->types()->last(); 229444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); 229544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instr->hydrogen()->need_generic()) { 2296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label generic; 2297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &generic, Label::kNear); 2298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitLoadFieldOrConstantFunction(result, object, map, name); 2299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 230044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&generic); 230144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(ecx, name); 230244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 23033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 230444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 230544f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(not_equal, instr->environment()); 2306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitLoadFieldOrConstantFunction(result, object, map, name); 230744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 230844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 230944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 231044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 231144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 231244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { 23141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->context()).is(esi)); 2315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->object()).is(eax)); 2316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->result()).is(eax)); 2317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ecx, instr->name()); 231944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 23203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 2321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 23249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { 23259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register function = ToRegister(instr->function()); 2326b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register temp = ToRegister(instr->TempAt(0)); 23279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register result = ToRegister(instr->result()); 23289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 23299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the function really is a function. 23309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CmpObjectType(function, JS_FUNCTION_TYPE, result); 23319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block DeoptimizeIf(not_equal, instr->environment()); 23329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 23339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check whether the function has an instance prototype. 2334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label non_instance; 23359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ test_b(FieldOperand(result, Map::kBitFieldOffset), 23369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 1 << Map::kHasNonInstancePrototype); 2337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &non_instance, Label::kNear); 23389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 23399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the prototype or initial map from the function. 23409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ mov(result, 23419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 23429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 23439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the function has a prototype or an initial map. 234444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(Operand(result), Immediate(factory()->the_hole_value())); 23459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block DeoptimizeIf(equal, instr->environment()); 23469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 23479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If the function does not have an initial map, we're done. 2348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 23499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CmpObjectType(result, MAP_TYPE, temp); 2350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &done, Label::kNear); 23519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 23529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the prototype from the initial map. 23539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); 2354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 23559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 23569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Non-instance prototype: Fetch prototype from constructor field 23579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // in the function's map. 23589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&non_instance); 23599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ mov(result, FieldOperand(result, Map::kConstructorOffset)); 23609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 23619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // All done. 23629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&done); 23639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 23649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 23659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 2366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoLoadElements(LLoadElements* instr) { 23671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 23681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 23691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(result, FieldOperand(input, JSObject::kElementsOffset)); 2370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_debug_code) { 23713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label done, ok, fail; 23721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(FieldOperand(result, HeapObject::kMapOffset), 237344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory()->fixed_array_map())); 2374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &done, Label::kNear); 23751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(FieldOperand(result, HeapObject::kMapOffset), 237644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Immediate(factory()->fixed_cow_array_map())); 2377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &done, Label::kNear); 237844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register temp((result.is(eax)) ? ebx : eax); 237944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ push(temp); 238044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(temp, FieldOperand(result, HeapObject::kMapOffset)); 23813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movzx_b(temp, FieldOperand(temp, Map::kBitField2Offset)); 23823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ and_(temp, Map::kElementsKindMask); 23833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ shr(temp, Map::kElementsKindShift); 2384589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ cmp(temp, FAST_ELEMENTS); 23853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(equal, &ok, Label::kNear); 2386589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ cmp(temp, FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 23873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(less, &fail, Label::kNear); 2388589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ cmp(temp, LAST_EXTERNAL_ARRAY_ELEMENTS_KIND); 23893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(less_equal, &ok, Label::kNear); 23903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&fail); 23913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Abort("Check for fast or external elements failed."); 23923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&ok); 239344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ pop(temp); 2394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&done); 2395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 239944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoLoadExternalArrayPointer( 240044f0eee88ff00398ff7f715fab053374d808c90dSteve Block LLoadExternalArrayPointer* instr) { 24011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 24021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register input = ToRegister(instr->InputAt(0)); 240344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(result, FieldOperand(input, 240444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalArray::kExternalPointerOffset)); 24051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 24061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 24071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { 2409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register arguments = ToRegister(instr->arguments()); 2410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register length = ToRegister(instr->length()); 2411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Operand index = ToOperand(instr->index()); 2412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register result = ToRegister(instr->result()); 2413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ sub(length, index); 2415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(below_equal, instr->environment()); 2416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2417086aeeaae12517475c22695a200be45495516549Ben Murdoch // There are two words between the frame pointer and the last argument. 2418086aeeaae12517475c22695a200be45495516549Ben Murdoch // Subtracting from length accounts for one of them add one more. 2419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result, Operand(arguments, length, times_4, kPointerSize)); 2420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { 2424b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register result = ToRegister(instr->result()); 2425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Load the result. 242769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(result, 242869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch BuildFastArrayOperand(instr->elements(), instr->key(), 2429589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch FAST_ELEMENTS, 243069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch FixedArray::kHeaderSize - kHeapObjectTag)); 2431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2432b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Check for the hole value. 2433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (instr->hydrogen()->RequiresHoleCheck()) { 2434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(result, factory()->the_hole_value()); 2435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(equal, instr->environment()); 2436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 24403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoLoadKeyedFastDoubleElement( 24413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LLoadKeyedFastDoubleElement* instr) { 24423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch XMMRegister result = ToDoubleRegister(instr->result()); 24433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 24443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + 24453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sizeof(kHoleNanLower32); 24463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand hole_check_operand = BuildFastArrayOperand( 24473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->elements(), instr->key(), 24483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FAST_DOUBLE_ELEMENTS, 24493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset); 24503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); 24513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(equal, instr->environment()); 24523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 24533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand double_load_operand = BuildFastArrayOperand( 2454589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS, 24553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedDoubleArray::kHeaderSize - kHeapObjectTag); 24563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movdbl(result, double_load_operand); 24573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 24583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 24593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 24603fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochOperand LCodeGen::BuildFastArrayOperand( 246169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch LOperand* elements_pointer, 24623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LOperand* key, 2463589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind, 24643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t offset) { 246569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Register elements_pointer_reg = ToRegister(elements_pointer); 24663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int shift_size = ElementsKindToShiftSize(elements_kind); 2467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (key->IsConstantOperand()) { 2468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int constant_value = ToInteger32(LConstantOperand::cast(key)); 2469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (constant_value & 0xF0000000) { 2470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Abort("array index constant value too big"); 2471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 247269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return Operand(elements_pointer_reg, 24733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch constant_value * (1 << shift_size) + offset); 2474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); 247669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return Operand(elements_pointer_reg, ToRegister(key), scale_factor, offset); 2477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 248144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoLoadKeyedSpecializedArrayElement( 248244f0eee88ff00398ff7f715fab053374d808c90dSteve Block LLoadKeyedSpecializedArrayElement* instr) { 2483589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = instr->elements_kind(); 24843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand operand(BuildFastArrayOperand(instr->external_pointer(), 24853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->key(), elements_kind, 0)); 2486589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 248744f0eee88ff00398ff7f715fab053374d808c90dSteve Block XMMRegister result(ToDoubleRegister(instr->result())); 2488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movss(result, operand); 248944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cvtss2sd(result, result); 2490589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 2491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movdbl(ToDoubleRegister(instr->result()), operand); 249244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 249344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result(ToRegister(instr->result())); 24943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 2495589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 2496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsx_b(result, operand); 249744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2498589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 2499589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 2500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movzx_b(result, operand); 250144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2502589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 2503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsx_w(result, operand); 250444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2505589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 2506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movzx_w(result, operand); 250744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2508589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 2509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(result, operand); 251044f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2511589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 2512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(result, operand); 25138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ test(result, Operand(result)); 251444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // TODO(danno): we could be more clever here, perhaps having a special 251544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // version of the stub that detects if the overflow case actually 251644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // happens, and generate code that returns a double rather than int. 25178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch DeoptimizeIf(negative, instr->environment()); 251844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2519589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 2520589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 25213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 2522589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 2523589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 2524589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 2525589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 252644f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 252744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 252844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 252944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 25301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 25311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 25321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { 25341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->context()).is(esi)); 2535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->object()).is(edx)); 2536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->key()).is(eax)); 2537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 253844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 25393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 2540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { 2544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register result = ToRegister(instr->result()); 2545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check for arguments adapter frame. 2547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, adapted; 2548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); 2550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(Operand(result), 2551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &adapted, Label::kNear); 2553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // No arguments adaptor frame. 2555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result, Operand(ebp)); 2556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 2557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Arguments adaptor frame present. 2559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&adapted); 2560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2562086aeeaae12517475c22695a200be45495516549Ben Murdoch // Result is the frame pointer for the frame if not adapted and for the real 2563086aeeaae12517475c22695a200be45495516549Ben Murdoch // frame below the adaptor frame if adapted. 2564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&done); 2565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { 2569b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Operand elem = ToOperand(instr->InputAt(0)); 2570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register result = ToRegister(instr->result()); 2571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 2573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2574086aeeaae12517475c22695a200be45495516549Ben Murdoch // If no arguments adaptor frame the number of arguments is fixed. 2575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(ebp, elem); 2576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result, Immediate(scope()->num_parameters())); 2577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &done, Label::kNear); 2578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Arguments adaptor frame present. Get argument length from there. 2580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result, Operand(result, 2582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ArgumentsAdaptorFrameConstants::kLengthOffset)); 2583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ SmiUntag(result); 2584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2585086aeeaae12517475c22695a200be45495516549Ben Murdoch // Argument length is in result register. 2586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&done); 2587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { 2591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register receiver = ToRegister(instr->receiver()); 25921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register function = ToRegister(instr->function()); 25931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register scratch = ToRegister(instr->TempAt(0)); 2594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 25953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // If the receiver is null or undefined, we have to pass the global 25963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // object as a receiver to normal functions. Values have to be 25973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // passed unchanged to builtins and strict-mode functions. 2598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label global_object, receiver_ok; 25993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 26003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Do not transform the receiver to object for strict mode 26013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // functions. 26023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(scratch, 26033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); 26043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset), 26053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1 << SharedFunctionInfo::kStrictModeBitWithinByte); 26063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(not_equal, &receiver_ok, Label::kNear); 26073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 26083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Do not transform the receiver to object for builtins. 26093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset), 26103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1 << SharedFunctionInfo::kNativeBitWithinByte); 26113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(not_equal, &receiver_ok, Label::kNear); 26123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 26133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Normal function. Replace undefined or null with global receiver. 261444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(receiver, factory()->null_value()); 2615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &global_object, Label::kNear); 261644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(receiver, factory()->undefined_value()); 2617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &global_object, Label::kNear); 2618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 26191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The receiver should be a JS object. 26201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ test(receiver, Immediate(kSmiTagMask)); 26211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(equal, instr->environment()); 26223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); 26231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(below, instr->environment()); 2624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&receiver_ok, Label::kNear); 26251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 26261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&global_object); 26271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // TODO(kmillikin): We have a hydrogen value for the global object. See 26281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // if it's better to use it than to explicitly fetch it from the context 26291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // here. 26301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset)); 26311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); 2632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(receiver, 2633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset)); 26341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&receiver_ok); 26353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 26363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoApplyArguments(LApplyArguments* instr) { 26393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver = ToRegister(instr->receiver()); 26403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register function = ToRegister(instr->function()); 26413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register length = ToRegister(instr->length()); 26423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements = ToRegister(instr->elements()); 26433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(receiver.is(eax)); // Used for parameter count. 26443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(function.is(edi)); // Required by InvokeFunction. 26453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToRegister(instr->result()).is(eax)); 2646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Copy the arguments to this function possibly from the 2648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // adaptor frame below it. 2649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const uint32_t kArgumentsLimit = 1 * KB; 2650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(length, kArgumentsLimit); 2651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(above, instr->environment()); 2652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(receiver); 2654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(receiver, length); 2655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Loop through the arguments pushing them onto the execution 2657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // stack. 2658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label invoke, loop; 2659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // length is a small non-negative integer, due to the test above. 2660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(length, Operand(length)); 2661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &invoke, Label::kNear); 2662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&loop); 2663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); 2664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ dec(length); 2665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(not_zero, &loop); 2666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Invoke the function. 2668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&invoke); 26691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 26701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LPointerMap* pointers = instr->pointer_map(); 26711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RecordPosition(pointers->position()); 26722b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch SafepointGenerator safepoint_generator( 26732b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch this, pointers, Safepoint::kLazyDeopt); 2674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ParameterCount actual(eax); 2675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, actual, CALL_FUNCTION, 2676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch safepoint_generator, CALL_AS_METHOD); 2677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoPushArgument(LPushArgument* instr) { 2681b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* argument = instr->InputAt(0); 26823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitPushTaggedOperand(argument); 2683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 26863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoThisFunction(LThisFunction* instr) { 26873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register result = ToRegister(instr->result()); 26883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(result, instr->hydrogen()->closure()); 26893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 26903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 26913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 26921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::DoContext(LContext* instr) { 26931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 26941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset)); 26951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 26961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 26971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 26981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::DoOuterContext(LOuterContext* instr) { 26991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register context = ToRegister(instr->context()); 27001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 27013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(result, 27023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); 27031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 27041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 27051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 27063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { 27073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToRegister(instr->InputAt(0)).is(esi)); 27083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(esi); // The context is the first argument. 27093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Immediate(instr->hydrogen()->pairs())); 27103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags()))); 27113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntime(Runtime::kDeclareGlobals, 3, instr); 27123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoGlobalObject(LGlobalObject* instr) { 27161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register context = ToRegister(instr->context()); 2717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register result = ToRegister(instr->result()); 27181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(result, Operand(context, Context::SlotOffset(Context::GLOBAL_INDEX))); 2719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { 27231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register global = ToRegister(instr->global()); 2724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register result = ToRegister(instr->result()); 27251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset)); 2726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::CallKnownFunction(Handle<JSFunction> function, 2730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int arity, 2731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LInstruction* instr, 2732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind) { 27333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool can_invoke_directly = !function->NeedsArgumentsAdaption() || 27343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function->shared()->formal_parameter_count() == arity; 2735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LPointerMap* pointers = instr->pointer_map(); 2737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RecordPosition(pointers->position()); 2738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 27393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (can_invoke_directly) { 27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(edi, function); 27413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Change context if needed. 27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool change_context = 27443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (info()->closure()->context() != function->context()) || 27453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scope()->contains_with() || 27463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (scope()->num_heap_slots() > 0); 27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (change_context) { 27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 27503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 27513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 27523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 27533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set eax to arguments count if adaption is not needed. Assumes that eax 27553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // is available to write to at this point. 27563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!function->NeedsArgumentsAdaption()) { 27573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(eax, arity); 27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 27593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke function directly. 27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SetCallKind(ecx, call_kind); 27623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (*function == *info()->closure()) { 27633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallSelf(); 27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset)); 27663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 27673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 2768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 27693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We need to adapt arguments. 27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SafepointGenerator generator( 27713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this, pointers, Safepoint::kLazyDeopt); 27723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ParameterCount count(arity); 27733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind); 2774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { 2779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->result()).is(eax)); 2780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKnownFunction(instr->function(), 2781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->arity(), 2782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr, 2783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CALL_AS_METHOD); 2784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { 27883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register input_reg = ToRegister(instr->value()); 2789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 279044f0eee88ff00398ff7f715fab053374d808c90dSteve Block factory()->heap_number_map()); 2791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 2792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label done; 2794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register tmp = input_reg.is(eax) ? ecx : eax; 2795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; 2796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Preserve the value of all registers. 27988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 2799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label negative; 2801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 28021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check the sign of the argument. If the argument is positive, just 28031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // return it. We do not need to patch the stack since |input| and 28041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // |result| are the same register and |input| will be restored 28051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // unchanged by popping safepoint registers. 2806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(tmp, Immediate(HeapNumber::kSignMask)); 2807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(not_zero, &negative); 2808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ jmp(&done); 2809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&negative); 2811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label allocated, slow; 2813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); 2814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ jmp(&allocated); 2815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Slow case: Call the runtime system to do the number allocation. 2817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&slow); 2818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 28193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, 28203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr, instr->context()); 28218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Set the pointer to the new heap number in tmp. 2823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!tmp.is(eax)) __ mov(tmp, eax); 2824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Restore input_reg after call to runtime. 2826e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadFromSafepointRegisterSlot(input_reg, input_reg); 2827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&allocated); 2829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 2830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ and_(tmp2, ~HeapNumber::kSignMask); 2831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); 2832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); 2833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2); 2834e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ StoreToSafepointRegisterSlot(input_reg, tmp); 2835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 28361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 2837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 28401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { 28413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register input_reg = ToRegister(instr->value()); 28421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ test(input_reg, Operand(input_reg)); 28431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label is_positive; 28441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_sign, &is_positive); 28451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ neg(input_reg); 28461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ test(input_reg, Operand(input_reg)); 28471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizeIf(negative, instr->environment()); 28481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&is_positive); 28491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 28501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 28511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { 2853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Class for deferred case. 2854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { 2855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 2856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, 2857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LUnaryMathOperation* instr) 2858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : LDeferredCode(codegen), instr_(instr) { } 2859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual void Generate() { 2860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); 2861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 28623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 2863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 2864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LUnaryMathOperation* instr_; 2865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch }; 2866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 28673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(instr->value()->Equals(instr->result())); 2868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation r = instr->hydrogen()->value()->representation(); 2869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (r.IsDouble()) { 2871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch XMMRegister scratch = xmm0; 28723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch XMMRegister input_reg = ToDoubleRegister(instr->value()); 2873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(scratch, scratch); 2874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ subsd(scratch, input_reg); 2875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pand(input_reg, scratch); 2876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (r.IsInteger32()) { 28771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitIntegerMathAbs(instr); 2878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { // Tagged case. 2879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeferredMathAbsTaggedHeapNumber* deferred = 2880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new DeferredMathAbsTaggedHeapNumber(this, instr); 28813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register input_reg = ToRegister(instr->value()); 2882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Smi check. 28833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(input_reg, deferred->entry()); 28841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitIntegerMathAbs(instr); 2885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(deferred->exit()); 2886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { 2891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch XMMRegister xmm_scratch = xmm0; 2892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register output_reg = ToRegister(instr->result()); 28933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch XMMRegister input_reg = ToDoubleRegister(instr->value()); 2894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 289569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (CpuFeatures::IsSupported(SSE4_1)) { 289669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch CpuFeatures::Scope scope(SSE4_1); 289769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 289869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Deoptimize on negative zero. 289969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label non_zero; 290069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ xorps(xmm_scratch, xmm_scratch); // Zero the register. 290169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ucomisd(input_reg, xmm_scratch); 290269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(not_equal, &non_zero, Label::kNear); 290369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movmskpd(output_reg, input_reg); 290469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ test(output_reg, Immediate(1)); 290569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(not_zero, instr->environment()); 290669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&non_zero); 290769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 290869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); 290969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cvttsd2si(output_reg, Operand(xmm_scratch)); 291069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Overflow is signalled with minint. 291169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(output_reg, 0x80000000u); 291269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(equal, instr->environment()); 2913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 291469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label done; 291569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Deoptimize on negative numbers. 291669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ xorps(xmm_scratch, xmm_scratch); // Zero the register. 291769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ ucomisd(input_reg, xmm_scratch); 2918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(below, instr->environment()); 2919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 292069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 292169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Check for negative zero. 292269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Label positive_sign; 292369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(above, &positive_sign, Label::kNear); 292469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ movmskpd(output_reg, input_reg); 292569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ test(output_reg, Immediate(1)); 292669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(not_zero, instr->environment()); 292769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Set(output_reg, Immediate(0)); 292869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ jmp(&done, Label::kNear); 292969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&positive_sign); 293069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 2931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 293269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Use truncating instruction (OK because input is positive). 293369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cvttsd2si(output_reg, Operand(input_reg)); 2934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 293569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Overflow is signalled with minint. 293669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(output_reg, 0x80000000u); 293769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(equal, instr->environment()); 293869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&done); 293969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 294069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 2941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoMathRound(LUnaryMathOperation* instr) { 2943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch XMMRegister xmm_scratch = xmm0; 2944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register output_reg = ToRegister(instr->result()); 29453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch XMMRegister input_reg = ToDoubleRegister(instr->value()); 2946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label below_half, done; 2948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // xmm_scratch = 0.5 2949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ExternalReference one_half = ExternalReference::address_of_one_half(); 2950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); 2951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ucomisd(xmm_scratch, input_reg); 2952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above, &below_half); 2953692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch // xmm_scratch = input + 0.5 2954692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ addsd(xmm_scratch, input_reg); 2955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Compute Math.floor(value + 0.5). 2957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Use truncating instruction (OK because input is positive). 2958692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ cvttsd2si(output_reg, Operand(xmm_scratch)); 2959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Overflow is signalled with minint. 2961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(output_reg, 0x80000000u); 2962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(equal, instr->environment()); 2963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done); 2964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&below_half); 2966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if 2968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // we can ignore the difference between a result of -0 and +0. 2969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 2970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the sign is positive, we return +0. 2971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movmskpd(output_reg, input_reg); 2972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ test(output_reg, Immediate(1)); 2973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(not_zero, instr->environment()); 2974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the input is >= -0.5, we return +0. 2976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(output_reg, Immediate(0xBF000000)); 2977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movd(xmm_scratch, Operand(output_reg)); 2978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvtss2sd(xmm_scratch, xmm_scratch); 2979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ucomisd(input_reg, xmm_scratch); 2980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(below, instr->environment()); 2981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Set(output_reg, Immediate(0)); 2983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 2984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { 29883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch XMMRegister input_reg = ToDoubleRegister(instr->value()); 2989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); 2990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ sqrtsd(input_reg, input_reg); 2991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 29943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { 2995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch XMMRegister xmm_scratch = xmm0; 29963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch XMMRegister input_reg = ToDoubleRegister(instr->value()); 29973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = ToRegister(instr->temp()); 2998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); 29993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Note that according to ECMA-262 15.8.2.13: 30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Math.pow(-Infinity, 0.5) == Infinity 30023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Math.sqrt(-Infinity) == NaN 30033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done, sqrt; 30043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check base for -Infinity. According to IEEE-754, single-precision 30053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -Infinity has the highest 9 bits set and the lowest 23 bits cleared. 30063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch, 0xFF800000); 30073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movd(xmm_scratch, scratch); 30083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cvtss2sd(xmm_scratch, xmm_scratch); 30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ucomisd(input_reg, xmm_scratch); 30103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Comparing -Infinity with NaN results in "unordered", which sets the 30113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // zero flag as if both were equal. However, it also sets the carry flag. 30123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &sqrt, Label::kNear); 30133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(carry, &sqrt, Label::kNear); 30143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If input is -Infinity, return Infinity. 30153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xorps(input_reg, input_reg); 30163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ subsd(input_reg, xmm_scratch); 30173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done, Label::kNear); 30183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Square root. 30203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&sqrt); 3021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(xmm_scratch, xmm_scratch); 30221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. 3023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ sqrtsd(input_reg, input_reg); 30243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 3025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoPower(LPower* instr) { 3029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation exponent_type = instr->hydrogen()->right()->representation(); 30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Having marked this as a call, we can use any registers. 30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Just make sure that the input/output registers are the expected ones. 30323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!instr->InputAt(1)->IsDoubleRegister() || 30333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ToDoubleRegister(instr->InputAt(1)).is(xmm1)); 30343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!instr->InputAt(1)->IsRegister() || 30353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ToRegister(instr->InputAt(1)).is(eax)); 30363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToDoubleRegister(instr->InputAt(0)).is(xmm2)); 30373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(xmm3)); 30383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (exponent_type.IsTagged()) { 30403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label no_deopt; 30413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(eax, &no_deopt); 30423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx); 30433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(not_equal, instr->environment()); 30443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&no_deopt); 30453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MathPowStub stub(MathPowStub::TAGGED); 30463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 3047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (exponent_type.IsInteger32()) { 30483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MathPowStub stub(MathPowStub::INTEGER); 30493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 3050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 30513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(exponent_type.IsDouble()); 30523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MathPowStub stub(MathPowStub::DOUBLE); 30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 3054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 30553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3056c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 30573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoRandom(LRandom* instr) { 30593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch class DeferredDoRandom: public LDeferredCode { 30603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public: 30613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeferredDoRandom(LCodeGen* codegen, LRandom* instr) 30623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : LDeferredCode(codegen), instr_(instr) { } 30633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual void Generate() { codegen()->DoDeferredRandom(instr_); } 30643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 30653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 30663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LRandom* instr_; 30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch }; 30683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeferredDoRandom* deferred = new DeferredDoRandom(this, instr); 30703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Having marked this instruction as a call we can use any 30723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // registers. 30733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 30743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToRegister(instr->InputAt(0)).is(eax)); 30753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assert that the register size is indeed the size of each seed. 30763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kSeedSize = sizeof(uint32_t); 30773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kPointerSize == kSeedSize); 30783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(eax, FieldOperand(eax, GlobalObject::kGlobalContextOffset)); 30803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kRandomSeedOffset = 30813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; 30823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, FieldOperand(eax, kRandomSeedOffset)); 30833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ebx: FixedArray of the global context's random seeds 30843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load state[0]. 30863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, FieldOperand(ebx, ByteArray::kHeaderSize)); 30873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If state[0] == 0, call runtime to initialize seeds. 30883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ test(ecx, ecx); 30893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(zero, deferred->entry()); 30903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load state[1]. 30913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(eax, FieldOperand(ebx, ByteArray::kHeaderSize + kSeedSize)); 30923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ecx: state[0] 30933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // eax: state[1] 30943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16) 30963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movzx_w(edx, ecx); 30973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ imul(edx, edx, 18273); 30983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ shr(ecx, 16); 30993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ecx, edx); 31003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save state[0]. 31013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(ebx, ByteArray::kHeaderSize), ecx); 31023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16) 31043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movzx_w(edx, eax); 31053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ imul(edx, edx, 36969); 31063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ shr(eax, 16); 31073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(eax, edx); 31083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save state[1]. 31093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(ebx, ByteArray::kHeaderSize + kSeedSize), eax); 31103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF) 31123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ shl(ecx, 14); 31133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ and_(eax, Immediate(0x3FFFF)); 31143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(eax, ecx); 31153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(deferred->exit()); 31173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Convert 32 random bits in eax to 0.(32 random bits) in a double 31183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // by computing: 31193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 31203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single. 31213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movd(xmm2, ebx); 31223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movd(xmm1, eax); 31233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cvtss2sd(xmm2, xmm2); 31243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xorps(xmm1, xmm2); 31253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ subsd(xmm1, xmm2); 31263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 31273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredRandom(LRandom* instr) { 31303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(1, ebx); 31313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(Operand(esp, 0), eax); 31323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); 31333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Return value is in eax. 31345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 31355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 31365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 3137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoMathLog(LUnaryMathOperation* instr) { 31383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(instr->value()->Equals(instr->result())); 31393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch XMMRegister input_reg = ToDoubleRegister(instr->value()); 3140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label positive, done, zero; 3141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xorps(xmm0, xmm0); 31428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ ucomisd(input_reg, xmm0); 3143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above, &positive, Label::kNear); 3144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &zero, Label::kNear); 31453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ExternalReference nan = 31463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ExternalReference::address_of_canonical_non_hole_nan(); 31478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movdbl(input_reg, Operand::StaticVariable(nan)); 3148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 31498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(&zero); 31508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ push(Immediate(0xFFF00000)); 31518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ push(Immediate(0)); 31528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movdbl(input_reg, Operand(esp, 0)); 31538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ add(Operand(esp), Immediate(kDoubleSize)); 3154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 31558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(&positive); 31568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ fldln2(); 31578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ sub(Operand(esp), Immediate(kDoubleSize)); 31588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movdbl(Operand(esp, 0), input_reg); 31598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ fld_d(Operand(esp, 0)); 31608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ fyl2x(); 31618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ fstp_d(Operand(esp, 0)); 31628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movdbl(input_reg, Operand(esp, 0)); 31638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ add(Operand(esp), Immediate(kDoubleSize)); 31648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(&done); 3165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 31683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoMathTan(LUnaryMathOperation* instr) { 31693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 31703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TranscendentalCacheStub stub(TranscendentalCache::TAN, 31713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TranscendentalCacheStub::UNTAGGED); 31723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 31733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 31743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoMathCos(LUnaryMathOperation* instr) { 3177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 3178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TranscendentalCacheStub stub(TranscendentalCache::COS, 3179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TranscendentalCacheStub::UNTAGGED); 31803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoMathSin(LUnaryMathOperation* instr) { 3185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 3186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TranscendentalCacheStub stub(TranscendentalCache::SIN, 3187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TranscendentalCacheStub::UNTAGGED); 31883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { 3193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (instr->op()) { 3194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathAbs: 3195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoMathAbs(instr); 3196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 3197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathFloor: 3198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoMathFloor(instr); 3199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 3200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathRound: 3201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoMathRound(instr); 3202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 3203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathSqrt: 3204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoMathSqrt(instr); 3205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 3206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathCos: 3207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoMathCos(instr); 3208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 3209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathSin: 3210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoMathSin(instr); 3211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 32123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case kMathTan: 32133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoMathTan(instr); 32143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 3215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathLog: 3216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoMathLog(instr); 3217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 3218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 3220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 3221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { 3226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(ToRegister(instr->context()).is(esi)); 3227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(ToRegister(instr->function()).is(edi)); 3228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->HasPointerMap()); 3229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->HasDeoptimizationEnvironment()); 3230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LPointerMap* pointers = instr->pointer_map(); 3231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RecordPosition(pointers->position()); 32322b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch SafepointGenerator generator( 32332b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch this, pointers, Safepoint::kLazyDeopt); 3234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ParameterCount count(instr->arity()); 3235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(edi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); 3236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCallKeyed(LCallKeyed* instr) { 32401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->context()).is(esi)); 32411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->key()).is(ecx)); 3242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->result()).is(eax)); 3243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int arity = instr->arity(); 3245589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Handle<Code> ic = 3246589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); 32473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 3248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCallNamed(LCallNamed* instr) { 32521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->context()).is(esi)); 3253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->result()).is(eax)); 3254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int arity = instr->arity(); 3256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RelocInfo::Mode mode = RelocInfo::CODE_TARGET; 3257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = 3258589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeCallInitialize(arity, mode); 3259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ecx, instr->name()); 32603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(ic, mode, instr); 3261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCallFunction(LCallFunction* instr) { 32651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->context()).is(esi)); 32663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToRegister(instr->function()).is(edi)); 3267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->result()).is(eax)); 3268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int arity = instr->arity(); 32703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); 32713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCallGlobal(LCallGlobal* instr) { 32761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->context()).is(esi)); 3277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->result()).is(eax)); 3278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int arity = instr->arity(); 3280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; 3281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = 3282589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch isolate()->stub_cache()->ComputeCallInitialize(arity, mode); 3283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ecx, instr->name()); 32843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(ic, mode, instr); 3285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { 3289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->result()).is(eax)); 3290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); 3291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCallNew(LCallNew* instr) { 32951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->context()).is(esi)); 32961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->constructor()).is(edi)); 3297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->result()).is(eax)); 3298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 32993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); 3300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ Set(eax, Immediate(instr->arity())); 33013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); 3302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCallRuntime(LCallRuntime* instr) { 33063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallRuntime(instr->function(), instr->arity(), instr); 3307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { 3311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register object = ToRegister(instr->object()); 3312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register value = ToRegister(instr->value()); 3313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int offset = instr->offset(); 3314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!instr->transition().is_null()) { 3316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); 3317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Do the store. 33203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HType type = instr->hydrogen()->value()->type(); 33213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck check_needed = 33223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 3323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->is_in_object()) { 3324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(FieldOperand(object, offset), value); 33253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->NeedsWriteBarrier()) { 3326b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register temp = ToRegister(instr->TempAt(0)); 3327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Update the write barrier for the object for in-object properties. 33283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(object, 33293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 33303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 33313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch temp, 33323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kSaveFPRegs, 33333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 33343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch check_needed); 3335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3337b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register temp = ToRegister(instr->TempAt(0)); 3338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); 3339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(FieldOperand(temp, offset), value); 33403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->hydrogen()->NeedsWriteBarrier()) { 3341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Update the write barrier for the properties array. 3342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // object is used as a scratch register. 33433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(temp, 33443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 33463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, 33473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kSaveFPRegs, 33483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 33493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch check_needed); 3350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 33561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->context()).is(esi)); 3357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->object()).is(edx)); 3358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->value()).is(eax)); 3359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ecx, instr->name()); 33613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) 336244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? isolate()->builtins()->StoreIC_Initialize_Strict() 336344f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate()->builtins()->StoreIC_Initialize(); 33643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 3365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { 336969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (instr->index()->IsConstantOperand()) { 337069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(ToOperand(instr->length()), 33713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Immediate(ToInteger32(LConstantOperand::cast(instr->index())))); 337269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(below_equal, instr->environment()); 337369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else { 337469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); 337569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DeoptimizeIf(above_equal, instr->environment()); 337669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 3377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 338044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoStoreKeyedSpecializedArrayElement( 338144f0eee88ff00398ff7f715fab053374d808c90dSteve Block LStoreKeyedSpecializedArrayElement* instr) { 3382589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = instr->elements_kind(); 33833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand operand(BuildFastArrayOperand(instr->external_pointer(), 33843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->key(), elements_kind, 0)); 3385589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 338644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value())); 3387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movss(operand, xmm0); 3388589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movdbl(operand, ToDoubleRegister(instr->value())); 339044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 339144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register value = ToRegister(instr->value()); 33923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3393589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3394589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3395589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov_b(operand, value); 339744f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3398589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3399589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov_w(operand, value); 340144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3402589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3403589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(operand, value); 340544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3406589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3407589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 34083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3409589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 3410589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3411589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3412589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 341344f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 341444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 341544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 3416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 3418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3419e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { 3421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register value = ToRegister(instr->value()); 3422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register elements = ToRegister(instr->object()); 3423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; 3424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Do the store. 3426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->key()->IsConstantOperand()) { 3427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); 3428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); 3429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int offset = 3430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; 3431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(FieldOperand(elements, offset), value); 3432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 34331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(FieldOperand(elements, 34341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block key, 34351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block times_pointer_size, 34361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FixedArray::kHeaderSize), 3437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value); 3438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->hydrogen()->NeedsWriteBarrier()) { 34413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HType type = instr->hydrogen()->value()->type(); 34423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SmiCheck check_needed = 34433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 3444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Compute address of modified element and store it into key register. 34451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ lea(key, 34461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FieldOperand(elements, 34471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block key, 34481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block times_pointer_size, 34491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FixedArray::kHeaderSize)); 34503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(elements, 34513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch key, 34523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 34533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kSaveFPRegs, 34543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 34553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch check_needed); 3456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 34603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoStoreKeyedFastDoubleElement( 34613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LStoreKeyedFastDoubleElement* instr) { 34623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch XMMRegister value = ToDoubleRegister(instr->value()); 34633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label have_value; 34643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ucomisd(value, value); 34663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(parity_odd, &have_value); // NaN. 34673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ExternalReference canonical_nan_reference = 34693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ExternalReference::address_of_canonical_non_hole_nan(); 34703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movdbl(value, Operand::StaticVariable(canonical_nan_reference)); 34713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&have_value); 34723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Operand double_store_operand = BuildFastArrayOperand( 3474589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS, 34753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedDoubleArray::kHeaderSize - kHeapObjectTag); 34763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movdbl(double_store_operand, value); 34773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 34783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { 34811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(ToRegister(instr->context()).is(esi)); 3482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->object()).is(edx)); 3483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->key()).is(ecx)); 3484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ToRegister(instr->value()).is(eax)); 3485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 34863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) 348744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 348844f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate()->builtins()->KeyedStoreIC_Initialize(); 34893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(ic, RelocInfo::CODE_TARGET, instr); 3490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 34933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { 34943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object_reg = ToRegister(instr->object()); 34953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register new_map_reg = ToRegister(instr->new_map_reg()); 34963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> from_map = instr->original_map(); 34983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> to_map = instr->transitioned_map(); 34993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind from_kind = from_map->elements_kind(); 35003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind to_kind = to_map->elements_kind(); 35013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 35023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label not_applicable; 35033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); 35043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, ¬_applicable); 35053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(new_map_reg, to_map); 35063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) { 35073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object_reg = ToRegister(instr->object()); 35083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); 35093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Write barrier. 35103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_NE(instr->temp_reg(), NULL); 35113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, 35123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ToRegister(instr->temp_reg()), kDontSaveFPRegs); 35133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (from_kind == FAST_SMI_ONLY_ELEMENTS && 35143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch to_kind == FAST_DOUBLE_ELEMENTS) { 35153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register fixed_object_reg = ToRegister(instr->temp_reg()); 35163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(fixed_object_reg.is(edx)); 35173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(new_map_reg.is(ebx)); 35183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(fixed_object_reg, object_reg); 35193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), 35203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo::CODE_TARGET, instr); 35213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { 35223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register fixed_object_reg = ToRegister(instr->temp_reg()); 35233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(fixed_object_reg.is(edx)); 35243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(new_map_reg.is(ebx)); 35253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(fixed_object_reg, object_reg); 35263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), 35273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RelocInfo::CODE_TARGET, instr); 35283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 35293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 35303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 35313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(¬_applicable); 35323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 35333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 35343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 35351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 35361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block class DeferredStringCharCodeAt: public LDeferredCode { 35371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public: 35381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) 35391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block : LDeferredCode(codegen), instr_(instr) { } 35401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } 35413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 35421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private: 35431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LStringCharCodeAt* instr_; 35441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block }; 35451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeferredStringCharCodeAt* deferred = 35471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block new DeferredStringCharCodeAt(this, instr); 35481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharLoadGenerator::Generate(masm(), 35503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch factory(), 35513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ToRegister(instr->string()), 35523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ToRegister(instr->index()), 35533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ToRegister(instr->result()), 35543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch deferred->entry()); 35551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(deferred->exit()); 35561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 35571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { 35601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register string = ToRegister(instr->string()); 35611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 35621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // TODO(3095996): Get rid of this. For now, we need to make the 35641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // result register contain a valid pointer because it is already 35651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // contained in the register pointer map. 35661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Set(result, Immediate(0)); 35671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 35691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(string); 35701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Push the index as a smi. This is safe because of the checks in 35711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // DoStringCharCodeAt above. 35721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); 35731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->index()->IsConstantOperand()) { 35741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int const_index = ToInteger32(LConstantOperand::cast(instr->index())); 35751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(Immediate(Smi::FromInt(const_index))); 35761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 35771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register index = ToRegister(instr->index()); 35781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiTag(index); 35791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(index); 35801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 35813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, 35823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr, instr->context()); 35831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_debug_code) { 35841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AbortIfNotSmi(eax); 35851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 35861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiUntag(eax); 3587e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ StoreToSafepointRegisterSlot(result, eax); 35881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 35891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 359144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { 359244f0eee88ff00398ff7f715fab053374d808c90dSteve Block class DeferredStringCharFromCode: public LDeferredCode { 359344f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 359444f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) 359544f0eee88ff00398ff7f715fab053374d808c90dSteve Block : LDeferredCode(codegen), instr_(instr) { } 359644f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } 35973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 359844f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 359944f0eee88ff00398ff7f715fab053374d808c90dSteve Block LStringCharFromCode* instr_; 360044f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 360144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 360244f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeferredStringCharFromCode* deferred = 360344f0eee88ff00398ff7f715fab053374d808c90dSteve Block new DeferredStringCharFromCode(this, instr); 360444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 360544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); 360644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register char_code = ToRegister(instr->char_code()); 360744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result = ToRegister(instr->result()); 360844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!char_code.is(result)); 360944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 361044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(char_code, String::kMaxAsciiCharCode); 361144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(above, deferred->entry()); 361244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(result, Immediate(factory()->single_character_string_cache())); 361344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ mov(result, FieldOperand(result, 361444f0eee88ff00398ff7f715fab053374d808c90dSteve Block char_code, times_pointer_size, 361544f0eee88ff00398ff7f715fab053374d808c90dSteve Block FixedArray::kHeaderSize)); 361644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(result, factory()->undefined_value()); 361744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(equal, deferred->entry()); 361844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(deferred->exit()); 361944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 362044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 362144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 362244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { 362344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register char_code = ToRegister(instr->char_code()); 362444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result = ToRegister(instr->result()); 362544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 362644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // TODO(3095996): Get rid of this. For now, we need to make the 362744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // result register contain a valid pointer because it is already 362844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // contained in the register pointer map. 362944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(result, Immediate(0)); 363044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 36318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 363244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiTag(char_code); 363344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ push(char_code); 36343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); 363544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ StoreToSafepointRegisterSlot(result, eax); 363644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 363744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 363844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 36391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::DoStringLength(LStringLength* instr) { 36401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register string = ToRegister(instr->string()); 36411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register result = ToRegister(instr->result()); 36421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(result, FieldOperand(string, String::kLengthOffset)); 36431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 36441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 36451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoStringAdd(LStringAdd* instr) { 36473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitPushTaggedOperand(instr->left()); 36483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitPushTaggedOperand(instr->right()); 3649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringAddStub stub(NO_STRING_CHECK_IN_STUB); 36503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { 3655b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* input = instr->InputAt(0); 3656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(input->IsRegister() || input->IsStackSlot()); 3657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* output = instr->result(); 3658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(output->IsDoubleRegister()); 3659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); 3660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoNumberTagI(LNumberTagI* instr) { 3664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch class DeferredNumberTagI: public LDeferredCode { 3665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 3666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) 3667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : LDeferredCode(codegen), instr_(instr) { } 3668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } 36693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 3670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 3671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LNumberTagI* instr_; 3672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch }; 3673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3674b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* input = instr->InputAt(0); 3675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(input->IsRegister() && input->Equals(instr->result())); 3676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register reg = ToRegister(input); 3677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); 3679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ SmiTag(reg); 3680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(overflow, deferred->entry()); 3681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(deferred->exit()); 3682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { 3686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label slow; 3687b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register reg = ToRegister(instr->InputAt(0)); 3688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register tmp = reg.is(eax) ? ecx : eax; 3689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Preserve the value of all registers. 36918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 3692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There was overflow, so bits 30 and 31 of the original integer 3694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // disagree. Try to allocate a heap number in new space and store 3695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the value in there. If that fails, call the runtime system. 3696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 3697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ SmiUntag(reg); 3698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ xor_(reg, 0x80000000); 3699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cvtsi2sd(xmm0, Operand(reg)); 3700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_inline_new) { 3701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ AllocateHeapNumber(reg, tmp, no_reg, &slow); 3702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 3703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Slow case: Call the runtime system to do the number allocation. 3706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&slow); 3707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(3095996): Put a valid pointer value in the stack slot where the result 3709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // register is stored, as this register is in the pointer map, but contains an 3710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // integer value. 3711e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ StoreToSafepointRegisterSlot(reg, Immediate(0)); 37123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // NumberTagI and NumberTagD use the context from the frame, rather than 37133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // the environment's HContext or HInlinedContext value. 37143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // They only call Runtime::kAllocateHeapNumber. 37153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // The corresponding HChange instructions are added in a phase that does 37163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // not have easy access to the local context. 37173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 37183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 37193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RecordSafepointWithRegisters( 37202b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 3721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!reg.is(eax)) __ mov(reg, eax); 3722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Done. Put the value in xmm0 into the value of the allocated heap 3724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // number. 3725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&done); 3726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0); 3727e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ StoreToSafepointRegisterSlot(reg, reg); 3728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoNumberTagD(LNumberTagD* instr) { 3732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch class DeferredNumberTagD: public LDeferredCode { 3733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 3734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) 3735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : LDeferredCode(codegen), instr_(instr) { } 3736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } 37373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 3738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 3739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LNumberTagD* instr_; 3740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch }; 3741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3742b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 3743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register reg = ToRegister(instr->result()); 3744b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register tmp = ToRegister(instr->TempAt(0)); 3745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); 3747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_inline_new) { 3748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); 3749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ jmp(deferred->entry()); 3751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(deferred->exit()); 3753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); 3754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { 3758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(3095996): Get rid of this. For now, we need to make the 3759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // result register contain a valid pointer because it is already 3760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // contained in the register pointer map. 3761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register reg = ToRegister(instr->result()); 3762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ Set(reg, Immediate(0)); 3763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 37648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushSafepointRegistersScope scope(this); 37653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // NumberTagI and NumberTagD use the context from the frame, rather than 37663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // the environment's HContext or HInlinedContext value. 37673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // They only call Runtime::kAllocateHeapNumber. 37683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // The corresponding HChange instructions are added in a phase that does 37693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // not have easy access to the local context. 37703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 37713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 37722b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepointWithRegisters( 37732b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 3774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ StoreToSafepointRegisterSlot(reg, eax); 3775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoSmiTag(LSmiTag* instr) { 3779b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* input = instr->InputAt(0); 3780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(input->IsRegister() && input->Equals(instr->result())); 3781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); 3782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ SmiTag(ToRegister(input)); 3783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoSmiUntag(LSmiUntag* instr) { 3787b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* input = instr->InputAt(0); 3788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(input->IsRegister() && input->Equals(instr->result())); 3789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->needs_check()) { 3790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(ToRegister(input), Immediate(kSmiTagMask)); 3791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(not_zero, instr->environment()); 3792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ SmiUntag(ToRegister(input)); 3794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::EmitNumberUntagD(Register input_reg, 37983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register temp_reg, 3799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch XMMRegister result_reg, 38007d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch bool deoptimize_on_undefined, 38013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool deoptimize_on_minus_zero, 3802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LEnvironment* env) { 3803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label load_smi, done; 3804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Smi check. 38063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfSmi(input_reg, &load_smi, Label::kNear); 3807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Heap number map check. 3809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 381044f0eee88ff00398ff7f715fab053374d808c90dSteve Block factory()->heap_number_map()); 38117d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch if (deoptimize_on_undefined) { 38127d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch DeoptimizeIf(not_equal, env); 38137d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } else { 3814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label heap_number; 3815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &heap_number, Label::kNear); 3816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 38177d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch __ cmp(input_reg, factory()->undefined_value()); 38187d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch DeoptimizeIf(not_equal, env); 3819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 38207d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch // Convert undefined to NaN. 38213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ExternalReference nan = 38223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ExternalReference::address_of_canonical_non_hole_nan(); 38237d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch __ movdbl(result_reg, Operand::StaticVariable(nan)); 3824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 3825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 38267d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch __ bind(&heap_number); 38277d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } 3828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Heap number to XMM conversion. 3829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); 38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (deoptimize_on_minus_zero) { 38313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch XMMRegister xmm_scratch = xmm0; 38323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xorps(xmm_scratch, xmm_scratch); 38333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ucomisd(result_reg, xmm_scratch); 38343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_zero, &done, Label::kNear); 38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movmskpd(temp_reg, result_reg); 38363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ test_b(temp_reg, 1); 38373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(not_zero, env); 38383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 3840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Smi to XMM conversion 3842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&load_smi); 3843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ SmiUntag(input_reg); // Untag smi before converting to float. 3844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cvtsi2sd(result_reg, Operand(input_reg)); 3845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ SmiTag(input_reg); // Retag smi. 3846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&done); 3847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { 3851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, heap_number; 3852b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register input_reg = ToRegister(instr->InputAt(0)); 3853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Heap number map check. 3855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 385644f0eee88ff00398ff7f715fab053374d808c90dSteve Block factory()->heap_number_map()); 3857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->truncating()) { 3859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &heap_number, Label::kNear); 3860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check for undefined. Undefined is converted to zero for truncating 3861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // conversions. 386244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(input_reg, factory()->undefined_value()); 3863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 3864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(input_reg, 0); 3865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 3866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&heap_number); 38688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(SSE3)) { 3869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CpuFeatures::Scope scope(SSE3); 3870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label convert; 3871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Use more powerful conversion when sse3 is available. 3872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Load x87 register with heap number. 3873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 3874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get exponent alone and check for too-big exponent. 3875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 3876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ and_(input_reg, HeapNumber::kExponentMask); 3877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const uint32_t kTooBigExponent = 3878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; 3879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(Operand(input_reg), Immediate(kTooBigExponent)); 3880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(less, &convert, Label::kNear); 3881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Pop FPU stack before deoptimizing. 38823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ fstp(0); 3883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(no_condition, instr->environment()); 3884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Reserve space for 64 bit answer. 3886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&convert); 3887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ sub(Operand(esp), Immediate(kDoubleSize)); 3888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Do conversion, which cannot fail because we checked the exponent. 3889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ fisttp_d(Operand(esp, 0)); 3890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. 3891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(Operand(esp), Immediate(kDoubleSize)); 3892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3893b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); 3894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 3895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cvttsd2si(input_reg, Operand(xmm0)); 3896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(input_reg, 0x80000000u); 3897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(not_equal, &done); 3898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check if the input was 0x8000000 (kMinInt). 3899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If no, then we got an overflow and we deoptimize. 3900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ExternalReference min_int = ExternalReference::address_of_min_int(); 3901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); 3902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ucomisd(xmm_temp, xmm0); 3903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 3904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(parity_even, instr->environment()); // NaN. 3905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Deoptimize if we don't have a heap number. 3908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 3909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3910b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); 3911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 3912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cvttsd2si(input_reg, Operand(xmm0)); 3913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cvtsi2sd(xmm_temp, Operand(input_reg)); 3914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ucomisd(xmm0, xmm_temp); 3915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 3916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(parity_even, instr->environment()); // NaN. 3917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(input_reg, Operand(input_reg)); 3919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(not_zero, &done); 3920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ movmskpd(input_reg, xmm0); 3921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ and_(input_reg, 1); 3922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(not_zero, instr->environment()); 3923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&done); 3926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoTaggedToI(LTaggedToI* instr) { 39303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch class DeferredTaggedToI: public LDeferredCode { 39313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public: 39323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 39333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : LDeferredCode(codegen), instr_(instr) { } 39343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } 39353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 39363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 39373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LTaggedToI* instr_; 39383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch }; 39393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3940b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* input = instr->InputAt(0); 3941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(input->IsRegister()); 3942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(input->Equals(instr->result())); 3943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register input_reg = ToRegister(input); 3945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); 3947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Smi check. 39493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(input_reg, deferred->entry()); 3950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Smi to int32 conversion 3952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ SmiUntag(input_reg); // Untag smi. 3953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(deferred->exit()); 3955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { 3959b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* input = instr->InputAt(0); 3960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(input->IsRegister()); 39613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LOperand* temp = instr->TempAt(0); 39623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(temp == NULL || temp->IsRegister()); 3963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* result = instr->result(); 3964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(result->IsDoubleRegister()); 3965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register input_reg = ToRegister(input); 3967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch XMMRegister result_reg = ToDoubleRegister(result); 3968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 39693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool deoptimize_on_minus_zero = 39703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->hydrogen()->deoptimize_on_minus_zero(); 39713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register temp_reg = deoptimize_on_minus_zero ? ToRegister(temp) : no_reg; 39723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitNumberUntagD(input_reg, 39743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch temp_reg, 39753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result_reg, 39767d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch instr->hydrogen()->deoptimize_on_undefined(), 39773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch deoptimize_on_minus_zero, 39787d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch instr->environment()); 3979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoDoubleToI(LDoubleToI* instr) { 3983b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* input = instr->InputAt(0); 3984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(input->IsDoubleRegister()); 3985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* result = instr->result(); 3986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(result->IsRegister()); 3987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch XMMRegister input_reg = ToDoubleRegister(input); 3989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register result_reg = ToRegister(result); 3990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->truncating()) { 3992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Performs a truncating conversion of a floating point number as used by 3993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the JS bitwise operations. 3994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cvttsd2si(result_reg, Operand(input_reg)); 3995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(result_reg, 0x80000000u); 39968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (CpuFeatures::IsSupported(SSE3)) { 3997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // This will deoptimize if the exponent of the input in out of range. 3998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CpuFeatures::Scope scope(SSE3); 3999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label convert, done; 4000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &done, Label::kNear); 4001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ sub(Operand(esp), Immediate(kDoubleSize)); 4002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ movdbl(Operand(esp, 0), input_reg); 4003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get exponent alone and check for too-big exponent. 4004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result_reg, Operand(esp, sizeof(int32_t))); 4005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ and_(result_reg, HeapNumber::kExponentMask); 4006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const uint32_t kTooBigExponent = 4007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; 4008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(Operand(result_reg), Immediate(kTooBigExponent)); 4009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(less, &convert, Label::kNear); 4010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(Operand(esp), Immediate(kDoubleSize)); 4011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(no_condition, instr->environment()); 4012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&convert); 4013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Do conversion, which cannot fail because we checked the exponent. 4014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ fld_d(Operand(esp, 0)); 4015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ fisttp_d(Operand(esp, 0)); 4016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. 4017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(Operand(esp), Immediate(kDoubleSize)); 4018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&done); 4019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 4021b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register temp_reg = ToRegister(instr->TempAt(0)); 4022b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch XMMRegister xmm_scratch = xmm0; 4023b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4024b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // If cvttsd2si succeeded, we're done. Otherwise, we attempt 4025b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // manual conversion. 4026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &done, Label::kNear); 4027b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4028b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Get high 32 bits of the input in result_reg and temp_reg. 4029b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ pshufd(xmm_scratch, input_reg, 1); 4030b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ movd(Operand(temp_reg), xmm_scratch); 4031b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ mov(result_reg, temp_reg); 4032b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4033b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Prepare negation mask in temp_reg. 4034b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ sar(temp_reg, kBitsPerInt - 1); 4035b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4036b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Extract the exponent from result_reg and subtract adjusted 4037b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // bias from it. The adjustment is selected in a way such that 4038b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // when the difference is zero, the answer is in the low 32 bits 4039b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // of the input, otherwise a shift has to be performed. 4040b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ shr(result_reg, HeapNumber::kExponentShift); 4041b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ and_(result_reg, 4042b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch HeapNumber::kExponentMask >> HeapNumber::kExponentShift); 4043b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ sub(Operand(result_reg), 4044b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Immediate(HeapNumber::kExponentBias + 4045b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch HeapNumber::kExponentBits + 4046b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch HeapNumber::kMantissaBits)); 4047b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Don't handle big (> kMantissaBits + kExponentBits == 63) or 4048b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // special exponents. 4049b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch DeoptimizeIf(greater, instr->environment()); 4050b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4051b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Zero out the sign and the exponent in the input (by shifting 4052b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // it to the left) and restore the implicit mantissa bit, 4053b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // i.e. convert the input to unsigned int64 shifted left by 4054b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // kExponentBits. 4055b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ExternalReference minus_zero = ExternalReference::address_of_minus_zero(); 4056b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Minus zero has the most significant bit set and the other 4057b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // bits cleared. 4058b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ movdbl(xmm_scratch, Operand::StaticVariable(minus_zero)); 4059b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ psllq(input_reg, HeapNumber::kExponentBits); 4060b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ por(input_reg, xmm_scratch); 4061b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4062b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Get the amount to shift the input right in xmm_scratch. 4063b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ neg(result_reg); 4064b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ movd(xmm_scratch, Operand(result_reg)); 4065b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4066b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Shift the input right and extract low 32 bits. 4067b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ psrlq(input_reg, xmm_scratch); 4068b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ movd(Operand(result_reg), input_reg); 4069b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4070b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Use the prepared mask in temp_reg to negate the result if necessary. 4071b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ xor_(result_reg, Operand(temp_reg)); 4072b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ sub(result_reg, Operand(temp_reg)); 4073b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&done); 4074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 4077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cvttsd2si(result_reg, Operand(input_reg)); 4078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cvtsi2sd(xmm0, Operand(result_reg)); 4079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ucomisd(xmm0, input_reg); 4080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 4081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(parity_even, instr->environment()); // NaN. 4082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 4083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The integer converted back is equal to the original. We 4084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // only have to test if we got -0 as an input. 4085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test(result_reg, Operand(result_reg)); 4086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, &done, Label::kNear); 4087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ movmskpd(result_reg, input_reg); 4088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Bit 0 contains the sign of the double in input_reg. 4089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If input was positive, we are ok and return 0, otherwise 4090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // deoptimize. 4091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ and_(result_reg, 1); 4092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(not_zero, instr->environment()); 4093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&done); 4095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCheckSmi(LCheckSmi* instr) { 4100b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* input = instr->InputAt(0); 41013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ test(ToOperand(input), Immediate(kSmiTagMask)); 410244f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(not_zero, instr->environment()); 410344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 410444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 410544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 410644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 410744f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOperand* input = instr->InputAt(0); 41083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ test(ToOperand(input), Immediate(kSmiTagMask)); 410944f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizeIf(zero, instr->environment()); 4110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 4114b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register input = ToRegister(instr->InputAt(0)); 4115b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register temp = ToRegister(instr->TempAt(0)); 4116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 4118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (instr->hydrogen()->is_interval_check()) { 4120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InstanceType first; 4121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InstanceType last; 4122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->hydrogen()->GetCheckInterval(&first, &last); 4123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 41241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 41251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static_cast<int8_t>(first)); 4126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If there is only one type in the interval check for equality. 4128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (first == last) { 4129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 4130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 4131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(below, instr->environment()); 4132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Omit check for the last type. 4133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (last != LAST_TYPE) { 4134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 4135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static_cast<int8_t>(last)); 4136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(above, instr->environment()); 4137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 4140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint8_t mask; 4141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint8_t tag; 4142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); 4143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (IsPowerOf2(mask)) { 4145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(tag == 0 || IsPowerOf2(tag)); 4146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask); 4147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment()); 4148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 4149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 4150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ and_(temp, mask); 41513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(temp, tag); 4152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 4153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCheckFunction(LCheckFunction* instr) { 41593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> target = instr->hydrogen()->target(); 41603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate()->heap()->InNewSpace(*target)) { 41613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = ToRegister(instr->value()); 41623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 41633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewJSGlobalPropertyCell(target); 41643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(reg, Operand::Cell(cell)); 41653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 41663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand operand = ToOperand(instr->value()); 41673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(operand, target); 41683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 4170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 41733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckMapCommon(Register reg, 41743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map, 41753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompareMapMode mode, 41763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LEnvironment* env) { 41773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label success; 41783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareMap(reg, map, &success, mode); 41793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(not_equal, env); 41803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&success); 41813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 41823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 41833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCheckMap(LCheckMap* instr) { 4185b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch LOperand* input = instr->InputAt(0); 4186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(input->IsRegister()); 4187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register reg = ToRegister(input); 41883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map = instr->hydrogen()->map(); 41893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoCheckMapCommon(reg, map, instr->hydrogen()->mode(), instr->environment()); 4190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 4194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); 4195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result_reg = ToRegister(instr->result()); 4196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ClampDoubleToUint8(value_reg, xmm0, result_reg); 4197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 4198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { 4201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->unclamped()->Equals(instr->result())); 4202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register value_reg = ToRegister(instr->result()); 4203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ClampUint8(value_reg); 4204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 4205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { 4208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->unclamped()->Equals(instr->result())); 4209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register input_reg = ToRegister(instr->unclamped()); 4210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label is_smi, done, heap_number; 4211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(input_reg, &is_smi); 4213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for heap number 4215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 4216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch factory()->heap_number_map()); 4217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &heap_number, Label::kNear); 4218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for undefined. Undefined is converted to zero for clamping 4220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // conversions. 4221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cmp(input_reg, factory()->undefined_value()); 4222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DeoptimizeIf(not_equal, instr->environment()); 4223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(input_reg, 0); 4224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 4225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Heap number 4227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&heap_number); 4228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 4229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ClampDoubleToUint8(xmm0, xmm1, input_reg); 4230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 4231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // smi 4233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&is_smi); 4234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(input_reg); 4235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ClampUint8(input_reg); 4236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 4238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 4239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { 4242b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register reg = ToRegister(instr->TempAt(0)); 4243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSObject> holder = instr->holder(); 4245b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<JSObject> current_prototype = instr->prototype(); 4246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Load prototype object. 42483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(reg, current_prototype); 4249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check prototype maps up to the holder. 4251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!current_prototype.is_identical_to(holder)) { 42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), 42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); 42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_prototype = 4256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); 4257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Load next prototype object. 42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(reg, current_prototype); 4259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check the holder map. 42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), 42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); 42643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoAllocateObject(LAllocateObject* instr) { 42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch class DeferredAllocateObject: public LDeferredCode { 42693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public: 42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr) 42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : LDeferredCode(codegen), instr_(instr) { } 42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } 42733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LAllocateObject* instr_; 42763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch }; 42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeferredAllocateObject* deferred = new DeferredAllocateObject(this, instr); 42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result = ToRegister(instr->result()); 42813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = ToRegister(instr->TempAt(0)); 42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> constructor = instr->hydrogen()->constructor(); 42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> initial_map(constructor->initial_map()); 42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int instance_size = initial_map->instance_size(); 42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(initial_map->pre_allocated_property_fields() + 42863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch initial_map->unused_property_fields() - 42873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch initial_map->inobject_properties() == 0); 42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate memory for the object. The initial map might change when 42903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the constructor's prototype changes, but instance size and property 42913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // counts remain unchanged (if slack tracking finished). 42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress()); 42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(instance_size, 42943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 42953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch no_reg, 42963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch deferred->entry(), 42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TAG_OBJECT); 42993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the initial map. 43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map = scratch; 43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(scratch, constructor); 43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(map, FieldOperand(scratch, JSFunction::kPrototypeOrInitialMapOffset)); 43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AbortIfSmi(map); 43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpb(FieldOperand(map, Map::kInstanceSizeOffset), 43083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instance_size >> kPointerSizeLog2); 43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(equal, "Unexpected instance size"); 43103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpb(FieldOperand(map, Map::kPreAllocatedPropertyFieldsOffset), 43113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch initial_map->pre_allocated_property_fields()); 43123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(equal, "Unexpected pre-allocated property fields count"); 43133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpb(FieldOperand(map, Map::kUnusedPropertyFieldsOffset), 43143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch initial_map->unused_property_fields()); 43153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(equal, "Unexpected unused property fields count"); 43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpb(FieldOperand(map, Map::kInObjectPropertiesOffset), 43173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch initial_map->inobject_properties()); 43183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(equal, "Unexpected in-object property fields count"); 43193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 43203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize map and fields of the newly allocated object. 43223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); 43233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(result, JSObject::kMapOffset), map); 43243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch, factory()->empty_fixed_array()); 43253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(result, JSObject::kElementsOffset), scratch); 43263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(result, JSObject::kPropertiesOffset), scratch); 43273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (initial_map->inobject_properties() != 0) { 43283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(scratch, factory()->undefined_value()); 43293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < initial_map->inobject_properties(); i++) { 43303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int property_offset = JSObject::kHeaderSize + i * kPointerSize; 43313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(result, property_offset), scratch); 43323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 43333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 43343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(deferred->exit()); 43363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 43373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) { 43403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result = ToRegister(instr->result()); 43413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> constructor = instr->hydrogen()->constructor(); 43423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // TODO(3095996): Get rid of this. For now, we need to make the 43443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // result register contain a valid pointer because it is already 43453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // contained in the register pointer map. 43463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Set(result, Immediate(0)); 43473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PushSafepointRegistersScope scope(this); 43493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushHeapObject(constructor); 43503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntimeFromDeferred(Runtime::kNewObject, 1, instr, instr->context()); 43513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ StoreToSafepointRegisterSlot(result, eax); 43525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 43535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 43545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 4355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { 43563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(ToRegister(instr->context()).is(esi)); 43573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap* heap = isolate()->heap(); 43583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind boilerplate_elements_kind = 43593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->hydrogen()->boilerplate_elements_kind(); 43603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Deopt if the array literal boilerplate ElementsKind is of a type different 43623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // than the expected one. The check isn't necessary if the boilerplate has 43633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // already been converted to FAST_ELEMENTS. 43643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (boilerplate_elements_kind != FAST_ELEMENTS) { 43653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(eax, instr->hydrogen()->boilerplate_object()); 43663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 43673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the map's "bit field 2". We only need the first byte, 43683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // but the following masking takes care of that anyway. 43693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, FieldOperand(ebx, Map::kBitField2Offset)); 43703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Retrieve elements_kind from bit field 2. 43713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ and_(ebx, Map::kElementsKindMask); 43723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ebx, boilerplate_elements_kind << Map::kElementsKindShift); 43733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(not_equal, instr->environment()); 43743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 43753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the parameters to the stub/runtime call. 4377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 4378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); 4379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); 43803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Boilerplate already exists, constant elements are never accessed. 43813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Pass an empty fixed array. 43823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Immediate(Handle<FixedArray>(heap->empty_fixed_array()))); 4383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Pick the right runtime function or stub to call. 4385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = instr->hydrogen()->length(); 4386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->hydrogen()->IsCopyOnWrite()) { 4387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(instr->hydrogen()->depth() == 1); 4388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FastCloneShallowArrayStub::Mode mode = 4389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; 4390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FastCloneShallowArrayStub stub(mode, length); 43913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (instr->hydrogen()->depth() > 1) { 43933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallRuntime(Runtime::kCreateArrayLiteral, 3, instr); 4394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 43953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr); 4396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FastCloneShallowArrayStub::Mode mode = 43983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch boilerplate_elements_kind == FAST_DOUBLE_ELEMENTS 43993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS 44003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : FastCloneShallowArrayStub::CLONE_ELEMENTS; 4401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FastCloneShallowArrayStub stub(mode, length); 44023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 44073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::EmitDeepCopy(Handle<JSObject> object, 44083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result, 44093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register source, 44103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int* offset) { 44113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!source.is(ecx)); 44123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!result.is(ecx)); 44133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 44153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(ecx, object); 44163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(source, ecx); 44173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Assert(equal, "Unexpected object literal boilerplate"); 44183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 44193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Only elements backing stores for non-COW arrays need to be copied. 44213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArrayBase> elements(object->elements()); 44223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool has_elements = elements->length() > 0 && 44233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements->map() != isolate()->heap()->fixed_cow_array_map(); 44243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increase the offset so that subsequent objects end up right after 44263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // this object and its backing store. 44273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int object_offset = *offset; 44283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int object_size = object->map()->instance_size(); 44293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int elements_offset = *offset + object_size; 44303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int elements_size = has_elements ? elements->Size() : 0; 44313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *offset += object_size + elements_size; 44323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy object header. 44343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(object->properties()->length() == 0); 44353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int inobject_properties = object->map()->inobject_properties(); 44363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int header_size = object_size - inobject_properties * kPointerSize; 44373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < header_size; i += kPointerSize) { 44383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (has_elements && i == JSObject::kElementsOffset) { 44393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(ecx, Operand(result, elements_offset)); 44403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 44413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, FieldOperand(source, i)); 44423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 44433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(result, object_offset + i), ecx); 44443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 44453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy in-object properties. 44473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < inobject_properties; i++) { 44483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int total_offset = object_offset + object->GetInObjectPropertyOffset(i); 44493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> value = Handle<Object>(object->InObjectPropertyAt(i)); 44503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (value->IsJSObject()) { 44513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> value_object = Handle<JSObject>::cast(value); 44523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(ecx, Operand(result, *offset)); 44533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(result, total_offset), ecx); 44543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(source, value_object); 44553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitDeepCopy(value_object, result, source, offset); 44563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (value->IsHeapObject()) { 44573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(ecx, Handle<HeapObject>::cast(value)); 44583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(result, total_offset), ecx); 44593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 44603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(result, total_offset), Immediate(value)); 44613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 44623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 44633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (has_elements) { 44653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy elements backing store header. 44663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(source, elements); 44673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < FixedArray::kHeaderSize; i += kPointerSize) { 44683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, FieldOperand(source, i)); 44693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(result, elements_offset + i), ecx); 44703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 44713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy elements backing store content. 44733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int elements_length = elements->length(); 44743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements->IsFixedDoubleArray()) { 44753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedDoubleArray> double_array = 44763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedDoubleArray>::cast(elements); 44773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < elements_length; i++) { 44783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int64_t value = double_array->get_representation(i); 44793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int32_t value_low = value & 0xFFFFFFFF; 44803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int32_t value_high = value >> 32; 44813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int total_offset = 44823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements_offset + FixedDoubleArray::OffsetOfElementAt(i); 44833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(result, total_offset), Immediate(value_low)); 44843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(result, total_offset + 4), Immediate(value_high)); 44853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 44863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (elements->IsFixedArray()) { 44873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < elements_length; i++) { 44883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i); 44893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> value = JSObject::GetElement(object, i); 44903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (value->IsJSObject()) { 44913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> value_object = Handle<JSObject>::cast(value); 44923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(ecx, Operand(result, *offset)); 44933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(result, total_offset), ecx); 44943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(source, value_object); 44953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitDeepCopy(value_object, result, source, offset); 44963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (value->IsHeapObject()) { 44973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(ecx, Handle<HeapObject>::cast(value)); 44983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(result, total_offset), ecx); 44993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 45003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(FieldOperand(result, total_offset), Immediate(value)); 45013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 45023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 45033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 45043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 45053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 45063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 45073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 45083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 45093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 45103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoFastLiteral(LFastLiteral* instr) { 45113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(ToRegister(instr->context()).is(esi)); 45123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = instr->hydrogen()->total_size(); 45133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 45143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate all objects that are part of the literal in one big 45153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allocation. This avoids multiple limit checks. 45163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label allocated, runtime_allocate; 45173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); 45183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&allocated); 45193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 45203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&runtime_allocate); 45213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Immediate(Smi::FromInt(size))); 45223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); 45233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 45243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&allocated); 45253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset = 0; 45263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(ebx, instr->hydrogen()->boilerplate()); 45273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitDeepCopy(instr->hydrogen()->boilerplate(), eax, ebx, &offset); 45283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(size, offset); 45293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 45303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 45313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 45325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { 4533592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(ToRegister(instr->context()).is(esi)); 45343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> literals(instr->environment()->closure()->literals()); 45353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> constant_properties = 45363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->hydrogen()->constant_properties(); 45373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 45383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the parameters to the stub/runtime call. 45393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushHeapObject(literals); 4540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); 45413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Immediate(constant_properties)); 454244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int flags = instr->hydrogen()->fast_elements() 454344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? ObjectLiteral::kFastElements 454444f0eee88ff00398ff7f715fab053374d808c90dSteve Block : ObjectLiteral::kNoFlags; 454544f0eee88ff00398ff7f715fab053374d808c90dSteve Block flags |= instr->hydrogen()->has_function() 454644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? ObjectLiteral::kHasFunction 454744f0eee88ff00398ff7f715fab053374d808c90dSteve Block : ObjectLiteral::kNoFlags; 454844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ push(Immediate(Smi::FromInt(flags))); 4549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 45503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Pick the right runtime function or stub to call. 45513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int properties_count = constant_properties->length() / 2; 4552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->hydrogen()->depth() > 1) { 45533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallRuntime(Runtime::kCreateObjectLiteral, 4, instr); 45543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (flags != ObjectLiteral::kFastElements || 45553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { 455685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); 45573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 45583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastCloneShallowObjectStub stub(properties_count); 45593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 456444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid LCodeGen::DoToFastProperties(LToFastProperties* instr) { 456544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(ToRegister(instr->InputAt(0)).is(eax)); 456644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ push(eax); 45673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallRuntime(Runtime::kToFastProperties, 1, instr); 456844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 456944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 457044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { 45723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(ToRegister(instr->context()).is(esi)); 4573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label materialized; 4574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Registers will be used as follows: 4575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // edi = JS function. 4576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ecx = literals array. 4577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ebx = regexp literal. 4578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // eax = regexp literal clone. 45793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // esi = context. 4580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 4581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); 4582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int literal_offset = FixedArray::kHeaderSize + 4583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->hydrogen()->literal_index() * kPointerSize; 4584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ebx, FieldOperand(ecx, literal_offset)); 458544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(ebx, factory()->undefined_value()); 4586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &materialized, Label::kNear); 4587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Create regexp literal using runtime function 4589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Result will be in eax. 4590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(ecx); 4591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); 4592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(Immediate(instr->hydrogen()->pattern())); 4593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(Immediate(instr->hydrogen()->flags())); 45943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); 4595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ebx, eax); 4596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&materialized); 4598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 4599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label allocated, runtime_allocate; 4600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); 4601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ jmp(&allocated); 4602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&runtime_allocate); 4604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(ebx); 4605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(Immediate(Smi::FromInt(size))); 46063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); 4607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(ebx); 4608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&allocated); 4610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Copy the content into the newly allocated memory. 4611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // (Unroll copy loop once for better throughput). 4612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { 4613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(edx, FieldOperand(ebx, i)); 4614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); 4615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(FieldOperand(eax, i), edx); 4616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(FieldOperand(eax, i + kPointerSize), ecx); 4617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if ((size % (2 * kPointerSize)) != 0) { 4619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(edx, FieldOperand(ebx, size - kPointerSize)); 4620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(FieldOperand(eax, size - kPointerSize), edx); 4621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { 46263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(ToRegister(instr->context()).is(esi)); 4627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Use the fast case closure allocation code that allocates in new 4628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // space for nested functions that don't need literals cloning. 4629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<SharedFunctionInfo> shared_info = instr->shared_info(); 46301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool pretenure = instr->hydrogen()->pretenure(); 463144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!pretenure && shared_info->num_literals() == 0) { 46323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FastNewClosureStub stub(shared_info->language_mode()); 4633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(Immediate(shared_info)); 46343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 46363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(esi); 4637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(Immediate(shared_info)); 4638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(Immediate(pretenure 463944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? factory()->true_value() 464044f0eee88ff00398ff7f715fab053374d808c90dSteve Block : factory()->false_value())); 46413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallRuntime(Runtime::kNewClosure, 3, instr); 4642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoTypeof(LTypeof* instr) { 46473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LOperand* input = instr->InputAt(1); 46483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitPushTaggedOperand(input); 46493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallRuntime(Runtime::kTypeof, 1, instr); 4650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 4654b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Register input = ToRegister(instr->InputAt(0)); 4655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int true_block = chunk_->LookupDestination(instr->true_block_id()); 4656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int false_block = chunk_->LookupDestination(instr->false_block_id()); 4657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* true_label = chunk_->GetAssemblyLabel(true_block); 4658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* false_label = chunk_->GetAssemblyLabel(false_block); 4659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 46603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Condition final_branch_condition = 46613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitTypeofIs(true_label, false_label, input, instr->type_literal()); 46623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (final_branch_condition != no_condition) { 46633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitBranch(true_block, false_block, final_branch_condition); 46643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochCondition LCodeGen::EmitTypeofIs(Label* true_label, 4669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* false_label, 4670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Register input, 4671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> type_name) { 4672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Condition final_branch_condition = no_condition; 467344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (type_name->Equals(heap()->number_symbol())) { 4674e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(input, true_label); 4675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(FieldOperand(input, HeapObject::kMapOffset), 467644f0eee88ff00398ff7f715fab053374d808c90dSteve Block factory()->heap_number_map()); 4677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch final_branch_condition = equal; 4678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 467944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->string_symbol())) { 4680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(input, false_label); 4681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); 4682e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(above_equal, false_label); 4683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test_b(FieldOperand(input, Map::kBitFieldOffset), 4684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1 << Map::kIsUndetectable); 4685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch final_branch_condition = zero; 4686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 468744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->boolean_symbol())) { 468844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(input, factory()->true_value()); 4689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(equal, true_label); 469044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(input, factory()->false_value()); 4691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch final_branch_condition = equal; 4692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 469369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_symbol())) { 469469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(input, factory()->null_value()); 469569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch final_branch_condition = equal; 469669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 469744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->undefined_symbol())) { 469844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmp(input, factory()->undefined_value()); 4699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ j(equal, true_label); 4700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(input, false_label); 4701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check for undetectable objects => true. 4702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); 4703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test_b(FieldOperand(input, Map::kBitFieldOffset), 4704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1 << Map::kIsUndetectable); 4705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch final_branch_condition = not_zero; 4706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 470744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->function_symbol())) { 47083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 4709e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(input, false_label); 47103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(input, JS_FUNCTION_TYPE, input); 47113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, true_label); 47123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE); 47133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch final_branch_condition = equal; 4714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 471544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (type_name->Equals(heap()->object_symbol())) { 4716e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(input, false_label); 471769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (!FLAG_harmony_typeof) { 471869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmp(input, factory()->null_value()); 471969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, true_label); 472069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 47213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); 4722e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(below, false_label); 47233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 47243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above, false_label); 4725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check for undetectable objects => false. 4726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ test_b(FieldOperand(input, Map::kBitFieldOffset), 4727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1 << Map::kIsUndetectable); 4728e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch final_branch_condition = zero; 4729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ jmp(false_label); 4732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return final_branch_condition; 4734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 47371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 47381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register temp = ToRegister(instr->TempAt(0)); 47391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int true_block = chunk_->LookupDestination(instr->true_block_id()); 47401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int false_block = chunk_->LookupDestination(instr->false_block_id()); 47411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 47421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitIsConstructCall(temp); 47431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitBranch(true_block, false_block, equal); 47441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 47451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 47461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 47471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LCodeGen::EmitIsConstructCall(Register temp) { 47481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Get the frame pointer for the calling frame. 47491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 47501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 47511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Skip the arguments adaptor frame if it exists. 4752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label check_frame_marker; 47531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), 47541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 4755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &check_frame_marker, Label::kNear); 47561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); 47571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 47581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check the marker in the calling frame. 47591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&check_frame_marker); 47601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), 47611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); 47621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 47631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 47641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 47652b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdochvoid LCodeGen::EnsureSpaceForLazyDeopt() { 47662b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // Ensure that we have enough space after the previous lazy-bailout 47672b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // instruction for patching the code here. 47682b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch int current_pc = masm()->pc_offset(); 47692b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch int patch_size = Deoptimizer::patch_size(); 47702b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch if (current_pc < last_lazy_deopt_pc_ + patch_size) { 47712b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch int padding_size = last_lazy_deopt_pc_ + patch_size - current_pc; 47723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Nop(padding_size); 47732b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch } 47742b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch last_lazy_deopt_pc_ = masm()->pc_offset(); 47752b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch} 47762b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch 47772b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch 4778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoLazyBailout(LLazyBailout* instr) { 47792b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch EnsureSpaceForLazyDeopt(); 47802b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(instr->HasEnvironment()); 47812b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch LEnvironment* env = instr->environment(); 47822b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); 47832b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 4784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoDeoptimize(LDeoptimize* instr) { 4788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeIf(no_condition, instr->environment()); 4789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { 4793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* obj = instr->object(); 4794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* key = instr->key(); 4795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(ToOperand(obj)); 47963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitPushTaggedOperand(key); 47971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 47981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LPointerMap* pointers = instr->pointer_map(); 47991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RecordPosition(pointers->position()); 4800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Create safepoint generator that will also ensure enough space in the 4801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // reloc info for patching in deoptimization (since this is invoking a 4802e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // builtin) 48032b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch SafepointGenerator safepoint_generator( 48042b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch this, pointers, Safepoint::kLazyDeopt); 4805e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ push(Immediate(Smi::FromInt(strict_mode_flag()))); 4806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); 4807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 48103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { 48112b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch PushSafepointRegistersScope scope(this); 48122b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 48132b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch __ CallRuntimeSaveDoubles(Runtime::kStackGuard); 48142b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RecordSafepointWithLazyDeopt( 48152b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); 48162b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(instr->HasEnvironment()); 48172b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch LEnvironment* env = instr->environment(); 48182b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 48193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 48203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 48213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoStackCheck(LStackCheck* instr) { 48233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch class DeferredStackCheck: public LDeferredCode { 48243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public: 48253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) 48263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch : LDeferredCode(codegen), instr_(instr) { } 48273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } 48283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch virtual LInstruction* instr() { return instr_; } 48293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private: 48303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LStackCheck* instr_; 48313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch }; 4832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 48332b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(instr->HasEnvironment()); 48342b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch LEnvironment* env = instr->environment(); 48352b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // There is no LLazyBailout instruction for stack-checks. We have to 48362b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // prepare for lazy deoptimization explicitly here. 48373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (instr->hydrogen()->is_function_entry()) { 48383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Perform stack overflow check. 48393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label done; 48403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ExternalReference stack_limit = 48413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ExternalReference::address_of_stack_limit(isolate()); 48423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(esp, Operand::StaticVariable(stack_limit)); 48433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above_equal, &done, Label::kNear); 48443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 48453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(instr->context()->IsRegister()); 48463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(ToRegister(instr->context()).is(esi)); 48473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch StackCheckStub stub; 48483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 48492b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch EnsureSpaceForLazyDeopt(); 48503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&done); 48512b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); 48522b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 48533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 48543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(instr->hydrogen()->is_backwards_branch()); 48553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Perform stack overflow check if this goto needs it before jumping. 48563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DeferredStackCheck* deferred_stack_check = 48573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new DeferredStackCheck(this, instr); 48583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ExternalReference stack_limit = 48593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ExternalReference::address_of_stack_limit(isolate()); 48603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmp(esp, Operand::StaticVariable(stack_limit)); 48613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(below, deferred_stack_check->entry()); 48622b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch EnsureSpaceForLazyDeopt(); 48633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(instr->done_label()); 48643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch deferred_stack_check->SetExit(instr->done_label()); 48652b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); 48662b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // Don't record a deoptimization index for the safepoint here. 48672b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // This will be done explicitly when emitting call and the safepoint in 48682b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // the deferred code. 48693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 4870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid LCodeGen::DoOsrEntry(LOsrEntry* instr) { 4874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // This is a pseudo-instruction that ensures that the environment here is 4875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // properly registered for deoptimization and records the assembler's PC 4876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // offset. 4877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LEnvironment* environment = instr->environment(); 4878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment->SetSpilledRegisters(instr->SpilledRegisterArray(), 4879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->SpilledDoubleRegisterArray()); 4880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If the environment were already registered, we would have no way of 4882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // backpatching it with the spill slot operands. 4883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!environment->HasBeenRegistered()); 48842b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 4885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(osr_pc_offset_ == -1); 4886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch osr_pc_offset_ = masm()->pc_offset(); 4887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid LCodeGen::DoIn(LIn* instr) { 4891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LOperand* obj = instr->object(); 4892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LOperand* key = instr->key(); 48933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitPushTaggedOperand(key); 48943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitPushTaggedOperand(obj); 4895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 4896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LPointerMap* pointers = instr->pointer_map(); 4897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch RecordPosition(pointers->position()); 48982b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch SafepointGenerator safepoint_generator( 48992b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch this, pointers, Safepoint::kLazyDeopt); 4900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); 4901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 4902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 49043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 49053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, isolate()->factory()->undefined_value()); 49063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(equal, instr->environment()); 49073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, isolate()->factory()->null_value()); 49093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(equal, instr->environment()); 49103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ test(eax, Immediate(kSmiTagMask)); 49123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(zero, instr->environment()); 49133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 49153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx); 49163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(below_equal, instr->environment()); 49173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label use_cache, call_runtime; 49193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckEnumCache(&call_runtime); 49203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 49223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&use_cache, Label::kNear); 49233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the set of properties to enumerate. 49253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&call_runtime); 49263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(eax); 49273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); 49283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 49303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->meta_map()); 49313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(not_equal, instr->environment()); 49323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&use_cache); 49333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 49343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 49373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register map = ToRegister(instr->map()); 49383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result = ToRegister(instr->result()); 49393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadInstanceDescriptors(map, result); 49403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(result, 49413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldOperand(result, DescriptorArray::kEnumerationIndexOffset)); 49423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(result, 49433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 49443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ test(result, result); 49453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(equal, instr->environment()); 49463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 49473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 49503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object = ToRegister(instr->value()); 49513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ToRegister(instr->map()), 49523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldOperand(object, HeapObject::kMapOffset)); 49533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizeIf(not_equal, instr->environment()); 49543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 49553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { 49583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object = ToRegister(instr->object()); 49593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register index = ToRegister(instr->index()); 49603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label out_of_object, done; 49623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(index, Immediate(0)); 49633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(less, &out_of_object); 49643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(object, FieldOperand(object, 49653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 49663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_half_pointer_size, 49673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSObject::kHeaderSize)); 49683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done, Label::kNear); 49693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&out_of_object); 49713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(object, FieldOperand(object, JSObject::kPropertiesOffset)); 49723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ neg(index); 49733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Index is now equal to out of object property index plus 1. 49743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(object, FieldOperand(object, 49753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 49763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_half_pointer_size, 49773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize - kPointerSize)); 49783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 49793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 49803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 49813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef __ 4983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} } // namespace v8::internal 4985b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 4986b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif // V8_TARGET_ARCH_IA32 4987