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, &not_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(&not_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, &not_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(&not_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, &not_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(&not_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