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