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