178d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
4b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
6b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
793a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_X64
89dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/code-stubs.h"
10196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/codegen.h"
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/compiler.h"
12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/debug.h"
13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/full-codegen.h"
14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/isolate-inl.h"
15196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/parser.h"
16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/scopes.h"
17196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/stub-cache.h"
18b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
19b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgnamespace v8 {
20b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgnamespace internal {
21b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
22b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org#define __ ACCESS_MASM(masm_)
23b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
24d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
25d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.comclass JumpPatchSite BASE_EMBEDDED {
26d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com public:
27486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
28d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com#ifdef DEBUG
29d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    info_emitted_ = false;
30d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com#endif
31d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  }
32d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
33d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  ~JumpPatchSite() {
34d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    ASSERT(patch_site_.is_bound() == info_emitted_);
35d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  }
36d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
3783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void EmitJumpIfNotSmi(Register reg,
3883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                        Label* target,
3983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                        Label::Distance near_jump = Label::kFar) {
40d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    __ testb(reg, Immediate(kSmiTagMask));
4183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    EmitJump(not_carry, target, near_jump);   // Always taken before patched.
42d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  }
43d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
4483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void EmitJumpIfSmi(Register reg,
4583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                     Label* target,
4683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org                     Label::Distance near_jump = Label::kFar) {
47d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    __ testb(reg, Immediate(kSmiTagMask));
4883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    EmitJump(carry, target, near_jump);  // Never taken before patched.
49d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  }
50d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
51d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  void EmitPatchInfo() {
524f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    if (patch_site_.is_bound()) {
534f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
54731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org      ASSERT(is_uint8(delta_to_patch_site));
554f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      __ testl(rax, Immediate(delta_to_patch_site));
56d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com#ifdef DEBUG
574f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      info_emitted_ = true;
58d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com#endif
594f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    } else {
604f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      __ nop();  // Signals no inlined code.
614f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    }
62d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  }
63d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
64d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com private:
65d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  // jc will be patched with jz, jnc will become jnz.
6683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  void EmitJump(Condition cc, Label* target, Label::Distance near_jump) {
67d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    ASSERT(!patch_site_.is_bound() && !info_emitted_);
68d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    ASSERT(cc == carry || cc == not_carry);
69d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    __ bind(&patch_site_);
7083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(cc, target, near_jump);
71d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  }
72d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
73d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  MacroAssembler* masm_;
74d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  Label patch_site_;
75d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com#ifdef DEBUG
76d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  bool info_emitted_;
77d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com#endif
78d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com};
79d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
80d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
81b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// Generate code for a JS function.  On entry to the function the receiver
82b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// and arguments have been pushed on the stack left to right, with the
83b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// return address on top of them.  The actual argument count matches the
84b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// formal parameter count expected by the function.
85b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org//
86b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// The live registers are:
872efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org//   o rdi: the JS function object being called (i.e. ourselves)
88b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org//   o rsi: our context
89b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org//   o rbp: our caller's frame pointer
90b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org//   o rsp: stack pointer (pointing to return address)
91b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org//
92b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// The function builds a JS frame.  Please see JavaScriptFrameConstants in
93b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// frames-x64.h for its layout.
9456454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.orgvoid FullCodeGenerator::Generate() {
9556454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  CompilationInfo* info = info_;
9604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  handler_table_ =
9704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org      isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
98f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
9941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  profiling_counter_ = isolate()->factory()->NewCell(
100fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
1015c838251403b0be9a882540f1922577abba4c872ager@chromium.org  SetFunctionPosition(function());
102ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  Comment cmnt(masm_, "[ function compiled by full code generator");
103b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
104753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  ProfileEntryHookStub::MaybeCallEntryHook(masm_);
105753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org
106a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org#ifdef DEBUG
107a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org  if (strlen(FLAG_stop_at) > 0 &&
10859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org      info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
109a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org    __ int3();
110a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org  }
111a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org#endif
112a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org
113486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  // Sloppy mode functions and builtins need to replace the receiver with the
114e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  // global proxy when called as functions (without an explicit receiver
115e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  // object).
116486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  if (info->strict_mode() == SLOPPY && !info->is_native()) {
11740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    Label ok;
118e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    // +1 for return address.
119d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    StackArgumentsAccessor args(rsp, info->scope()->num_parameters());
12043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rcx, args.GetReceiverOperand());
121e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org
122e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
123e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    __ j(not_equal, &ok, Label::kNear);
124e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org
12543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rcx, GlobalObjectOperand());
12643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
127e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org
12843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(args.GetReceiverOperand(), rcx);
129e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org
13040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org    __ bind(&ok);
13140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  }
13240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org
133c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Open a frame scope to indicate that there is a frame on the stack.  The
134c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // MANUAL indicates that the scope shouldn't actually generate code to set up
135c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // the frame (that is done below).
136c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  FrameScope frame_scope(masm_, StackFrame::MANUAL);
137c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
13883130cfc204d3ffed6832a7ef149b19328a58b33svenpanne@chromium.org  info->set_prologue_offset(masm_->pc_offset());
139285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org  __ Prologue(info->IsCodePreAgingActive());
1404e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  info->AddNoFrameRange(0, masm_->pc_offset());
141ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org
142ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  { Comment cmnt(masm_, "[ Allocate locals");
1434f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    int locals_count = info->scope()->num_stack_slots();
144e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    // Generators allocate locals, if any, in context slots.
145e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    ASSERT(!info->function()->is_generator() || locals_count == 0);
146ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    if (locals_count == 1) {
147ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org      __ PushRoot(Heap::kUndefinedValueRootIndex);
148ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    } else if (locals_count > 1) {
149a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org      if (locals_count >= 128) {
1503ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        Label ok;
1513ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        __ movp(rcx, rsp);
1523ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        __ subp(rcx, Immediate(locals_count * kPointerSize));
1533ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        __ CompareRoot(rcx, Heap::kRealStackLimitRootIndex);
1543ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        __ j(above_equal, &ok, Label::kNear);
1553ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
1563ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        __ bind(&ok);
157a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org      }
158ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org      __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
159a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org      const int kMaxPushes = 32;
160a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org      if (locals_count >= kMaxPushes) {
161a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org        int loop_iterations = locals_count / kMaxPushes;
1622f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org        __ movp(rcx, Immediate(loop_iterations));
163a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org        Label loop_header;
164a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org        __ bind(&loop_header);
165a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org        // Do pushes.
166a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org        for (int i = 0; i < kMaxPushes; i++) {
167a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org          __ Push(rdx);
168a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org        }
169a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org        // Continue loop if not done.
1702f599e5925b02d78bd78703b44741d6b27e53a44machenbach@chromium.org        __ decp(rcx);
171a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org        __ j(not_zero, &loop_header, Label::kNear);
172a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org      }
173a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org      int remaining = locals_count % kMaxPushes;
174a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org      // Emit the remaining pushes.
175a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org      for (int i  = 0; i < remaining; i++) {
176763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org        __ Push(rdx);
177b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      }
178b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
179ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  }
180b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
181ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  bool function_in_register = true;
182b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
183ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  // Possibly allocate a local context.
1844f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
185ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  if (heap_slots > 0) {
18646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    Comment cmnt(masm_, "[ Allocate context");
1877e6132b924829c353864933f29124419916db550machenbach@chromium.org    bool need_write_barrier = true;
188ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    // Argument to NewContext is the function, which is still in rdi.
18946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
190763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rdi);
19146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      __ Push(info->scope()->GetScopeInfo());
192895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org      __ CallRuntime(Runtime::kHiddenNewGlobalContext, 2);
19346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    } else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
194f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org      FastNewContextStub stub(isolate(), heap_slots);
195ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org      __ CallStub(&stub);
1967e6132b924829c353864933f29124419916db550machenbach@chromium.org      // Result of FastNewContextStub is always in new space.
1977e6132b924829c353864933f29124419916db550machenbach@chromium.org      need_write_barrier = false;
198ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    } else {
199763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rdi);
200895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org      __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1);
201ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    }
202ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    function_in_register = false;
203bbbda924f939464825b508976aabe7ed128605cbmachenbach@chromium.org    // Context is returned in rax.  It replaces the context passed to us.
204bbbda924f939464825b508976aabe7ed128605cbmachenbach@chromium.org    // It's saved in the stack and kept live in rsi.
205bbbda924f939464825b508976aabe7ed128605cbmachenbach@chromium.org    __ movp(rsi, rax);
206bbbda924f939464825b508976aabe7ed128605cbmachenbach@chromium.org    __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax);
207ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org
208ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    // Copy any necessary parameters into the context.
2094f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    int num_parameters = info->scope()->num_parameters();
210ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    for (int i = 0; i < num_parameters; i++) {
211486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      Variable* var = scope()->parameter(i);
212486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      if (var->IsContextSlot()) {
213ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
214ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org            (num_parameters - 1 - i) * kPointerSize;
215ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org        // Load parameter from stack.
21643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org        __ movp(rax, Operand(rbp, parameter_offset));
217ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org        // Store it in the context.
218486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org        int context_offset = Context::SlotOffset(var->index());
21943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org        __ movp(Operand(rsi, context_offset), rax);
220c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        // Update the write barrier.  This clobbers rax and rbx.
2217e6132b924829c353864933f29124419916db550machenbach@chromium.org        if (need_write_barrier) {
2227e6132b924829c353864933f29124419916db550machenbach@chromium.org          __ RecordWriteContextSlot(
2237e6132b924829c353864933f29124419916db550machenbach@chromium.org              rsi, context_offset, rax, rbx, kDontSaveFPRegs);
2247e6132b924829c353864933f29124419916db550machenbach@chromium.org        } else if (FLAG_debug_code) {
2257e6132b924829c353864933f29124419916db550machenbach@chromium.org          Label done;
2267e6132b924829c353864933f29124419916db550machenbach@chromium.org          __ JumpIfInNewSpace(rsi, rax, &done, Label::kNear);
2277e6132b924829c353864933f29124419916db550machenbach@chromium.org          __ Abort(kExpectedNewSpaceObject);
2287e6132b924829c353864933f29124419916db550machenbach@chromium.org          __ bind(&done);
2297e6132b924829c353864933f29124419916db550machenbach@chromium.org        }
230b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      }
231b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
232ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  }
233b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
234ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  // Possibly allocate an arguments object.
2354a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  Variable* arguments = scope()->arguments();
236ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  if (arguments != NULL) {
237ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    // Arguments object must be allocated after the context object, in
238ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    // case the "arguments" or ".arguments" variables are in the context.
239ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    Comment cmnt(masm_, "[ Allocate arguments object");
240ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    if (function_in_register) {
241763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rdi);
242ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    } else {
243763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
244b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
245ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    // The receiver is just before the parameters on the caller's stack.
2464f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    int num_parameters = info->scope()->num_parameters();
2474f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    int offset = num_parameters * kPointerSize;
248895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    __ leap(rdx,
249ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org           Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
250763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(rdx);
2514f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    __ Push(Smi::FromInt(num_parameters));
252ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    // Arguments to ArgumentsAccessStub:
253ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    //   function, receiver address, parameter count.
254ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    // The stub will rewrite receiver and parameter count if the previous
255ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    // stack frame was an arguments adapter frame.
2562efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    ArgumentsAccessStub::Type type;
257486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    if (strict_mode() == STRICT) {
2582efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org      type = ArgumentsAccessStub::NEW_STRICT;
2592efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    } else if (function()->has_duplicate_parameters()) {
260486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
2612efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    } else {
262486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
2632efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org    }
264f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org    ArgumentsAccessStub stub(isolate(), type);
265ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org    __ CallStub(&stub);
2664d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org
267486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    SetVar(arguments, rax, rbx, rdx);
268b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
269b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
270a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  if (FLAG_trace) {
271a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ CallRuntime(Runtime::kTraceEnter, 0);
272a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
273a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
2745d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // Visit the declarations and body unless there is an illegal
2755d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // redeclaration.
2765d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  if (scope()->HasIllegalRedeclaration()) {
2775d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    Comment cmnt(masm_, "[ Declarations");
2785d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    scope()->VisitIllegalRedeclaration(this);
279486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org
2805d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  } else {
281471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org    PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
2825d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    { Comment cmnt(masm_, "[ Declarations");
2835d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org      // For named function expressions, declare the function name as a
2845d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org      // constant.
2855d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org      if (scope()->is_function_scope() && scope()->function() != NULL) {
286ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com        VariableDeclaration* function = scope()->function();
287ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com        ASSERT(function->proxy()->var()->mode() == CONST ||
288486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org               function->proxy()->var()->mode() == CONST_LEGACY);
289ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com        ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
290ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com        VisitVariableDeclaration(function);
2915d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org      }
2925d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org      VisitDeclarations(scope()->declarations());
2935d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    }
294b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2955d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    { Comment cmnt(masm_, "[ Stack check");
296471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org      PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
2973ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org       Label ok;
2983ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org       __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
2993ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org       __ j(above_equal, &ok, Label::kNear);
3003ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org       __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET);
3013ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org       __ bind(&ok);
3025d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    }
3035d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org
3045d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    { Comment cmnt(masm_, "[ Body");
3055d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org      ASSERT(loop_depth() == 0);
3065d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org      VisitStatements(function()->body());
3075d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org      ASSERT(loop_depth() == 0);
3085d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    }
309b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
310b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
3115d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // Always emit a 'return undefined' in case control fell off the end of
3125d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // the body.
313b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  { Comment cmnt(masm_, "[ return <undefined>;");
314b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
3152cc82ae439960d1adaf4374e093730dc23945d59ager@chromium.org    EmitReturnSequence();
316b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
317b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
318b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
319b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
3205f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.orgvoid FullCodeGenerator::ClearAccumulator() {
3215d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  __ Set(rax, 0);
3225f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org}
3235f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
3245f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
3251456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
3269cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
32741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset),
3281456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org                    Smi::FromInt(-delta));
3291456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org}
3301456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
3311456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
3321456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgvoid FullCodeGenerator::EmitProfilingCounterReset() {
3331456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  int reset_value = FLAG_interrupt_budget;
3349cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
335e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  __ Move(kScratchRegister, Smi::FromInt(reset_value));
33643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister);
3371456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org}
3381456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
3391456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
340731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.orgstatic const byte kJnsOffset = kPointerSize == kInt64Size ? 0x1d : 0x14;
341731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org
342731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org
343cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.orgvoid FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
344cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org                                                Label* back_edge_target) {
345cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org  Comment cmnt(masm_, "[ Back edge bookkeeping");
34683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label ok;
3471456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
348afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  ASSERT(back_edge_target->is_bound());
349afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
350afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  int weight = Min(kMaxBackEdgeWeight,
351afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org                   Max(1, distance / kCodeSizeMultiplier));
352cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org  EmitProfilingCounterDecrement(weight);
3531456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
354731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  __ j(positive, &ok, Label::kNear);
355731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  {
356731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    PredictableCodeSizeScope predictible_code_size_scope(masm_, kJnsOffset);
357731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    DontEmitDebugCodeScope dont_emit_debug_code_scope(masm_);
358731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
359d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
360731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    // Record a mapping of this PC offset to the OSR id.  This is used to find
361731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    // the AST id from the unoptimized code in order to use it as a key into
362731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    // the deoptimization input data found in the optimized code.
363731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    RecordBackEdge(stmt->OsrEntryId());
3641456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
365731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org    EmitProfilingCounterReset();
366731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org  }
367a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&ok);
368731474e847a8ccd6e27f74842506c9c807dae658jarin@chromium.org
369a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
370d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // Record a mapping of the OSR id to this PC.  This is used if the OSR
371d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // entry becomes the target of a bailout.  We don't expect it to be, but
372d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // we want it to work if it is.
373a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
374a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
375a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
376a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
3772cc82ae439960d1adaf4374e093730dc23945d59ager@chromium.orgvoid FullCodeGenerator::EmitReturnSequence() {
378b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Comment cmnt(masm_, "[ Return sequence");
379b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  if (return_label_.is_bound()) {
380b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ jmp(&return_label_);
381b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  } else {
382b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ bind(&return_label_);
383b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    if (FLAG_trace) {
384763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);
385b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ CallRuntime(Runtime::kTraceExit, 1);
386b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
387afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    // Pretend that the exit is a backwards jump to the entry.
388afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    int weight = 1;
389afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    if (info_->ShouldSelfOptimize()) {
390afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org      weight = FLAG_interrupt_budget / FLAG_self_opt_count;
391afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    } else {
392afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org      int distance = masm_->pc_offset();
393afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org      weight = Min(kMaxBackEdgeWeight,
394afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org                   Max(1, distance / kCodeSizeMultiplier));
3951456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    }
396afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    EmitProfilingCounterDecrement(weight);
397afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    Label ok;
398afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    __ j(positive, &ok, Label::kNear);
399763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(rax);
400afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    __ call(isolate()->builtins()->InterruptCheck(),
401afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org            RelocInfo::CODE_TARGET);
402763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Pop(rax);
403afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    EmitProfilingCounterReset();
404afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    __ bind(&ok);
405b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org#ifdef DEBUG
406b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    // Add a label for checking the size of the code used for returning.
407b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    Label check_exit_codesize;
408b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    masm_->bind(&check_exit_codesize);
409b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org#endif
410e90029b96bc4097e0f14d33cc086030d7ad5007awhesse@chromium.org    CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
411b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ RecordJSReturn();
412b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    // Do not use the leave instruction here because it is too short to
413b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    // patch with the code required by the debugger.
41443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rsp, rbp);
415763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ popq(rbp);
4164e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    int no_frame_start = masm_->pc_offset();
417d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
4184f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize;
419d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    __ Ret(arguments_bytes, rcx);
420d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
421b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    // Add padding that will be overwritten by a debugger breakpoint.  We
4224edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org    // have just generated at least 7 bytes: "movp rsp, rbp; pop rbp; ret k"
4234edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org    // (3 + 1 + 3) for x64 and at least 6 (2 + 1 + 3) bytes for x32.
4244edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org    const int kPadding = Assembler::kJSReturnSequenceLength -
4254edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org                         kPointerSize == kInt64Size ? 7 : 6;
426b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    for (int i = 0; i < kPadding; ++i) {
427b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      masm_->int3();
428b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
429d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    // Check that the size of the code used for returning is large enough
430d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    // for the debugger's requirements.
431d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    ASSERT(Assembler::kJSReturnSequenceLength <=
432d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com           masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
433865f51ff8c94f86f4c97636d70addc0f29e79674machenbach@chromium.org
4344e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
435b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
436b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
437b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
438b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
439486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.orgvoid FullCodeGenerator::EffectContext::Plug(Variable* var) const {
440486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
4414a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
442b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
443b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
444486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.orgvoid FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
445486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
446486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  codegen()->GetVar(result_register(), var);
4474a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
448b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4494a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
450486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.orgvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
451486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
452486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  MemOperand operand = codegen()->VarOperand(var, result_register());
453763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(operand);
454b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
455b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
456b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
457486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.orgvoid FullCodeGenerator::TestContext::Plug(Variable* var) const {
458486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  codegen()->GetVar(result_register(), var);
459c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
4606d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  codegen()->DoTest(this);
4614a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
462b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4634a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
4644a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
465b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
466b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
467b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4684a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::AccumulatorValueContext::Plug(
4694a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    Heap::RootListIndex index) const {
4704a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ LoadRoot(result_register(), index);
4714a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
472b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4734a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
4744a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::StackValueContext::Plug(
4754a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    Heap::RootListIndex index) const {
4764a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ PushRoot(index);
4774a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
4784a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
4794a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
4804a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
481c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  codegen()->PrepareForBailoutBeforeSplit(condition(),
482a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                          true,
483a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                          true_label_,
484a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                          false_label_);
4854a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  if (index == Heap::kUndefinedValueRootIndex ||
4864a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      index == Heap::kNullValueRootIndex ||
4874a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      index == Heap::kFalseValueRootIndex) {
488a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    if (false_label_ != fall_through_) __ jmp(false_label_);
4894a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  } else if (index == Heap::kTrueValueRootIndex) {
490a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    if (true_label_ != fall_through_) __ jmp(true_label_);
4914a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  } else {
4924a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    __ LoadRoot(result_register(), index);
4936d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    codegen()->DoTest(this);
494b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
495b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
496b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
497b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4984a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
4994a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
500b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
501b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5024a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::AccumulatorValueContext::Plug(
5034a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    Handle<Object> lit) const {
5047a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  if (lit->IsSmi()) {
5057a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org    __ SafeMove(result_register(), Smi::cast(*lit));
5067a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  } else {
5077a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org    __ Move(result_register(), lit);
5087a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  }
5094a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
510b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5114a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
5124a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
5137a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  if (lit->IsSmi()) {
5147a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org    __ SafePush(Smi::cast(*lit));
5157a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  } else {
5167a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org    __ Push(lit);
5177a6fc815d62905d0c52705b96225b1bd23e00a43jkummerow@chromium.org  }
5184a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
5194a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
5204a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
5214a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
522c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  codegen()->PrepareForBailoutBeforeSplit(condition(),
523a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                          true,
524a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                          true_label_,
525a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                          false_label_);
5264a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  ASSERT(!lit->IsUndetectableObject());  // There are no undetectable literals.
5274a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
528a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    if (false_label_ != fall_through_) __ jmp(false_label_);
5294a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  } else if (lit->IsTrue() || lit->IsJSObject()) {
530a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    if (true_label_ != fall_through_) __ jmp(true_label_);
5314a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  } else if (lit->IsString()) {
5324a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    if (String::cast(*lit)->length() == 0) {
533a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      if (false_label_ != fall_through_) __ jmp(false_label_);
5344a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    } else {
535a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      if (true_label_ != fall_through_) __ jmp(true_label_);
5364a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    }
5374a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  } else if (lit->IsSmi()) {
5384a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    if (Smi::cast(*lit)->value() == 0) {
539a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      if (false_label_ != fall_through_) __ jmp(false_label_);
5404a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    } else {
541a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      if (true_label_ != fall_through_) __ jmp(true_label_);
5424a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    }
5434a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  } else {
5444a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    // For simplicity we always test the accumulator register.
5454a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    __ Move(result_register(), lit);
5466d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    codegen()->DoTest(this);
547b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
548b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
549b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
550b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5514a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::EffectContext::DropAndPlug(int count,
5524a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                                                   Register reg) const {
553b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ASSERT(count > 0);
5544a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ Drop(count);
5554a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
556b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
557b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5584a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
5594a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    int count,
5604a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    Register reg) const {
5614a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  ASSERT(count > 0);
5624a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ Drop(count);
5634a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ Move(result_register(), reg);
5644a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
565b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5664a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
5674a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count,
5684a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                                                       Register reg) const {
5694a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  ASSERT(count > 0);
5704a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  if (count > 1) __ Drop(count - 1);
57143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(Operand(rsp, 0), reg);
5729dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
5739dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
5749dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
5754a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::TestContext::DropAndPlug(int count,
5764a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                                                 Register reg) const {
5774a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  ASSERT(count > 0);
5784a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  // For simplicity we always test the accumulator register.
5794a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ Drop(count);
5804a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ Move(result_register(), reg);
581c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
5826d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  codegen()->DoTest(this);
5834a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
584b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
585b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5864a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
5874a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                                            Label* materialize_false) const {
588a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  ASSERT(materialize_true == materialize_false);
5894a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ bind(materialize_true);
5904a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
591b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
5924a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
5934a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::AccumulatorValueContext::Plug(
5944a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    Label* materialize_true,
5954a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    Label* materialize_false) const {
59683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label done;
5974a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ bind(materialize_true);
598ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ Move(result_register(), isolate()->factory()->true_value());
59983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ jmp(&done, Label::kNear);
6004a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ bind(materialize_false);
601ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ Move(result_register(), isolate()->factory()->false_value());
6024a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ bind(&done);
603b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
604b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
605b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
6064a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::StackValueContext::Plug(
6074a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    Label* materialize_true,
6084a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    Label* materialize_false) const {
60983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label done;
6104a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ bind(materialize_true);
611ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ Push(isolate()->factory()->true_value());
61283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ jmp(&done, Label::kNear);
6134a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ bind(materialize_false);
614ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  __ Push(isolate()->factory()->false_value());
6154a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ bind(&done);
6164a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
6174a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6184a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6194a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true,
6204a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                                          Label* materialize_false) const {
6214a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  ASSERT(materialize_true == true_label_);
622a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  ASSERT(materialize_false == false_label_);
6234a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
6244a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6254a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6264a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::EffectContext::Plug(bool flag) const {
6274a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
6284a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6294a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6304a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
6314a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  Heap::RootListIndex value_root_index =
6324a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
6334a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ LoadRoot(result_register(), value_root_index);
6344a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
6354a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6364a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6374a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const {
6384a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  Heap::RootListIndex value_root_index =
6394a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
6404a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  __ PushRoot(value_root_index);
6414a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org}
6424a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6434a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
6444a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::TestContext::Plug(bool flag) const {
645c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  codegen()->PrepareForBailoutBeforeSplit(condition(),
646d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org                                          true,
647d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org                                          true_label_,
648d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org                                          false_label_);
6494a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  if (flag) {
6504a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    if (true_label_ != fall_through_) __ jmp(true_label_);
6514a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  } else {
6524a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    if (false_label_ != fall_through_) __ jmp(false_label_);
6539dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  }
6549dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
6559dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
6569dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
6576d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.orgvoid FullCodeGenerator::DoTest(Expression* condition,
6586d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org                               Label* if_true,
65965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                               Label* if_false,
66065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                               Label* fall_through) {
661b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org  Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
662f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  CallIC(ic, condition->test_id());
6637a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ testp(result_register(), result_register());
66465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // The stub returns nonzero for true.
66565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Split(not_zero, if_true, if_false, fall_through);
66665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
667b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
668b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
66965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.orgvoid FullCodeGenerator::Split(Condition cc,
67065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                              Label* if_true,
67165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                              Label* if_false,
67265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                              Label* fall_through) {
67365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  if (if_false == fall_through) {
67465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ j(cc, if_true);
67565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else if (if_true == fall_through) {
67665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ j(NegateCondition(cc), if_false);
67765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
67865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ j(cc, if_true);
67965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ jmp(if_false);
680b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
681b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
682b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
683b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
684486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.orgMemOperand FullCodeGenerator::StackOperand(Variable* var) {
685486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  ASSERT(var->IsStackAllocated());
686486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // Offset is negative because higher indexes are at lower addresses.
687486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  int offset = -var->index() * kPointerSize;
688486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // Adjust by a (parameter or local) base offset.
689486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  if (var->IsParameter()) {
690d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org    offset += kFPOnStackSize + kPCOnStackSize +
691d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org              (info_->scope()->num_parameters() - 1) * kPointerSize;
692486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  } else {
693486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    offset += JavaScriptFrameConstants::kLocal0Offset;
694486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  }
695486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  return Operand(rbp, offset);
696486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org}
697486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org
698486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org
699486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.orgMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
700486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
701486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  if (var->IsContextSlot()) {
702486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    int context_chain_length = scope()->ContextChainLength(var->scope());
703486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    __ LoadContext(scratch, context_chain_length);
704486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    return ContextOperand(scratch, var->index());
705486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  } else {
706486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    return StackOperand(var);
707b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
708b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
709b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
710b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
711486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.orgvoid FullCodeGenerator::GetVar(Register dest, Variable* var) {
712486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
713486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  MemOperand location = VarOperand(var, dest);
71443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(dest, location);
715b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
716b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
717b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
718486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.orgvoid FullCodeGenerator::SetVar(Variable* var,
719486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org                               Register src,
720486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org                               Register scratch0,
721486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org                               Register scratch1) {
722486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
723486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  ASSERT(!scratch0.is(src));
724486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  ASSERT(!scratch0.is(scratch1));
725486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  ASSERT(!scratch1.is(src));
726486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  MemOperand location = VarOperand(var, scratch0);
72743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(location, src);
728c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
729b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Emit the write barrier code if the location is in the heap.
730486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  if (var->IsContextSlot()) {
731486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    int offset = Context::SlotOffset(var->index());
732c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
733b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
734b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
735b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
736b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
737c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
738a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                                     bool should_normalize,
739a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                                     Label* if_true,
740a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                                     Label* if_false) {
741d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // Only prepare for bailouts before splits if we're in a test
742d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // context. Otherwise, we let the Visit function deal with the
743d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // preparation to avoid preparing with the same AST id twice.
744d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  if (!context()->IsTest() || !info_->IsOptimizable()) return;
745d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
74683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label skip;
74783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  if (should_normalize) __ jmp(&skip, Label::kNear);
748c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailout(expr, TOS_REG);
749d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  if (should_normalize) {
750d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
751d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    Split(equal, if_true, if_false, NULL);
752d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    __ bind(&skip);
753d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  }
754a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
755a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
756a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
757ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.comvoid FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
7588e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  // The variable in the declaration always resides in the current context.
759ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
760000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org  if (generate_debug_code_) {
761ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    // Check that we're not inside a with or catch context.
76243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rbx, FieldOperand(rsi, HeapObject::kMapOffset));
763ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    __ CompareRoot(rbx, Heap::kWithContextMapRootIndex);
764594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Check(not_equal, kDeclarationInWithContext);
765ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
766594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Check(not_equal, kDeclarationInCatchContext);
767ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  }
768ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com}
769ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
770ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
771ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.comvoid FullCodeGenerator::VisitVariableDeclaration(
772ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    VariableDeclaration* declaration) {
773486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // If it was not possible to allocate the variable at compile time, we
774486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // need to "declare" it at runtime to make sure it actually exists in the
775486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // local context.
776ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  VariableProxy* proxy = declaration->proxy();
777ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  VariableMode mode = declaration->mode();
7781805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  Variable* variable = proxy->var();
779486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
780486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  switch (variable->location()) {
781486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    case Variable::UNALLOCATED:
7827028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      globals_->Add(variable->name(), zone());
783ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      globals_->Add(variable->binding_needs_init()
784ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com                        ? isolate()->factory()->the_hole_value()
7857028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                    : isolate()->factory()->undefined_value(),
7867028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                    zone());
787486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      break;
788486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org
789486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    case Variable::PARAMETER:
790486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    case Variable::LOCAL:
791ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      if (hole_init) {
792ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com        Comment cmnt(masm_, "[ VariableDeclaration");
79380c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org        __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
79443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org        __ movp(StackOperand(variable), kScratchRegister);
795b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      }
7964668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      break;
797b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
798486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    case Variable::CONTEXT:
799ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      if (hole_init) {
800ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com        Comment cmnt(masm_, "[ VariableDeclaration");
801ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com        EmitDebugCheckDeclarationContext(variable);
80280c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org        __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
80343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org        __ movp(ContextOperand(rsi, variable->index()), kScratchRegister);
80480c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org        // No write barrier since the hole value is in old space.
8051805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
8064668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      }
8074668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      break;
808b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
809486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    case Variable::LOOKUP: {
810ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      Comment cmnt(masm_, "[ VariableDeclaration");
811763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rsi);
8124668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      __ Push(variable->name());
813394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      // Declaration nodes are always introduced in one of four modes.
814355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      ASSERT(IsDeclaredVariableMode(mode));
815394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      PropertyAttributes attr =
816355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org          IsImmutableVariableMode(mode) ? READ_ONLY : NONE;
8174668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      __ Push(Smi::FromInt(attr));
8184668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      // Push initial value, if any.
8194668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      // Note: For variables we must not push an initial value (such as
8204668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      // 'undefined') because we may have a (legal) redeclaration and we
8214668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      // must not destroy the current value.
822ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      if (hole_init) {
82380c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org        __ PushRoot(Heap::kTheHoleValueRootIndex);
8244668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      } else {
825486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org        __ Push(Smi::FromInt(0));  // Indicates no initial value.
8264668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      }
827895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org      __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4);
8284668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      break;
829b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
830b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
831b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
832b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
833b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
834ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.comvoid FullCodeGenerator::VisitFunctionDeclaration(
835ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    FunctionDeclaration* declaration) {
836ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  VariableProxy* proxy = declaration->proxy();
837ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  Variable* variable = proxy->var();
838ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  switch (variable->location()) {
839ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    case Variable::UNALLOCATED: {
8407028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      globals_->Add(variable->name(), zone());
841ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      Handle<SharedFunctionInfo> function =
842ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com          Compiler::BuildFunctionInfo(declaration->fun(), script());
843ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      // Check for stack-overflow exception.
844ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      if (function.is_null()) return SetStackOverflow();
8457028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      globals_->Add(function, zone());
846ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      break;
847ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    }
848ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
849ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    case Variable::PARAMETER:
850ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    case Variable::LOCAL: {
851ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      Comment cmnt(masm_, "[ FunctionDeclaration");
852ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      VisitForAccumulatorValue(declaration->fun());
85343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(StackOperand(variable), result_register());
854ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      break;
855ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    }
856ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
857ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    case Variable::CONTEXT: {
858ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      Comment cmnt(masm_, "[ FunctionDeclaration");
859ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      EmitDebugCheckDeclarationContext(variable);
860ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      VisitForAccumulatorValue(declaration->fun());
86143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(ContextOperand(rsi, variable->index()), result_register());
862ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      int offset = Context::SlotOffset(variable->index());
863ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      // We know that we have written a function, which is not a smi.
864ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      __ RecordWriteContextSlot(rsi,
865ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com                                offset,
866ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com                                result_register(),
867ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com                                rcx,
868ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com                                kDontSaveFPRegs,
869ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com                                EMIT_REMEMBERED_SET,
870ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com                                OMIT_SMI_CHECK);
871ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
872ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      break;
873ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    }
874ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
875ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    case Variable::LOOKUP: {
876ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      Comment cmnt(masm_, "[ FunctionDeclaration");
877763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rsi);
878ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      __ Push(variable->name());
879ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      __ Push(Smi::FromInt(NONE));
880ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      VisitForStackValue(declaration->fun());
881895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org      __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4);
882ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      break;
883ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    }
884ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  }
885ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com}
886ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
887ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
888ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.comvoid FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
8898e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  Variable* variable = declaration->proxy()->var();
8908e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  ASSERT(variable->location() == Variable::CONTEXT);
8918e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  ASSERT(variable->interface()->IsFrozen());
8928e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
8938e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  Comment cmnt(masm_, "[ ModuleDeclaration");
8948e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  EmitDebugCheckDeclarationContext(variable);
8958e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
8968e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  // Load instance object.
8978e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  __ LoadContext(rax, scope_->ContextChainLength(scope_->GlobalScope()));
89843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, ContextOperand(rax, variable->interface()->Index()));
89943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, ContextOperand(rax, Context::EXTENSION_INDEX));
9008e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
9018e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  // Assign it.
90243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(ContextOperand(rsi, variable->index()), rax);
9038e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  // We know that we have written a module, which is not a smi.
9048e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  __ RecordWriteContextSlot(rsi,
9058e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org                            Context::SlotOffset(variable->index()),
9068e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org                            rax,
9078e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org                            rcx,
9088e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org                            kDontSaveFPRegs,
9098e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org                            EMIT_REMEMBERED_SET,
9108e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org                            OMIT_SMI_CHECK);
9118e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS);
9128e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
9138e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  // Traverse into body.
9148e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  Visit(declaration->module());
915ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com}
916ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
917ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
918ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.comvoid FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) {
919ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  VariableProxy* proxy = declaration->proxy();
920ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  Variable* variable = proxy->var();
921ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  switch (variable->location()) {
922ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    case Variable::UNALLOCATED:
923ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      // TODO(rossberg)
924ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      break;
925ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
926ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    case Variable::CONTEXT: {
927ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      Comment cmnt(masm_, "[ ImportDeclaration");
928ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      EmitDebugCheckDeclarationContext(variable);
929ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      // TODO(rossberg)
930ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      break;
931ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    }
932ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
933ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    case Variable::PARAMETER:
934ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    case Variable::LOCAL:
935ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    case Variable::LOOKUP:
936ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      UNREACHABLE();
937ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  }
938ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com}
939ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
940ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
941ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.comvoid FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
942ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // TODO(rossberg)
943ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com}
944ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
945ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
946b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
947b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Call the runtime to declare the globals.
948763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rsi);  // The context is the first argument.
949b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  __ Push(pairs);
9501805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  __ Push(Smi::FromInt(DeclareGlobalsFlags()));
951895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ CallRuntime(Runtime::kHiddenDeclareGlobals, 3);
952b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Return value is ignored.
953b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
954b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
955b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
9568e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.orgvoid FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) {
9578e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  // Call the runtime to declare the modules.
9588e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  __ Push(descriptions);
959895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ CallRuntime(Runtime::kHiddenDeclareModules, 1);
9608e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  // Return value is ignored.
9618e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org}
9628e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
9638e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org
9649dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.comvoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
9659dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Comment cmnt(masm_, "[ SwitchStatement");
9669dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Breakable nested_statement(this, stmt);
9679dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  SetStatementPosition(stmt);
968d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
9699dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Keep the switch value on the stack until a case matches.
9704a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(stmt->tag());
971d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
9729dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
9739dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ZoneList<CaseClause*>* clauses = stmt->cases();
9749dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
9759dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
9769dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label next_test;  // Recycled for each test.
9779dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Compile all the tests with branches to their bodies.
9789dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  for (int i = 0; i < clauses->length(); i++) {
9799dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    CaseClause* clause = clauses->at(i);
98044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    clause->body_target()->Unuse();
981d218783b5ca3a9706b143874e9372e469f3e6f71fschneider@chromium.org
9829dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    // The default is not a test, but remember it as final fall through.
9839dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    if (clause->is_default()) {
9849dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com      default_clause = clause;
9859dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com      continue;
9869dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    }
9879dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
9889dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    Comment cmnt(masm_, "[ Case comparison");
9899dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    __ bind(&next_test);
9909dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    next_test.Unuse();
9919dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
9929dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    // Compile the label expression.
9934a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    VisitForAccumulatorValue(clause->label());
9949dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
99565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Perform the comparison as if via '==='.
99643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rdx, Operand(rsp, 0));  // Switch value.
997d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
998d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    JumpPatchSite patch_site(masm_);
999d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    if (inline_smi_code) {
100083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label slow_case;
100143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(rcx, rdx);
1002895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org      __ orp(rcx, rax);
100383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
1004d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
10057a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org      __ cmpp(rdx, rax);
100665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      __ j(not_equal, &next_test);
100765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      __ Drop(1);  // Switch value is no longer needed.
100844bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org      __ jmp(clause->body_target());
100965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      __ bind(&slow_case);
101065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    }
10119dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
1012d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    // Record position before stub call for type feedback.
1013d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com    SetSourcePosition(clause->position());
10148432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
1015f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    CallIC(ic, clause->CompareId());
10164f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    patch_site.EmitPatchInfo();
1017d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
10184f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org    Label skip;
10194f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org    __ jmp(&skip, Label::kNear);
10204f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org    PrepareForBailout(clause, TOS_REG);
10214f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
10224f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org    __ j(not_equal, &next_test);
10234f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org    __ Drop(1);
10244f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org    __ jmp(clause->body_target());
10254f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org    __ bind(&skip);
10264f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org
10277a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org    __ testp(rax, rax);
10289dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    __ j(not_equal, &next_test);
10299dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    __ Drop(1);  // Switch value is no longer needed.
103044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    __ jmp(clause->body_target());
10319dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  }
10329dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
10339dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Discard the test value and jump to the default if present, otherwise to
10349dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // the end of the statement.
10359dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&next_test);
10369dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ Drop(1);  // Switch value is no longer needed.
10379dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  if (default_clause == NULL) {
103828a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org    __ jmp(nested_statement.break_label());
10399dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  } else {
104044bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    __ jmp(default_clause->body_target());
10419dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  }
10429dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
10439dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Compile all the case bodies.
10449dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  for (int i = 0; i < clauses->length(); i++) {
10459dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    Comment cmnt(masm_, "[ Case body");
10469dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    CaseClause* clause = clauses->at(i);
104744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org    __ bind(clause->body_target());
10484d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
10499dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    VisitStatements(clause->statements());
10509dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  }
10519dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
105228a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org  __ bind(nested_statement.break_label());
1053d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
10549dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
10559dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
10569dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
10579dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.comvoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
10589dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Comment cmnt(masm_, "[ ForInStatement");
1059f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int slot = stmt->ForInFeedbackSlot();
10609dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  SetStatementPosition(stmt);
10619dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
10629dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label loop, exit;
10639dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ForIn loop_statement(this, stmt);
10649dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  increment_loop_depth();
10659dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
10661fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  // Get the object to enumerate over. If the object is null or undefined, skip
10671fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  // over the loop.  See ECMA-262 version 5, section 12.6.4.
10684a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(stmt->enumerable());
10699dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
10709dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ j(equal, &exit);
10715d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  Register null_value = rdi;
10725d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  __ LoadRoot(null_value, Heap::kNullValueRootIndex);
10737a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ cmpp(rax, null_value);
10749dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ j(equal, &exit);
10759dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
1076be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
1077be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org
10789dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Convert the object to a JS object.
10799dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label convert, done_convert;
10809dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ JumpIfSmi(rax, &convert);
1081d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org  __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
10829dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ j(above_equal, &done_convert);
10839dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&convert);
1084763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rax);
10859dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
10869dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&done_convert);
1087763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rax);
10889dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
1089394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Check for proxies.
1090394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Label call_runtime;
1091394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1092394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx);
1093394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ j(below_equal, &call_runtime);
1094394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
10955d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // Check cache validity in generated code. This is a fast case for
10965d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
10975d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // guarantee cache validity, call the runtime system to check cache
10985d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // validity or get the property names in a fixed array.
1099be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  __ CheckEnumCache(null_value, &call_runtime);
11005d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org
11015d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // The enum cache is valid.  Load the map of the object being
11025d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // iterated over and use the cache for the iteration.
110383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label use_cache;
110443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
110583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ jmp(&use_cache, Label::kNear);
11069dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
11079dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Get the set of properties to enumerate.
11085d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  __ bind(&call_runtime);
1109763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rax);  // Duplicate the enumerable object on the stack.
11109dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
11119dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
11129dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // If we got a map from the runtime call, we can do a fast
11139dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // modification check. Otherwise, we got a fixed array, and we have
11149dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // to do a slow check.
111583a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label fixed_array;
11169dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
11179dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                 Heap::kMetaMapRootIndex);
1118355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  __ j(not_equal, &fixed_array);
11199dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
11209dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // We got a map in register rax. Get the enumeration cache from it.
11215d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  __ bind(&use_cache);
1122355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
1123355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  Label no_descriptors;
1124355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
1125355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  __ EnumLength(rdx, rax);
1126355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  __ Cmp(rdx, Smi::FromInt(0));
1127355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  __ j(equal, &no_descriptors);
1128355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
112940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org  __ LoadInstanceDescriptors(rax, rcx);
113043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheOffset));
113143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
11329dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
1133f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // Set up the four remaining stack slots.
1134763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rax);  // Map.
1135763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rcx);  // Enumeration cache.
1136763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rdx);  // Number of valid entries for the map in the enum cache.
11379dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ Push(Smi::FromInt(0));  // Initial index.
11389dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ jmp(&loop);
11399dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
1140355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  __ bind(&no_descriptors);
1141fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  __ addp(rsp, Immediate(kPointerSize));
1142355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  __ jmp(&exit);
1143355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
11449dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // We got a fixed array in register rax. Iterate through that.
1145394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Label non_proxy;
11469dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&fixed_array);
11479a21ec41a2007f01ba18cf5fa48f7987e40e5109ulan@chromium.org
1148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // No need for a write barrier, we are storing a Smi in the feedback vector.
1149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  __ Move(rbx, FeedbackVector());
1150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  __ Move(FieldOperand(rbx, FixedArray::OffsetOfElementAt(slot)),
1151a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org          TypeFeedbackInfo::MegamorphicSentinel(isolate()));
1152394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ Move(rbx, Smi::FromInt(1));  // Smi indicates slow check
115343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rcx, Operand(rsp, 0 * kPointerSize));  // Get enumerated object
1154394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1155394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx);
1156394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ j(above, &non_proxy);
1157394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ Move(rbx, Smi::FromInt(0));  // Zero indicates proxy
1158394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ bind(&non_proxy);
1159763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rbx);  // Smi
1160763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rax);  // Array
116143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, FieldOperand(rax, FixedArray::kLengthOffset));
1162763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rax);  // Fixed array length (as smi).
11639dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ Push(Smi::FromInt(0));  // Initial index.
11649dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
11659dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Generate code for doing the condition check.
1166be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
11679dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&loop);
116843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, Operand(rsp, 0 * kPointerSize));  // Get the current index.
11697a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ cmpp(rax, Operand(rsp, 1 * kPointerSize));  // Compare to the array length.
117028a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org  __ j(above_equal, loop_statement.break_label());
11719dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
11729dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Get the current entry of the array into register rbx.
117343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rbx, Operand(rsp, 2 * kPointerSize));
1174eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2);
117543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rbx, FieldOperand(rbx,
11769dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                            index.reg,
11779dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                            index.scale,
11789dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                            FixedArray::kHeaderSize));
11799dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
1180394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Get the expected map from the stack or a smi in the
11819dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // permanent slow case into register rdx.
118243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdx, Operand(rsp, 3 * kPointerSize));
11839dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
11849dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Check if the expected map still matches that of the enumerable.
1185394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // If not, we may have to filter the key.
118683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label update_each;
118743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rcx, Operand(rsp, 4 * kPointerSize));
11887a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ cmpp(rdx, FieldOperand(rcx, HeapObject::kMapOffset));
118983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(equal, &update_each, Label::kNear);
11909dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
1191394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // For proxies, no filtering is done.
1192394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
1193394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ Cmp(rdx, Smi::FromInt(0));
1194394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  __ j(equal, &update_each, Label::kNear);
1195394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
11969dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Convert the entry to a string or null if it isn't a property
11979dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // anymore. If the property has been removed while iterating, we
11989dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // just skip it.
1199763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rcx);  // Enumerable.
1200763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rbx);  // Current entry.
12019dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1202badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  __ Cmp(rax, Smi::FromInt(0));
120328a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org  __ j(equal, loop_statement.continue_label());
120443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rbx, rax);
12059dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
12069dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Update the 'each' property or variable from the possibly filtered
12079dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // entry in register rbx.
12089dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&update_each);
120943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(result_register(), rbx);
12109dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Perform the assignment as if via '='.
12115f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  { EffectContext context(this);
1212be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org    EmitAssignment(stmt->each());
12135f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  }
12149dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
12159dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Generate code for the body of the loop.
12169dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Visit(stmt->body());
12179dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
12189dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Generate code for going to the next element by incrementing the
12199dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // index (smi) stored on top of the stack.
122028a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org  __ bind(loop_statement.continue_label());
12219dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1));
12229dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
1223cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org  EmitBackEdgeBookkeeping(stmt, &loop);
1224a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ jmp(&loop);
12259dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
12269dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Remove the pointers stored on the stack.
122728a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org  __ bind(loop_statement.break_label());
1228fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  __ addp(rsp, Immediate(5 * kPointerSize));
12299dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
12309dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Exit and decrement the loop depth.
1231be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.org  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
12329dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&exit);
12339dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  decrement_loop_depth();
12349dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
1235b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1236b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
12371fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.orgvoid FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
12381fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  Comment cmnt(masm_, "[ ForOfStatement");
12391fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  SetStatementPosition(stmt);
12401fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
12411fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  Iteration loop_statement(this, stmt);
12421fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  increment_loop_depth();
12431fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
12441845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  // var iterable = subject
12451845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  VisitForAccumulatorValue(stmt->assign_iterable());
12461fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
12471845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  // As with for-in, skip the loop if the iterable is null or undefined.
12481fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
12491fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  __ j(equal, loop_statement.break_label());
12501fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  __ CompareRoot(rax, Heap::kNullValueRootIndex);
12511fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  __ j(equal, loop_statement.break_label());
12521fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
12531845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  // var iterator = iterable[Symbol.iterator]();
12541845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  VisitForEffect(stmt->assign_iterator());
12551fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
12561fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  // Loop entry.
12571fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  __ bind(loop_statement.continue_label());
12581fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
12591fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  // result = iterator.next()
12601fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  VisitForEffect(stmt->next_result());
12611fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
12621fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  // if (result.done) break;
12631fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  Label result_not_done;
12641fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  VisitForControl(stmt->result_done(),
12651fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org                  loop_statement.break_label(),
12661fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org                  &result_not_done,
12671fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org                  &result_not_done);
12681fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  __ bind(&result_not_done);
12691fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
12701fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  // each = result.value
12711fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  VisitForEffect(stmt->assign_each());
12721fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
12731fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  // Generate code for the body of the loop.
12741fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  Visit(stmt->body());
12751fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
12761fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  // Check stack before looping.
12771fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
12781fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
12791fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  __ jmp(loop_statement.continue_label());
12801fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
12811fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  // Exit and decrement the loop depth.
12821fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
12831fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  __ bind(loop_statement.break_label());
12841fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  decrement_loop_depth();
12851fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org}
12861fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
12871fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
128821b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.orgvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
128921b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org                                       bool pretenure) {
12909dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Use the fast case closure allocation code that allocates in new
12915d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // space for nested functions that don't need literals cloning. If
12925d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // we're running with the --always-opt or the --prepare-always-opt
12935d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // flag, we need to use the runtime function so that the new function
12945d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // we are creating here gets a chance to have its code optimized and
12955d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // doesn't just get a copy of the existing unoptimized code.
12965d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  if (!FLAG_always_opt &&
12975d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org      !FLAG_prepare_always_opt &&
1298ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      !pretenure &&
12995d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org      scope()->is_function_scope() &&
1300ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      info->num_literals() == 0) {
1301f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org    FastNewClosureStub stub(isolate(),
1302f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org                            info->strict_mode(),
1303f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org                            info->is_generator());
1304662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org    __ Move(rbx, info);
13059dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    __ CallStub(&stub);
13069dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  } else {
1307763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(rsi);
13089dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    __ Push(info);
1309ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    __ Push(pretenure
1310ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org            ? isolate()->factory()->true_value()
1311ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org            : isolate()->factory()->false_value());
1312895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    __ CallRuntime(Runtime::kHiddenNewClosure, 3);
13139dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  }
13144a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
1315b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
1316b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1317b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1318b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
1319b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Comment cmnt(masm_, "[ VariableProxy");
1320030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.org  EmitVariableLoad(expr);
1321b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
1322b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1323b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1324486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.orgvoid FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
1325486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org                                                      TypeofState typeof_state,
1326486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org                                                      Label* slow) {
13272ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  Register context = rsi;
13282ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  Register temp = rdx;
13292ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
13302ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  Scope* s = scope();
13312ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  while (s != NULL) {
13322ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    if (s->num_heap_slots() > 0) {
1333486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      if (s->calls_sloppy_eval()) {
13342ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org        // Check that extension is NULL.
13357a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org        __ cmpp(ContextOperand(context, Context::EXTENSION_INDEX),
13362ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org                Immediate(0));
13372ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org        __ j(not_equal, slow);
13382ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      }
13392ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      // Load next context in chain.
134043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
13412ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      // Walk the rest of the chain without clobbering rsi.
13422ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      context = temp;
13432ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    }
13442ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    // If no outer scope calls eval, we do not need to check more
13452ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    // context extensions.  If we have reached an eval scope, we check
13462ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    // all extensions from this point.
1347486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
13482ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    s = s->outer_scope();
13492ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  }
13502ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
13512ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  if (s != NULL && s->is_eval_scope()) {
13522ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    // Loop up the context chain.  There is no frame effect so it is
13532ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    // safe to use raw labels here.
135483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    Label next, fast;
13552ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    if (!context.is(temp)) {
135643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(temp, context);
13572ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    }
13582ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    // Load map for comparison into register, outside loop.
135946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    __ LoadRoot(kScratchRegister, Heap::kNativeContextMapRootIndex);
13602ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    __ bind(&next);
136146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    // Terminate at native context.
13627a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org    __ cmpp(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset));
136383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org    __ j(equal, &fast, Label::kNear);
13642ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    // Check that extension is NULL.
13657a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org    __ cmpp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
13662ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    __ j(not_equal, slow);
13672ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    // Load next context in chain.
136843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(temp, ContextOperand(temp, Context::PREVIOUS_INDEX));
13692ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    __ jmp(&next);
13702ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    __ bind(&fast);
13712ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  }
13722ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
13732ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  // All extension objects were empty and it is safe to use a global
13742ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  // load IC call.
137543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, GlobalObjectOperand());
1376486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  __ Move(rcx, var->name());
13779cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
13789cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org      ? NOT_CONTEXTUAL
13799cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org      : CONTEXTUAL;
13809cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  CallLoadIC(mode);
13812ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org}
13822ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
13832ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
1384486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.orgMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1385486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org                                                                Label* slow) {
1386486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  ASSERT(var->IsContextSlot());
13872ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  Register context = rsi;
13882ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  Register temp = rbx;
13892ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
1390486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
13912ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    if (s->num_heap_slots() > 0) {
1392486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      if (s->calls_sloppy_eval()) {
13932ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org        // Check that extension is NULL.
13947a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org        __ cmpp(ContextOperand(context, Context::EXTENSION_INDEX),
13952ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org                Immediate(0));
13962ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org        __ j(not_equal, slow);
13972ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      }
139843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
13992ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      // Walk the rest of the chain without clobbering rsi.
14002ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org      context = temp;
14012ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    }
14022ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  }
14032ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  // Check that last extension is NULL.
14047a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ cmpp(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
14052ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  __ j(not_equal, slow);
14065d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org
14075d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // This function is used only for loads, not stores, so it's safe to
14085d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // return an rsi-based operand (the write barrier cannot be allowed to
14095d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org  // destroy the rsi register).
1410486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  return ContextOperand(context, var->index());
14112ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org}
14122ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
14132ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
1414486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.orgvoid FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
1415486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org                                                  TypeofState typeof_state,
1416486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org                                                  Label* slow,
1417486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org                                                  Label* done) {
14182ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  // Generate fast-case code for variables that might be shadowed by
14192ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  // eval-introduced variables.  Eval is used a lot without
14202ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  // introducing variables.  In those cases, we do not want to
14212ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  // perform a runtime call for all variables in the scope
14222ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  // containing the eval.
1423b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  if (var->mode() == DYNAMIC_GLOBAL) {
1424486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
14252ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    __ jmp(done);
1426b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  } else if (var->mode() == DYNAMIC_LOCAL) {
1427486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    Variable* local = var->local_if_not_shadowed();
142843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rax, ContextSlotOperandCheckExtensions(local, slow));
1429486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    if (local->mode() == LET || local->mode() == CONST ||
1430486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        local->mode() == CONST_LEGACY) {
1431486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1432486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      __ j(not_equal, done);
1433486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      if (local->mode() == CONST_LEGACY) {
1434a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org        __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1435486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      } else {  // LET || CONST
1436a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org        __ Push(var->name());
1437895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org        __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1);
1438a8bb4d938869bdcdf759625ee868775ff24826d9svenpanne@chromium.org      }
14392ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    }
1440486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    __ jmp(done);
14412ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org  }
14422ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org}
14432ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
14442ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
1445030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.orgvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
1446030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.org  // Record position before possible IC call.
1447030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.org  SetSourcePosition(proxy->position());
1448030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.org  Variable* var = proxy->var();
1449030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.org
1450486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // Three cases: global variables, lookup variables, and all other types of
1451486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // variables.
1452486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  switch (var->location()) {
1453486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    case Variable::UNALLOCATED: {
1454f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      Comment cmnt(masm_, "[ Global variable");
1455486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      // Use inline caching. Variable name is passed in rcx and the global
1456486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      // object on the stack.
1457486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      __ Move(rcx, var->name());
145843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(rax, GlobalObjectOperand());
14599cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org      CallLoadIC(CONTEXTUAL);
1460486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      context()->Plug(rax);
1461486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      break;
1462486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    }
14632ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
1464486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    case Variable::PARAMETER:
1465486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    case Variable::LOCAL:
1466486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    case Variable::CONTEXT: {
1467f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot"
1468f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                               : "[ Stack slot");
1469c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org      if (var->binding_needs_init()) {
1470c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // var->scope() may be NULL when the proxy is located in eval code and
1471c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // refers to a potential outside binding. Currently those bindings are
1472c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // always looked up dynamically, i.e. in that case
1473c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        //     var->location() == LOOKUP.
1474c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // always holds.
1475c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        ASSERT(var->scope() != NULL);
1476c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org
1477c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // Check if the binding really needs an initialization check. The check
1478c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // can be skipped in the following situation: we have a LET or CONST
1479c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // binding in harmony mode, both the Variable and the VariableProxy have
1480c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // the same declaration scope (i.e. they are both in global code, in the
1481c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // same function or in the same eval code) and the VariableProxy is in
1482c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // the source physically located after the initializer of the variable.
1483c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        //
1484c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // We cannot skip any initialization checks for CONST in non-harmony
1485c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // mode because const variables may be declared but never initialized:
1486c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        //   if (false) { const x; }; var y = x;
1487c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        //
1488c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // The condition on the declaration scopes is a conservative check for
1489c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // nested functions that access a binding and are called before the
1490c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        // binding is initialized:
1491c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        //   function() { f(); let x = 1; function f() { x = 2; } }
1492c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        //
1493c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        bool skip_init_check;
1494c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
1495c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          skip_init_check = false;
1496ac45fedf88208de9636b896863f0942bae969d67jkummerow@chromium.org        } else {
1497c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          // Check that we always have valid source position.
1498c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
1499c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          ASSERT(proxy->position() != RelocInfo::kNoPosition);
1500486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org          skip_init_check = var->mode() != CONST_LEGACY &&
1501c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org              var->initializer_position() < proxy->position();
1502c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        }
1503c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org
1504c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org        if (!skip_init_check) {
1505c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          // Let and const need a read barrier.
1506c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          Label done;
1507c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          GetVar(rax, var);
1508c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1509c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          __ j(not_equal, &done, Label::kNear);
1510486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org          if (var->mode() == LET || var->mode() == CONST) {
1511c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org            // Throw a reference error when using an uninitialized let/const
1512c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org            // binding in harmony mode.
1513c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org            __ Push(var->name());
1514895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org            __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1);
1515c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          } else {
1516c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org            // Uninitalized const bindings outside of harmony mode are unholed.
1517486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org            ASSERT(var->mode() == CONST_LEGACY);
1518c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org            __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1519c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          }
1520c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          __ bind(&done);
1521c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          context()->Plug(rax);
1522c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          break;
1523486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org        }
1524486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      }
1525c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org      context()->Plug(var);
1526486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      break;
1527486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    }
1528b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1529486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    case Variable::LOOKUP: {
1530f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      Comment cmnt(masm_, "[ Lookup slot");
1531486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      Label done, slow;
1532486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      // Generate code for loading from variables potentially shadowed
1533486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      // by eval-introduced variables.
1534486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
1535486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      __ bind(&slow);
1536763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rsi);  // Context.
153780c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org      __ Push(var->name());
1538895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org      __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2);
153980c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org      __ bind(&done);
154080c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org      context()->Plug(rax);
1541486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      break;
15429dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    }
1543b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
1544b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
1545b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1546b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1547b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1548b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Comment cmnt(masm_, "[ RegExpLiteral");
1549c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  Label materialized;
1550b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Registers will be used as follows:
1551b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // rdi = JS function.
1552c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  // rcx = literals array.
1553c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  // rbx = regexp literal.
1554c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  // rax = regexp literal clone.
155543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
155643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
1557b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  int literal_offset =
155865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
155943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rbx, FieldOperand(rcx, literal_offset));
1560c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
1561486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  __ j(not_equal, &materialized, Label::kNear);
1562c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org
1563b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Create regexp literal using runtime function
1564b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Result will be in rax.
1565763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rcx);
1566b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  __ Push(Smi::FromInt(expr->literal_index()));
1567b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  __ Push(expr->pattern());
1568b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  __ Push(expr->flags());
1569895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4);
157043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rbx, rax);
1571c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org
1572c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  __ bind(&materialized);
1573c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1574c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  Label allocated, runtime_allocate;
15752bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org  __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
1576c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  __ jmp(&allocated);
1577c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org
1578c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  __ bind(&runtime_allocate);
1579763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rbx);
1580c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  __ Push(Smi::FromInt(size));
1581895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1);
1582763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rbx);
1583c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org
1584c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  __ bind(&allocated);
1585c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  // Copy the content into the newly allocated memory.
1586c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  // (Unroll copy loop once for better throughput).
1587c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
158843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rdx, FieldOperand(rbx, i));
158943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rcx, FieldOperand(rbx, i + kPointerSize));
159043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(FieldOperand(rax, i), rdx);
159143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(FieldOperand(rax, i + kPointerSize), rcx);
1592c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  }
1593c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  if ((size % (2 * kPointerSize)) != 0) {
159443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rdx, FieldOperand(rbx, size - kPointerSize));
159543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(FieldOperand(rax, size - kPointerSize), rdx);
1596c4e51ac6d26b42753a57a4a9e4a419243b50151clrn@chromium.org  }
15974a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
1598b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
1599b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1600b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
16012c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.orgvoid FullCodeGenerator::EmitAccessor(Expression* expression) {
16022c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org  if (expression == NULL) {
16032c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org    __ PushRoot(Heap::kNullValueRootIndex);
16042c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org  } else {
16052c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org    VisitForStackValue(expression);
16062c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org  }
16072c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org}
16082c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org
16092c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org
1610b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1611b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Comment cmnt(masm_, "[ ObjectLiteral");
1612e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org
16137ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  expr->BuildConstantProperties(isolate());
1614f8c6bd531c2a8ba717cb8d316206347b05acebedmstarzinger@chromium.org  Handle<FixedArray> constant_properties = expr->constant_properties();
1615ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  int flags = expr->fast_elements()
1616ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ? ObjectLiteral::kFastElements
1617ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      : ObjectLiteral::kNoFlags;
1618ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  flags |= expr->has_function()
1619ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ? ObjectLiteral::kHasFunction
1620ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      : ObjectLiteral::kNoFlags;
1621f8c6bd531c2a8ba717cb8d316206347b05acebedmstarzinger@chromium.org  int properties_count = constant_properties->length() / 2;
1622a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  if (expr->may_store_doubles() || expr->depth() > 1 ||
1623874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org      masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements ||
1624f8c6bd531c2a8ba717cb8d316206347b05acebedmstarzinger@chromium.org      properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
162543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1626763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
162771fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org    __ Push(Smi::FromInt(expr->literal_index()));
162871fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org    __ Push(constant_properties);
162971fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org    __ Push(Smi::FromInt(flags));
1630895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    __ CallRuntime(Runtime::kHiddenCreateObjectLiteral, 4);
1631f8c6bd531c2a8ba717cb8d316206347b05acebedmstarzinger@chromium.org  } else {
163243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
163343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rax, FieldOperand(rdi, JSFunction::kLiteralsOffset));
163471fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org    __ Move(rbx, Smi::FromInt(expr->literal_index()));
163571fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org    __ Move(rcx, constant_properties);
163671fc3467b5396c27d0b701d88e196e88c78d8864mstarzinger@chromium.org    __ Move(rdx, Smi::FromInt(flags));
1637f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org    FastCloneShallowObjectStub stub(isolate(), properties_count);
1638f8c6bd531c2a8ba717cb8d316206347b05acebedmstarzinger@chromium.org    __ CallStub(&stub);
1639b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
1640b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1641b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // If result_saved is true the result is on top of the stack.  If
1642b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // result_saved is false the result is in rax.
1643b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  bool result_saved = false;
1644b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1645e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  // Mark all computed expressions that are bound to a key that
1646e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  // is shadowed by a later occurrence of the same key. For the
1647e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  // marked expressions, no store code is emitted.
16487028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  expr->CalculateEmitStore(zone());
1649e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org
16505a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  AccessorTable accessor_table(zone());
1651b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  for (int i = 0; i < expr->properties()->length(); i++) {
1652b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    ObjectLiteral::Property* property = expr->properties()->at(i);
1653b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    if (property->IsCompileTimeValue()) continue;
1654b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1655b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    Literal* key = property->key();
1656b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    Expression* value = property->value();
1657b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    if (!result_saved) {
1658763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);  // Save result on the stack
1659b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      result_saved = true;
1660b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
1661b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    switch (property->kind()) {
1662b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      case ObjectLiteral::Property::CONSTANT:
1663b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        UNREACHABLE();
1664b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1665b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1666b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        // Fall through.
1667b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      case ObjectLiteral::Property::COMPUTED:
16681510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org        if (key->value()->IsInternalizedString()) {
1669e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org          if (property->emit_store()) {
167040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org            VisitForAccumulatorValue(value);
16711510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org            __ Move(rcx, key->value());
167243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org            __ movp(rdx, Operand(rsp, 0));
1673f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            CallStoreIC(key->LiteralFeedbackId());
1674d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org            PrepareForBailoutForId(key->id(), NO_REGISTERS);
167540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org          } else {
167640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org            VisitForEffect(value);
1677e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org          }
1678b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org          break;
1679b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        }
1680763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org        __ Push(Operand(rsp, 0));  // Duplicate receiver.
16814a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        VisitForStackValue(key);
16824a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        VisitForStackValue(value);
1683e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org        if (property->emit_store()) {
16849ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          __ Push(Smi::FromInt(NONE));    // PropertyAttributes
16859ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          __ CallRuntime(Runtime::kSetProperty, 4);
1686e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org        } else {
1687e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org          __ Drop(3);
1688e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org        }
1689b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        break;
1690750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org      case ObjectLiteral::Property::PROTOTYPE:
1691763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org        __ Push(Operand(rsp, 0));  // Duplicate receiver.
1692750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org        VisitForStackValue(value);
1693750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org        if (property->emit_store()) {
1694750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org          __ CallRuntime(Runtime::kSetPrototype, 2);
1695750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org        } else {
1696750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org          __ Drop(2);
1697750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org        }
1698750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org        break;
1699b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      case ObjectLiteral::Property::GETTER:
17002c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org        accessor_table.lookup(key)->second->getter = value;
17012c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org        break;
17022c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org      case ObjectLiteral::Property::SETTER:
17032c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org        accessor_table.lookup(key)->second->setter = value;
1704b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        break;
1705b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
1706b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
1707b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
17082c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org  // Emit code to define accessors, using only a single call to the runtime for
17092c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org  // each pair of corresponding getters and setters.
17102c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org  for (AccessorTable::Iterator it = accessor_table.begin();
17112c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org       it != accessor_table.end();
17122c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org       ++it) {
1713763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(Operand(rsp, 0));  // Duplicate receiver.
17142c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org    VisitForStackValue(it->first);
17152c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org    EmitAccessor(it->second->getter);
17162c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org    EmitAccessor(it->second->setter);
17172c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org    __ Push(Smi::FromInt(NONE));
17182c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org    __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
17192c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org  }
17202c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org
1721ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (expr->has_function()) {
1722ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    ASSERT(result_saved);
1723763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(Operand(rsp, 0));
1724ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    __ CallRuntime(Runtime::kToFastProperties, 1);
1725ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  }
1726ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
1727b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  if (result_saved) {
17284a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    context()->PlugTOS();
1729b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  } else {
17304a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    context()->Plug(rax);
1731b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
1732b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
1733b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1734b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1735b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1736b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Comment cmnt(masm_, "[ ArrayLiteral");
17379dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
17387ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org  expr->BuildConstantElements(isolate());
173937be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org  int flags = expr->depth() == 1
174037be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org      ? ArrayLiteral::kShallowElements
174137be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org      : ArrayLiteral::kNoFlags;
174237be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org
17439dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ZoneList<Expression*>* subexprs = expr->values();
17449dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  int length = subexprs->length();
1745394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Handle<FixedArray> constant_elements = expr->constant_elements();
1746394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  ASSERT_EQ(2, constant_elements->length());
1747394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  ElementsKind constant_elements_kind =
1748394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1749830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org  bool has_constant_fast_elements =
1750830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org      IsFastObjectElementsKind(constant_elements_kind);
1751394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Handle<FixedArrayBase> constant_elements_values(
1752394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      FixedArrayBase::cast(constant_elements->get(1)));
17539dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
17549cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1755c86e8c29eea534916f0d6a2a285b65a86d1b3b67machenbach@chromium.org  if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
1756c86e8c29eea534916f0d6a2a285b65a86d1b3b67machenbach@chromium.org    // If the only customer of allocation sites is transitioning, then
1757c86e8c29eea534916f0d6a2a285b65a86d1b3b67machenbach@chromium.org    // we can turn it off if we don't have anywhere else to transition to.
1758c86e8c29eea534916f0d6a2a285b65a86d1b3b67machenbach@chromium.org    allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1759c86e8c29eea534916f0d6a2a285b65a86d1b3b67machenbach@chromium.org  }
1760c86e8c29eea534916f0d6a2a285b65a86d1b3b67machenbach@chromium.org
1761e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
176243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1763763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
1764e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ Push(Smi::FromInt(expr->literal_index()));
1765e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ Push(constant_elements);
176637be408adf363bbe682921a4a690752fa0ec33femachenbach@chromium.org    __ Push(Smi::FromInt(flags));
1767895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    __ CallRuntime(Runtime::kHiddenCreateArrayLiteral, 4);
17689dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  } else {
176943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
177043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rax, FieldOperand(rbx, JSFunction::kLiteralsOffset));
1771e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ Move(rbx, Smi::FromInt(expr->literal_index()));
1772e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ Move(rcx, constant_elements);
1773a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org    FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
17749dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    __ CallStub(&stub);
1775b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
1776b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1777b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  bool result_saved = false;  // Is the result saved to the stack?
1778b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1779b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Emit code to evaluate all the non-constant subexpressions and to store
1780b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // them into the newly cloned array.
17819dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  for (int i = 0; i < length; i++) {
1782b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    Expression* subexpr = subexprs->at(i);
1783b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    // If the subexpression is a literal or a simple materialized literal it
1784b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    // is already set in the cloned array.
17851510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1786b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1787b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    if (!result_saved) {
1788763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);  // array literal
1789b752d4061aaeb7d6a6ec368607871789d54b0207dslomov@chromium.org      __ Push(Smi::FromInt(expr->literal_index()));
1790b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      result_saved = true;
1791b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
17924a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    VisitForAccumulatorValue(subexpr);
1793b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1794830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org    if (IsFastObjectElementsKind(constant_elements_kind)) {
1795830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org      // Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
1796830d30c478be03b0ac560f4002833ab141e41effsvenpanne@chromium.org      // cannot transition and don't need to call the runtime stub.
17971b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      int offset = FixedArray::kHeaderSize + (i * kPointerSize);
179843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(rbx, Operand(rsp, kPointerSize));  // Copy of array literal.
179943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
18001b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      // Store the subexpression value in the array's elements.
180143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(FieldOperand(rbx, offset), result_register());
18021b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      // Update the write barrier for the array store.
18031b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      __ RecordWriteField(rbx, offset, result_register(), rcx,
18041b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                          kDontSaveFPRegs,
18051b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                          EMIT_REMEMBERED_SET,
18061b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                          INLINE_SMI_CHECK);
18071b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    } else {
18081b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      // Store the subexpression value in the array's elements.
18091b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      __ Move(rcx, Smi::FromInt(i));
1810f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org      StoreArrayLiteralElementStub stub(isolate());
18111b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      __ CallStub(&stub);
18121b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    }
1813d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
1814d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
1815b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
1816b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1817b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  if (result_saved) {
1818fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    __ addp(rsp, Immediate(kPointerSize));  // literal index
18194a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    context()->PlugTOS();
1820b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  } else {
18214a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    context()->Plug(rax);
1822b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
1823b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
1824b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
1825b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
18265c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid FullCodeGenerator::VisitAssignment(Assignment* expr) {
18274edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org  ASSERT(expr->target()->IsValidReferenceExpression());
18282904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org
18295c838251403b0be9a882540f1922577abba4c872ager@chromium.org  Comment cmnt(masm_, "[ Assignment");
18309dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
18315c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Left-hand side can only be a property, a global or a (parameter or local)
18327b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // slot.
18335c838251403b0be9a882540f1922577abba4c872ager@chromium.org  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
18345c838251403b0be9a882540f1922577abba4c872ager@chromium.org  LhsKind assign_type = VARIABLE;
1835d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  Property* property = expr->target()->AsProperty();
1836d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  if (property != NULL) {
1837d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    assign_type = (property->key()->IsPropertyName())
1838d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org        ? NAMED_PROPERTY
1839d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org        : KEYED_PROPERTY;
18405c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
18415c838251403b0be9a882540f1922577abba4c872ager@chromium.org
18425c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Evaluate LHS expression.
18435c838251403b0be9a882540f1922577abba4c872ager@chromium.org  switch (assign_type) {
18445c838251403b0be9a882540f1922577abba4c872ager@chromium.org    case VARIABLE:
18455c838251403b0be9a882540f1922577abba4c872ager@chromium.org      // Nothing to do here.
18465c838251403b0be9a882540f1922577abba4c872ager@chromium.org      break;
18475c838251403b0be9a882540f1922577abba4c872ager@chromium.org    case NAMED_PROPERTY:
18485c838251403b0be9a882540f1922577abba4c872ager@chromium.org      if (expr->is_compound()) {
18495c838251403b0be9a882540f1922577abba4c872ager@chromium.org        // We need the receiver both on the stack and in the accumulator.
18504a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        VisitForAccumulatorValue(property->obj());
1851763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org        __ Push(result_register());
18525c838251403b0be9a882540f1922577abba4c872ager@chromium.org      } else {
18534a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        VisitForStackValue(property->obj());
18545c838251403b0be9a882540f1922577abba4c872ager@chromium.org      }
18555c838251403b0be9a882540f1922577abba4c872ager@chromium.org      break;
1856d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    case KEYED_PROPERTY: {
18579dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com      if (expr->is_compound()) {
18587b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org        VisitForStackValue(property->obj());
18597b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org        VisitForAccumulatorValue(property->key());
186043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org        __ movp(rdx, Operand(rsp, 0));
1861763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org        __ Push(rax);
18629dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com      } else {
18637b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org        VisitForStackValue(property->obj());
18647b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org        VisitForStackValue(property->key());
18659dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com      }
18665c838251403b0be9a882540f1922577abba4c872ager@chromium.org      break;
1867d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    }
18685c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
18695c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1870c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // For compound assignments we need another deoptimization point after the
1871c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // variable/property load.
18725c838251403b0be9a882540f1922577abba4c872ager@chromium.org  if (expr->is_compound()) {
18734a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    { AccumulatorValueContext context(this);
18744a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      switch (assign_type) {
18754a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        case VARIABLE:
1876030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.org          EmitVariableLoad(expr->target()->AsVariableProxy());
1877c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org          PrepareForBailout(expr->target(), TOS_REG);
18784a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          break;
18794a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        case NAMED_PROPERTY:
18804a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          EmitNamedPropertyLoad(property);
1881471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org          PrepareForBailoutForId(property->LoadId(), TOS_REG);
18824a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          break;
18834a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        case KEYED_PROPERTY:
18844a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          EmitKeyedPropertyLoad(property);
1885471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org          PrepareForBailoutForId(property->LoadId(), TOS_REG);
18864a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          break;
18874a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      }
18885c838251403b0be9a882540f1922577abba4c872ager@chromium.org    }
18895c838251403b0be9a882540f1922577abba4c872ager@chromium.org
1890d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    Token::Value op = expr->binary_op();
1891763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(rax);  // Left operand goes on the stack.
18929ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    VisitForAccumulatorValue(expr->value());
18935c838251403b0be9a882540f1922577abba4c872ager@chromium.org
189465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
189565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org        ? OVERWRITE_RIGHT
189665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org        : NO_OVERWRITE;
1897d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    SetSourcePosition(expr->position() + 1);
18984a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    AccumulatorValueContext context(this);
1899d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    if (ShouldInlineSmiCase(op)) {
19008e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org      EmitInlineSmiBinaryOp(expr->binary_operation(),
1901d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org                            op,
1902d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org                            mode,
1903d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org                            expr->target(),
19049ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org                            expr->value());
1905d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    } else {
19068e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org      EmitBinaryOp(expr->binary_operation(), op, mode);
1907d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    }
1908d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    // Deoptimization point in case the binary operation may have side effects.
1909d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    PrepareForBailout(expr->binary_operation(), TOS_REG);
1910d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  } else {
19114a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    VisitForAccumulatorValue(expr->value());
19125c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
19135c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19145c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Record source position before possible IC call.
19155c838251403b0be9a882540f1922577abba4c872ager@chromium.org  SetSourcePosition(expr->position());
19165c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19175c838251403b0be9a882540f1922577abba4c872ager@chromium.org  // Store the value.
19185c838251403b0be9a882540f1922577abba4c872ager@chromium.org  switch (assign_type) {
19195c838251403b0be9a882540f1922577abba4c872ager@chromium.org    case VARIABLE:
19205c838251403b0be9a882540f1922577abba4c872ager@chromium.org      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
19214a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                             expr->op());
1922d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
19235f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org      context()->Plug(rax);
19245c838251403b0be9a882540f1922577abba4c872ager@chromium.org      break;
19255c838251403b0be9a882540f1922577abba4c872ager@chromium.org    case NAMED_PROPERTY:
19265c838251403b0be9a882540f1922577abba4c872ager@chromium.org      EmitNamedPropertyAssignment(expr);
19275c838251403b0be9a882540f1922577abba4c872ager@chromium.org      break;
19285c838251403b0be9a882540f1922577abba4c872ager@chromium.org    case KEYED_PROPERTY:
19295c838251403b0be9a882540f1922577abba4c872ager@chromium.org      EmitKeyedPropertyAssignment(expr);
19305c838251403b0be9a882540f1922577abba4c872ager@chromium.org      break;
19315c838251403b0be9a882540f1922577abba4c872ager@chromium.org  }
19325c838251403b0be9a882540f1922577abba4c872ager@chromium.org}
19335c838251403b0be9a882540f1922577abba4c872ager@chromium.org
19345c838251403b0be9a882540f1922577abba4c872ager@chromium.org
193577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.orgvoid FullCodeGenerator::VisitYield(Yield* expr) {
193677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  Comment cmnt(masm_, "[ Yield");
193777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  // Evaluate yielded value first; the initial iterator definition depends on
193877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  // this.  It stays on the stack while we update the iterator.
193977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  VisitForStackValue(expr->expression());
194077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
194177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  switch (expr->yield_kind()) {
194241728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    case Yield::SUSPEND:
194341728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      // Pop value from top-of-stack slot; box result into result register.
194441728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      EmitCreateIteratorResult(false);
1945763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(result_register());
194641728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      // Fall through.
194741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    case Yield::INITIAL: {
19481510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      Label suspend, continuation, post_runtime, resume;
19491510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
19501510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ jmp(&suspend);
19511510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
19521510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ bind(&continuation);
19531510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ jmp(&resume);
19541510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org
19551510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ bind(&suspend);
19561510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      VisitForAccumulatorValue(expr->generator_object());
19571510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
19581510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset),
19591510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org              Smi::FromInt(continuation.pos()));
196043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi);
196143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(rcx, rsi);
19621510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx,
19631510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org                          kDontSaveFPRegs);
1964895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org      __ leap(rbx, Operand(rbp, StandardFrameConstants::kExpressionsOffset));
19657a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org      __ cmpp(rsp, rbx);
19661510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ j(equal, &post_runtime);
1967763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);  // generator object
1968895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org      __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1);
196943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(context_register(),
197077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org              Operand(rbp, StandardFrameConstants::kContextOffset));
19711510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ bind(&post_runtime);
197277ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
1973763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Pop(result_register());
197441728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      EmitReturnSequence();
197577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
197677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org      __ bind(&resume);
197777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org      context()->Plug(result_register());
197877ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org      break;
197977ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    }
198077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
198177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    case Yield::FINAL: {
198277ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org      VisitForAccumulatorValue(expr->generator_object());
198377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org      __ Move(FieldOperand(result_register(),
198477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org                           JSGeneratorObject::kContinuationOffset),
198577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org              Smi::FromInt(JSGeneratorObject::kGeneratorClosed));
198641728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      // Pop value from top-of-stack slot, box result into result register.
198741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      EmitCreateIteratorResult(true);
198841728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      EmitUnwindBeforeReturn();
198941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      EmitReturnSequence();
199077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org      break;
199177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    }
199277ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
19934e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    case Yield::DELEGATING: {
19944e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      VisitForStackValue(expr->generator_object());
19954e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
19964e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      // Initial stack layout is as follows:
19974e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      // [sp + 1 * kPointerSize] iter
19984e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      // [sp + 0 * kPointerSize] g
19994e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
20001510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      Label l_catch, l_try, l_suspend, l_continuation, l_resume;
20011510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      Label l_next, l_call, l_loop;
20024e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      // Initial send value is undefined.
20034e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
20048a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org      __ jmp(&l_next);
20054e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
2006f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org      // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
20074e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ bind(&l_catch);
20084e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
20094e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ LoadRoot(rcx, Heap::kthrow_stringRootIndex);    // "throw"
2010763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rcx);
2011763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(Operand(rsp, 2 * kPointerSize));           // iter
2012763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);                                      // exception
20134e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ jmp(&l_call);
20144e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
2015f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org      // try { received = %yield result }
2016f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org      // Shuffle the received result above a try handler and yield it without
2017f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org      // re-boxing.
20184e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ bind(&l_try);
2019763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Pop(rax);                                       // result
20204e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ PushTryHandler(StackHandler::CATCH, expr->index());
20214e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      const int handler_size = StackHandlerConstants::kSize;
2022763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);                                      // result
20231510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ jmp(&l_suspend);
20241510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ bind(&l_continuation);
20251510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ jmp(&l_resume);
20261510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ bind(&l_suspend);
20271510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      const int generator_object_depth = kPointerSize + handler_size;
202843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(rax, Operand(rsp, generator_object_depth));
2029763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);                                      // g
20301510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
20311510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset),
20321510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org              Smi::FromInt(l_continuation.pos()));
203343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi);
203443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(rcx, rsi);
20351510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx,
20361510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org                          kDontSaveFPRegs);
2037895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org      __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1);
203843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(context_register(),
20394e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org              Operand(rbp, StandardFrameConstants::kContextOffset));
2040763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Pop(rax);                                       // result
204141728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      EmitReturnSequence();
20424e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ bind(&l_resume);                                // received in rax
20434e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ PopTryHandler();
20444e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
2045f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org      // receiver = iter; f = 'next'; arg = received;
20468a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org      __ bind(&l_next);
20478a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org      __ LoadRoot(rcx, Heap::knext_stringRootIndex);     // "next"
2048763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rcx);
2049763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(Operand(rsp, 2 * kPointerSize));           // iter
2050763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);                                      // received
20514e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
2052f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org      // result = receiver[f](arg);
20534e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ bind(&l_call);
2054a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org      __ movp(rdx, Operand(rsp, kPointerSize));
2055a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org      __ movp(rax, Operand(rsp, 2 * kPointerSize));
2056a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org      Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2057f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      CallIC(ic, TypeFeedbackId::None());
2058a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org      __ movp(rdi, rax);
2059a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org      __ movp(Operand(rsp, 2 * kPointerSize), rdi);
2060f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org      CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
2061a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org      __ CallStub(&stub);
2062a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org
206343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2064a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org      __ Drop(1);  // The function is still on the stack; drop it.
20654e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
2066f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org      // if (!result.done) goto l_try;
20674e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ bind(&l_loop);
2068763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);                                      // save result
20694e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ LoadRoot(rcx, Heap::kdone_stringRootIndex);     // "done"
20709cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org      CallLoadIC(NOT_CONTEXTUAL);                        // result.done in rax
2071b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org      Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2072b99c75496e05b4cd58815ada1e39e6029130d11crossberg@chromium.org      CallIC(bool_ic);
20737a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org      __ testp(result_register(), result_register());
20744e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      __ j(zero, &l_try);
20754e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
20764e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      // result.value
2077763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Pop(rax);                                       // result
2078f95d4b920abb640ab0986d138ad559a7d3b91d04danno@chromium.org      __ LoadRoot(rcx, Heap::kvalue_stringRootIndex);    // "value"
20799cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org      CallLoadIC(NOT_CONTEXTUAL);                        // result.value in rax
20804e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      context()->DropAndPlug(2, rax);                    // drop iter and g
20814e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      break;
20824e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    }
208377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  }
208477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org}
208577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
208677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org
2087ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.orgvoid FullCodeGenerator::EmitGeneratorResume(Expression *generator,
2088ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    Expression *value,
2089ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    JSGeneratorObject::ResumeMode resume_mode) {
2090ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // The value stays in rax, and is ultimately read by the resumed generator, as
2091895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  // if CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject) returned it. Or it
2092e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  // is read to throw the value when the resumed generator is already closed.
2093e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  // rbx will hold the generator object until the activation has been resumed.
2094ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  VisitForStackValue(generator);
2095ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  VisitForAccumulatorValue(value);
2096763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rbx);
2097ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
2098ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Check generator state.
2099e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  Label wrong_state, closed_state, done;
2100e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
2101e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
2102ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ SmiCompare(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset),
2103ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org                Smi::FromInt(0));
2104e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  __ j(equal, &closed_state);
2105e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  __ j(less, &wrong_state);
2106ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
2107ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Load suspended function and context.
210843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rsi, FieldOperand(rbx, JSGeneratorObject::kContextOffset));
210943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset));
2110ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
2111ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Push receiver.
2112763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(FieldOperand(rbx, JSGeneratorObject::kReceiverOffset));
2113ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
2114ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Push holes for arguments to generator function.
211543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
211604a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org  __ LoadSharedFunctionInfoSpecialField(rdx, rdx,
211704a34e6171ac922cb1a4c5162cf471809c468ad0machenbach@chromium.org      SharedFunctionInfo::kFormalParameterCountOffset);
2118ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ LoadRoot(rcx, Heap::kTheHoleValueRootIndex);
2119ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  Label push_argument_holes, push_frame;
2120ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ bind(&push_argument_holes);
2121fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  __ subp(rdx, Immediate(1));
2122ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ j(carry, &push_frame);
2123763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rcx);
2124ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ jmp(&push_argument_holes);
2125ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
2126ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Enter a new JavaScript frame, and initialize its slots as they were when
2127ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // the generator was suspended.
2128ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  Label resume_frame;
2129ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ bind(&push_frame);
2130ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ call(&resume_frame);
2131ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ jmp(&done);
2132ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ bind(&resume_frame);
2133763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ pushq(rbp);  // Caller's frame pointer.
213443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rbp, rsp);
2135763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rsi);  // Callee's context.
2136763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rdi);  // Callee's JS Function.
2137ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
2138ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Load the operand stack size.
213943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdx, FieldOperand(rbx, JSGeneratorObject::kOperandStackOffset));
214043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdx, FieldOperand(rdx, FixedArray::kLengthOffset));
2141ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ SmiToInteger32(rdx, rdx);
2142ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
2143ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // If we are sending a value and there is no operand stack, we can jump back
2144ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // in directly.
21458a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  if (resume_mode == JSGeneratorObject::NEXT) {
2146ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    Label slow_resume;
21477a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org    __ cmpp(rdx, Immediate(0));
2148ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ j(not_zero, &slow_resume);
214943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
2150ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ SmiToInteger64(rcx,
2151ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org        FieldOperand(rbx, JSGeneratorObject::kContinuationOffset));
2152fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    __ addp(rdx, rcx);
2153ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ Move(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset),
2154ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org            Smi::FromInt(JSGeneratorObject::kGeneratorExecuting));
2155ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ jmp(rdx);
2156ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ bind(&slow_resume);
2157ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  }
2158ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
2159ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Otherwise, we push holes for the operand stack and call the runtime to fix
2160ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // up the stack and the handlers.
2161ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  Label push_operand_holes, call_resume;
2162ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ bind(&push_operand_holes);
2163fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  __ subp(rdx, Immediate(1));
2164ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ j(carry, &call_resume);
2165763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rcx);
2166ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ jmp(&push_operand_holes);
2167ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ bind(&call_resume);
2168763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rbx);
2169763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(result_register());
2170ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ Push(Smi::FromInt(resume_mode));
2171895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ CallRuntime(Runtime::kHiddenResumeJSGeneratorObject, 3);
2172ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Not reached: the runtime call returns elsewhere.
2173594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ Abort(kGeneratorFailedToResume);
2174ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
2175e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  // Reach here when generator is closed.
2176e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  __ bind(&closed_state);
2177e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  if (resume_mode == JSGeneratorObject::NEXT) {
2178e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    // Return completed iterator result when generator is closed.
2179e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    __ PushRoot(Heap::kUndefinedValueRootIndex);
2180e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    // Pop value from top-of-stack slot; box result into result register.
2181e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    EmitCreateIteratorResult(true);
2182e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  } else {
2183e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    // Throw the provided value.
2184763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(rax);
2185895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    __ CallRuntime(Runtime::kHiddenThrow, 1);
2186e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  }
2187e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  __ jmp(&done);
2188e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org
2189ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  // Throw error if we attempt to operate on a running generator.
2190ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ bind(&wrong_state);
2191763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rbx);
2192895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ CallRuntime(Runtime::kHiddenThrowGeneratorStateError, 1);
2193ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
2194ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  __ bind(&done);
2195ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  context()->Plug(result_register());
2196ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org}
2197ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
2198ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
219941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.orgvoid FullCodeGenerator::EmitCreateIteratorResult(bool done) {
220057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  Label gc_required;
220157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  Label allocated;
220257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
22034ef23eea527ce7f45bdc5edd52bd4d1a989e2359machenbach@chromium.org  Handle<Map> map(isolate()->native_context()->iterator_result_map());
220457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
220557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT);
220641728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  __ jmp(&allocated);
220741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org
220841728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  __ bind(&gc_required);
220941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  __ Push(Smi::FromInt(map->instance_size()));
2210895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1);
221143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(context_register(),
221241728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org          Operand(rbp, StandardFrameConstants::kContextOffset));
221357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
221457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ bind(&allocated);
221557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ Move(rbx, map);
2216763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rcx);
221757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ Move(rdx, isolate()->factory()->ToBoolean(done));
221857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  ASSERT_EQ(map->instance_size(), 5 * kPointerSize);
221943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx);
222057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ Move(FieldOperand(rax, JSObject::kPropertiesOffset),
222157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org          isolate()->factory()->empty_fixed_array());
222257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ Move(FieldOperand(rax, JSObject::kElementsOffset),
222357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org          isolate()->factory()->empty_fixed_array());
222443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(FieldOperand(rax, JSGeneratorObject::kResultValuePropertyOffset),
222557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org          rcx);
222643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(FieldOperand(rax, JSGeneratorObject::kResultDonePropertyOffset),
222757ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org          rdx);
222857ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
222957ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  // Only the value field needs a write barrier, as the other values are in the
223057ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  // root set.
223157ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org  __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset,
223257ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org                      rcx, rdx, kDontSaveFPRegs);
223357ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org}
223457ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
223557ff881caeb2e15b46ac9e4dfc00e378f7c5f929ulan@chromium.org
2236b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
2237b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  SetSourcePosition(prop->position());
2238b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Literal* key = prop->key()->AsLiteral();
22391510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ Move(rcx, key->value());
22409cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
2241b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
2242b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2243b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2244b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
2245b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  SetSourcePosition(prop->position());
22467979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2247f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  CallIC(ic, prop->PropertyFeedbackId());
2248b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
2249b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2250b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
22518e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.orgvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
2252d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org                                              Token::Value op,
2253d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org                                              OverwriteMode mode,
2254d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org                                              Expression* left,
22559ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org                                              Expression* right) {
2256d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // Do combined smi check of the operands. Left operand is on the
2257d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // stack (popped into rdx). Right operand is in rax but moved into
2258d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // rcx to make the shifts easier.
225983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label done, stub_call, smi_case;
2260763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rdx);
226143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rcx, rax);
2262895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ orp(rax, rdx);
2263d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com  JumpPatchSite patch_site(masm_);
226483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear);
2265d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
2266d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  __ bind(&stub_call);
226743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, rcx);
2268f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  BinaryOpICStub stub(isolate(), op, mode);
2269f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId());
22704f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  patch_site.EmitPatchInfo();
227183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ jmp(&done, Label::kNear);
2272d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
2273d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  __ bind(&smi_case);
2274d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  switch (op) {
2275d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    case Token::SAR:
2276d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      __ SmiShiftArithmeticRight(rax, rdx, rcx);
2277d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      break;
2278d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    case Token::SHL:
2279e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org      __ SmiShiftLeft(rax, rdx, rcx, &stub_call);
2280d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      break;
2281d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    case Token::SHR:
2282d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      __ SmiShiftLogicalRight(rax, rdx, rcx, &stub_call);
2283d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      break;
2284d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    case Token::ADD:
2285d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      __ SmiAdd(rax, rdx, rcx, &stub_call);
2286d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      break;
2287d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    case Token::SUB:
2288d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      __ SmiSub(rax, rdx, rcx, &stub_call);
2289d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      break;
2290d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    case Token::MUL:
2291d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      __ SmiMul(rax, rdx, rcx, &stub_call);
2292d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      break;
2293d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    case Token::BIT_OR:
2294d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      __ SmiOr(rax, rdx, rcx);
2295d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      break;
2296d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    case Token::BIT_AND:
2297d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      __ SmiAnd(rax, rdx, rcx);
2298d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      break;
2299d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    case Token::BIT_XOR:
2300d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      __ SmiXor(rax, rdx, rcx);
2301d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      break;
2302d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org    default:
2303d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      UNREACHABLE();
2304d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org      break;
2305d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  }
2306d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
2307d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  __ bind(&done);
23084a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
2309d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org}
2310d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
2311d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
23128e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.orgvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
23138e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org                                     Token::Value op,
231465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org                                     OverwriteMode mode) {
2315763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rdx);
2316f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  BinaryOpICStub stub(isolate(), op, mode);
23174f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
2318f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId());
23194f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  patch_site.EmitPatchInfo();
23204a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
2321b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
2322b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2323b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2324be6bd10d8264b7a05e0a04407eb98b253bc0f152kmillikin@chromium.orgvoid FullCodeGenerator::EmitAssignment(Expression* expr) {
23254edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org  ASSERT(expr->IsValidReferenceExpression());
23269dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
23279dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Left-hand side can only be a property, a global or a (parameter or local)
23287b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // slot.
23299dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
23309dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  LhsKind assign_type = VARIABLE;
23319dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Property* prop = expr->AsProperty();
23329dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  if (prop != NULL) {
23339dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    assign_type = (prop->key()->IsPropertyName())
23349dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com        ? NAMED_PROPERTY
23359dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com        : KEYED_PROPERTY;
23369dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  }
23379dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
23389dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  switch (assign_type) {
23399dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    case VARIABLE: {
23409dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com      Variable* var = expr->AsVariableProxy()->var();
23414a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      EffectContext context(this);
23424a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      EmitVariableAssignment(var, Token::ASSIGN);
23439dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com      break;
23449dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    }
23459dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    case NAMED_PROPERTY: {
2346763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);  // Preserve value.
23474a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      VisitForAccumulatorValue(prop->obj());
234843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(rdx, rax);
2349763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Pop(rax);  // Restore value.
23501510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ Move(rcx, prop->key()->AsLiteral()->value());
2351f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      CallStoreIC();
23529dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com      break;
23539dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    }
23549dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    case KEYED_PROPERTY: {
2355763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);  // Preserve value.
23567b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      VisitForStackValue(prop->obj());
23577b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      VisitForAccumulatorValue(prop->key());
235843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(rcx, rax);
2359763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Pop(rdx);
2360763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Pop(rax);  // Restore value.
2361486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      Handle<Code> ic = strict_mode() == SLOPPY
23621b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          ? isolate()->builtins()->KeyedStoreIC_Initialize()
23631b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
23641456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org      CallIC(ic);
23659dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com      break;
23669dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    }
23679dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  }
23685f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  context()->Plug(rax);
23699dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
23709dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
23719dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
2372f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2373f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Variable* var, MemOperand location) {
2374f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  __ movp(location, rax);
2375f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  if (var->IsContextSlot()) {
2376f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    __ movp(rdx, rax);
2377f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    __ RecordWriteContextSlot(
2378f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
2379f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
2380f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
2381f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2382f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2383f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid FullCodeGenerator::EmitCallStoreContextSlot(
2384486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    Handle<String> name, StrictMode strict_mode) {
2385763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rax);  // Value.
2386763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rsi);  // Context.
2387f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  __ Push(name);
2388486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  __ Push(Smi::FromInt(strict_mode));
2389895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ CallRuntime(Runtime::kHiddenStoreContextSlot, 4);
2390f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
2391f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2392f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2393b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::EmitVariableAssignment(Variable* var,
23944a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                                               Token::Value op) {
2395486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  if (var->IsUnallocated()) {
2396486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // Global var, const, or let.
2397b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ Move(rcx, var->name());
239843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rdx, GlobalObjectOperand());
2399f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    CallStoreIC();
2400f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2401486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  } else if (op == Token::INIT_CONST_LEGACY) {
2402486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // Const initializers need a write barrier.
2403486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    ASSERT(!var->IsParameter());  // No const parameters.
2404f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (var->IsLookupSlot()) {
2405763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);
2406763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rsi);
2407052c9560e8a41c723726ebe914a93747d8f13285hpayer@chromium.org      __ Push(var->name());
2408895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org      __ CallRuntime(Runtime::kHiddenInitializeConstContextSlot, 3);
2409f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    } else {
2410f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      ASSERT(var->IsStackLocal() || var->IsContextSlot());
2411f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      Label skip;
2412f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      MemOperand location = VarOperand(var, rcx);
2413f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      __ movp(rdx, location);
2414f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2415f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      __ j(not_equal, &skip);
2416f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      EmitStoreToStackLocalOrContextSlot(var, location);
2417f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      __ bind(&skip);
24185d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org    }
24195d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org
2420b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  } else if (var->mode() == LET && op != Token::INIT_LET) {
2421486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // Non-initializing assignment to let variable needs a write barrier.
2422486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    if (var->IsLookupSlot()) {
2423486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      EmitCallStoreContextSlot(var->name(), strict_mode());
2424486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    } else {
2425486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2426486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      Label assign;
2427486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      MemOperand location = VarOperand(var, rcx);
242843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(rdx, location);
2429486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2430486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      __ j(not_equal, &assign, Label::kNear);
2431486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      __ Push(var->name());
2432895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org      __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1);
2433486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      __ bind(&assign);
2434f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      EmitStoreToStackLocalOrContextSlot(var, location);
243580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    }
2436b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2437486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
2438394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Assignment to var or initializing assignment to let/const
2439394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // in harmony mode.
2440f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (var->IsLookupSlot()) {
2441486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      EmitCallStoreContextSlot(var->name(), strict_mode());
2442f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    } else {
2443f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2444486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      MemOperand location = VarOperand(var, rcx);
2445000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org      if (generate_debug_code_ && op == Token::INIT_LET) {
2446486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org        // Check for an uninitialized let binding.
244743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org        __ movp(rdx, location);
2448486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org        __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2449594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org        __ Check(equal, kLetBindingReInitialization);
2450486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      }
2451f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      EmitStoreToStackLocalOrContextSlot(var, location);
2452b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
2453b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
2454486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // Non-initializing assignments to consts are ignored.
2455b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
2456b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2457b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2458b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2459b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Assignment to a property, using a named store IC.
2460b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Property* prop = expr->target()->AsProperty();
2461b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ASSERT(prop != NULL);
2462196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org  ASSERT(prop->key()->IsLiteral());
2463b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2464b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Record source code position before IC call.
2465b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  SetSourcePosition(expr->position());
24661510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  __ Move(rcx, prop->key()->AsLiteral()->value());
2467763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rdx);
2468f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  CallStoreIC(expr->AssignmentFeedbackId());
2469b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2470d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
24715f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  context()->Plug(rax);
2472b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
2473b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2474b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2475b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2476b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Assignment to a property, using a keyed store IC.
2477b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2478763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rcx);
2479763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rdx);
2480b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Record source code position before IC call.
2481b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  SetSourcePosition(expr->position());
2482486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  Handle<Code> ic = strict_mode() == SLOPPY
24831b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      ? isolate()->builtins()->KeyedStoreIC_Initialize()
24841b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2485f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  CallIC(ic, expr->AssignmentFeedbackId());
2486b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2487d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
24884a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
2489b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
2490b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2491b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2492b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::VisitProperty(Property* expr) {
2493b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Comment cmnt(masm_, "[ Property");
2494b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Expression* key = expr->key();
2495b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2496b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  if (key->IsPropertyName()) {
24974a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    VisitForAccumulatorValue(expr->obj());
2498b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    EmitNamedPropertyLoad(expr);
2499471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org    PrepareForBailoutForId(expr->LoadId(), TOS_REG);
2500a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    context()->Plug(rax);
2501b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  } else {
25024a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    VisitForStackValue(expr->obj());
25034a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    VisitForAccumulatorValue(expr->key());
2504763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Pop(rdx);
2505b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    EmitKeyedPropertyLoad(expr);
2506a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    context()->Plug(rax);
2507b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
2508b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
2509b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2510b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
25111456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgvoid FullCodeGenerator::CallIC(Handle<Code> code,
2512471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org                               TypeFeedbackId ast_id) {
25131456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  ic_total_count_++;
25149cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org  __ call(code, RelocInfo::CODE_TARGET, ast_id);
25151456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org}
25161456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
25171456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
2518a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org// Code common for calls using the IC.
2519a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.orgvoid FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
2520a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org  Expression* callee = expr->expression();
2521a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org
2522a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  CallIC::CallType call_type = callee->IsVariableProxy()
2523a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org      ? CallIC::FUNCTION
2524a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org      : CallIC::METHOD;
2525a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  // Get the target function.
2526a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  if (call_type == CallIC::FUNCTION) {
2527a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    { StackValueContext context(this);
2528a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org      EmitVariableLoad(callee->AsVariableProxy());
2529a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org      PrepareForBailout(callee, NO_REGISTERS);
2530a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    }
2531a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    // Push undefined as receiver. This is patched in the method prologue if it
2532486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    // is a sloppy mode method.
2533a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    __ Push(isolate()->factory()->undefined_value());
2534a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org  } else {
2535a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    // Load the function from the receiver.
2536a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    ASSERT(callee->IsProperty());
2537a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    __ movp(rax, Operand(rsp, 0));
2538a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    EmitNamedPropertyLoad(callee->AsProperty());
2539a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2540a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    // Push the target function under the receiver.
2541763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(Operand(rsp, 0));
2542a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    __ movp(Operand(rsp, kPointerSize), rax);
2543b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
2544a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org
2545a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  EmitCall(expr, call_type);
2546b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
2547b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2548b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2549a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org// Common code for calls using the IC.
2550a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.orgvoid FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2551a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org                                                Expression* key) {
25524a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  // Load the key.
25534a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com  VisitForAccumulatorValue(key);
25544a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com
2555a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org  Expression* callee = expr->expression();
2556a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org
2557a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org  // Load the function from the receiver.
2558a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org  ASSERT(callee->IsProperty());
2559a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org  __ movp(rdx, Operand(rsp, 0));
2560a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org  EmitKeyedPropertyLoad(callee->AsProperty());
2561a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org  PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2562a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org
2563a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org  // Push the target function under the receiver.
2564763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(Operand(rsp, 0));
2565a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org  __ movp(Operand(rsp, kPointerSize), rax);
2566a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org
2567a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  EmitCall(expr, CallIC::METHOD);
25682c186ca6690a1cb19ec7584e71f167234587c87cwhesse@chromium.org}
25692c186ca6690a1cb19ec7584e71f167234587c87cwhesse@chromium.org
25702c186ca6690a1cb19ec7584e71f167234587c87cwhesse@chromium.org
2571a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.orgvoid FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) {
2572a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  // Load the arguments.
2573b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ZoneList<Expression*>* args = expr->arguments();
2574b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  int arg_count = args->length();
2575a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  { PreservePositionScope scope(masm()->positions_recorder());
2576f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org    for (int i = 0; i < arg_count; i++) {
2577f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org      VisitForStackValue(args->at(i));
2578f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org    }
2579b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
258088d326b0935b802e71e3a75e02f31fae8c2af96cmstarzinger@chromium.org
2581a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  // Record source position of the IC call.
2582a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  SetSourcePosition(expr->position());
2583a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  Handle<Code> ic = CallIC::initialize_stub(
2584a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org      isolate(), arg_count, call_type);
2585f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  __ Move(rdx, Smi::FromInt(expr->CallFeedbackSlot()));
258643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2587a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  // Don't assign a type feedback id to the IC, since type feedback is provided
2588a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  // by the vector above.
2589a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  CallIC(ic);
2590a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org
2591d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  RecordJSReturnSite(expr);
2592a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org
2593b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Restore context register.
259443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2595b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Discard the function left on TOS.
25964a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->DropAndPlug(1, rax);
2597b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
2598b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2599b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2600c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
26019ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  // Push copy of the first argument or undefined if it doesn't exist.
26029ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  if (arg_count > 0) {
2603763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(Operand(rsp, arg_count * kPointerSize));
26049ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  } else {
26059ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    __ PushRoot(Heap::kUndefinedValueRootIndex);
26069ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  }
26079ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
26089ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  // Push the receiver of the enclosing function and do runtime call.
2609d8a3a149cb9dac7437e264a2fe50f680418c3a45jkummerow@chromium.org  StackArgumentsAccessor args(rbp, info_->scope()->num_parameters());
2610763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(args.GetReceiverOperand());
26119ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
26121b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // Push the language mode.
2613486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  __ Push(Smi::FromInt(strict_mode()));
26149ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
261504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  // Push the start position of the scope the calls resides in.
261604e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  __ Push(Smi::FromInt(scope()->start_position()));
261704e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org
26181b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  // Do the runtime call.
2619895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ CallRuntime(Runtime::kHiddenResolvePossiblyDirectEval, 5);
26209ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org}
26219ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
26229ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
2623b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::VisitCall(Call* expr) {
2624d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org#ifdef DEBUG
2625d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // We want to verify that RecordJSReturnSite gets called on all paths
2626d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // through this function.  Avoid early returns.
2627d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  expr->return_is_recorded_ = false;
2628d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org#endif
2629d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
2630b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Comment cmnt(masm_, "[ Call");
2631486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  Expression* callee = expr->expression();
263243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  Call::CallType call_type = expr->GetCallType(isolate());
2633b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
263443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  if (call_type == Call::POSSIBLY_EVAL_CALL) {
2635895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
2636895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    // to resolve the function we need to call and the receiver of the call.
2637486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // Then we call the resolved function using the given arguments.
26389dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    ZoneList<Expression*>* args = expr->arguments();
26399dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    int arg_count = args->length();
2640a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    { PreservePositionScope pos_scope(masm()->positions_recorder());
2641486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      VisitForStackValue(callee);
2642f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org      __ PushRoot(Heap::kUndefinedValueRootIndex);  // Reserved receiver slot.
26439dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
2644f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org      // Push the arguments.
2645f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org      for (int i = 0; i < arg_count; i++) {
2646f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org        VisitForStackValue(args->at(i));
2647f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org      }
26489dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
2649486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      // Push a copy of the function (found below the arguments) and resolve
2650486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      // eval.
2651763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(Operand(rsp, (arg_count + 1) * kPointerSize));
2652c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      EmitResolvePossiblyDirectEval(arg_count);
26539dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
2654f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org      // The runtime call returns a pair of values in rax (function) and
2655f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org      // rdx (receiver). Touch up the stack with the right values.
265643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
265743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
2658f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org    }
26599dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    // Record source position for debugger.
2660a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    SetSourcePosition(expr->position());
2661f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org    CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
266243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
26639dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    __ CallStub(&stub);
2664d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    RecordJSReturnSite(expr);
26659dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    // Restore context register.
266643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
26674a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    context()->DropAndPlug(1, rax);
266843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  } else if (call_type == Call::GLOBAL_CALL) {
2669a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org    EmitCallWithLoadIC(expr);
2670a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org
267143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  } else if (call_type == Call::LOOKUP_SLOT_CALL) {
26722ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    // Call to a lookup slot (dynamically introduced variable).
267343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    VariableProxy* proxy = callee->AsVariableProxy();
26742ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    Label slow, done;
26752ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
2676a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    { PreservePositionScope scope(masm()->positions_recorder());
2677486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      // Generate code for loading from variables potentially shadowed by
2678486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      // eval-introduced variables.
2679486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
2680d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    }
2681486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    __ bind(&slow);
2682486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // Call the runtime to find the function to call (returned in rax) and
2683486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // the object holding it (returned in rdx).
2684763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(context_register());
2685486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    __ Push(proxy->name());
2686895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2);
2687763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(rax);  // Function.
2688763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(rdx);  // Receiver.
2689d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
2690486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // If fast case code has been generated, emit code to push the function
2691486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // and receiver and have the slow path jump around this code.
2692d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    if (done.is_linked()) {
269383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      Label call;
269483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org      __ jmp(&call, Label::kNear);
2695d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      __ bind(&done);
2696d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      // Push function.
2697763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);
2698486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      // The receiver is implicitly the global receiver. Indicate this by
2699486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      // passing the hole to the call function stub.
2700e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org      __ PushRoot(Heap::kUndefinedValueRootIndex);
27018e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org      __ bind(&call);
27022ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    }
27032ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
2704486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // The receiver is either the global receiver or an object found by
2705e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    // LoadContextSlot.
2706a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org    EmitCall(expr);
270743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  } else if (call_type == Call::PROPERTY_CALL) {
270843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    Property* property = callee->AsProperty();
2709486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    { PreservePositionScope scope(masm()->positions_recorder());
2710486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      VisitForStackValue(property->obj());
2711486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    }
2712486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    if (property->key()->IsPropertyName()) {
2713a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org      EmitCallWithLoadIC(expr);
2714b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    } else {
2715a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org      EmitKeyedCallWithLoadIC(expr, property->key());
2716b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
2717b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  } else {
271843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    ASSERT(call_type == Call::OTHER_CALL);
2719486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // Call to an arbitrary expression not handled specially above.
2720a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    { PreservePositionScope scope(masm()->positions_recorder());
2721486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      VisitForStackValue(callee);
2722f0ac72dfa39ec827de605aafc57d4834237aa7f3whesse@chromium.org    }
2723e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org    __ PushRoot(Heap::kUndefinedValueRootIndex);
2724b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    // Emit function call.
2725a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org    EmitCall(expr);
2726b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
2727d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
2728d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org#ifdef DEBUG
2729d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // RecordJSReturnSite should have been called.
2730d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  ASSERT(expr->return_is_recorded_);
2731d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org#endif
2732b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
2733b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2734b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2735b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::VisitCallNew(CallNew* expr) {
2736b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Comment cmnt(masm_, "[ CallNew");
2737b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // According to ECMA-262, section 11.2.2, page 44, the function
2738b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // expression in new calls must be evaluated before the
2739b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // arguments.
2740b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
274165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Push constructor on the stack.  If it's not a function it's used as
274265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
274365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // ignored.
27444a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(expr->expression());
2745b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2746b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Push the arguments ("left-to-right") on the stack.
2747b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ZoneList<Expression*>* args = expr->arguments();
2748b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  int arg_count = args->length();
2749b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  for (int i = 0; i < arg_count; i++) {
27504a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    VisitForStackValue(args->at(i));
2751b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
2752b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2753b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Call the construct call builtin that handles allocation and
2754b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // constructor invocation.
2755b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  SetSourcePosition(expr->position());
2756b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
275765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  // Load function and argument count into rdi and rax.
2758b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  __ Set(rax, arg_count);
275943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdi, Operand(rsp, arg_count * kPointerSize));
2760b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2761fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org  // Record call targets in unoptimized code, but not in the snapshot.
276269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  if (FLAG_pretenuring_call_new) {
2763a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org    EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot());
276469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    ASSERT(expr->AllocationSiteFeedbackSlot() ==
276569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org           expr->CallNewFeedbackSlot() + 1);
276669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  }
276769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
2768f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  __ Move(rbx, FeedbackVector());
2769f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  __ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot()));
2770fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org
2771a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET);
2772f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
2773967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
27744a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
2775b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
2776b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2777b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
2778c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2779c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
27809dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 1);
27819dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
27824a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));
27839dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
27849dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label materialize_true, materialize_false;
27859dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_true = NULL;
27869dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_false = NULL;
278765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* fall_through = NULL;
27884a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
27894a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                         &if_true, &if_false, &fall_through);
27909dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
2791c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
27929dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ JumpIfSmi(rax, if_true);
27939dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ jmp(if_false);
27949dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
27954a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(if_true, if_false);
27969dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
27979dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
27989dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
2799c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
2800c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
28019dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 1);
28029dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
28034a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));
28049dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
28059dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label materialize_true, materialize_false;
28069dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_true = NULL;
28079dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_false = NULL;
280865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* fall_through = NULL;
28094a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
28104a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                         &if_true, &if_false, &fall_through);
28119dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
2812c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2813eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
2814eb7c144137bd7d461d4996f752f1353a0856fac1ricow@chromium.org  Split(non_negative_smi, if_true, if_false, fall_through);
28159dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
28164a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(if_true, if_false);
28179dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
28189dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
28199dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
2820c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
2821c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
28229dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 1);
28239dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
28244a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));
28259dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
28269dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label materialize_true, materialize_false;
28279dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_true = NULL;
28289dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_false = NULL;
282965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* fall_through = NULL;
28304a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
28314a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                         &if_true, &if_false, &fall_through);
28329dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
28339dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ JumpIfSmi(rax, if_false);
28349dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CompareRoot(rax, Heap::kNullValueRootIndex);
28359dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ j(equal, if_true);
283643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
28379dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Undetectable objects behave like undefined when tested with typeof.
28389dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
28399dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com           Immediate(1 << Map::kIsUndetectable));
28409dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ j(not_zero, if_false);
2841895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ movzxbp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
28427a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ cmpp(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
28439dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ j(below, if_false);
28447a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ cmpp(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
2845c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
284665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Split(below_equal, if_true, if_false, fall_through);
28479dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
28484a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(if_true, if_false);
28499dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
28509dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
28519dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
2852c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
2853c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
28544980dff4208f9b77bc5320af43d7cc4b2a3d9688ricow@chromium.org  ASSERT(args->length() == 1);
28554980dff4208f9b77bc5320af43d7cc4b2a3d9688ricow@chromium.org
28564a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));
28574980dff4208f9b77bc5320af43d7cc4b2a3d9688ricow@chromium.org
28584980dff4208f9b77bc5320af43d7cc4b2a3d9688ricow@chromium.org  Label materialize_true, materialize_false;
28594980dff4208f9b77bc5320af43d7cc4b2a3d9688ricow@chromium.org  Label* if_true = NULL;
28604980dff4208f9b77bc5320af43d7cc4b2a3d9688ricow@chromium.org  Label* if_false = NULL;
286165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* fall_through = NULL;
28624a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
28634a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                         &if_true, &if_false, &fall_through);
28644980dff4208f9b77bc5320af43d7cc4b2a3d9688ricow@chromium.org
28654980dff4208f9b77bc5320af43d7cc4b2a3d9688ricow@chromium.org  __ JumpIfSmi(rax, if_false);
2866d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org  __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx);
2867c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
286865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Split(above_equal, if_true, if_false, fall_through);
28694980dff4208f9b77bc5320af43d7cc4b2a3d9688ricow@chromium.org
28704a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(if_true, if_false);
28714980dff4208f9b77bc5320af43d7cc4b2a3d9688ricow@chromium.org}
28724980dff4208f9b77bc5320af43d7cc4b2a3d9688ricow@chromium.org
28734980dff4208f9b77bc5320af43d7cc4b2a3d9688ricow@chromium.org
2874c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
2875c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
28769dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 1);
28779dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
28784a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));
28799dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
28809dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label materialize_true, materialize_false;
28819dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_true = NULL;
28829dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_false = NULL;
288365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* fall_through = NULL;
28844a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
28854a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                         &if_true, &if_false, &fall_through);
28869dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
28879dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ JumpIfSmi(rax, if_false);
288843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
28899dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
28909dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com           Immediate(1 << Map::kIsUndetectable));
2891c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
289265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Split(not_zero, if_true, if_false, fall_through);
28939dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
28944a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(if_true, if_false);
28959dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
28969dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
28979dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
2898ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.orgvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2899c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    CallRuntime* expr) {
2900c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
2901ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  ASSERT(args->length() == 1);
2902ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org
29034a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));
2904ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org
29054a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  Label materialize_true, materialize_false, skip_lookup;
2906ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  Label* if_true = NULL;
2907ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  Label* if_false = NULL;
290865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* fall_through = NULL;
29094a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
29104a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                         &if_true, &if_false, &fall_through);
2911ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org
2912c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  __ AssertNotSmi(rax);
2913c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org
2914c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // Check whether this map has already been checked to be safe for default
2915c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // valueOf.
291643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2917c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  __ testb(FieldOperand(rbx, Map::kBitField2Offset),
2918c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org           Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
29194a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ j(not_zero, &skip_lookup);
2920c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org
2921c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // Check for fast case object. Generate false result for slow case object.
292243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rcx, FieldOperand(rax, JSObject::kPropertiesOffset));
292343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
2924c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  __ CompareRoot(rcx, Heap::kHashTableMapRootIndex);
2925c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  __ j(equal, if_false);
2926c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org
29274a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // Look for valueOf string in the descriptor array, and indicate false if
292806ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org  // found. Since we omit an enumeration index check, if it is added via a
292906ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org  // transition that shares its descriptor array, this is a false positive.
293006ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org  Label entry, loop, done;
293106ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org
293206ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org  // Skip loop if no descriptors are valid.
293306ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org  __ NumberOfOwnDescriptors(rcx, rbx);
29347a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ cmpp(rcx, Immediate(0));
293506ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org  __ j(equal, &done);
293606ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org
29374a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ LoadInstanceDescriptors(rbx, r8);
293806ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org  // rbx: descriptor array.
293906ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org  // rcx: valid entries in the descriptor array.
2940c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // Calculate the end of the descriptor array.
2941fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  __ imulp(rcx, rcx, Immediate(DescriptorArray::kDescriptorSize));
29423c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  __ leap(rcx, Operand(r8, rcx, times_8, DescriptorArray::kFirstOffset));
2943c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // Calculate location of the first key name.
2944fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  __ addp(r8, Immediate(DescriptorArray::kFirstOffset));
2945c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // Loop through all the keys in the descriptor array. If one of these is the
29464a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  // internalized string "valueOf" the result is false.
2947c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  __ jmp(&entry);
2948c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  __ bind(&loop);
294943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdx, FieldOperand(r8, 0));
2950d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  __ Cmp(rdx, isolate()->factory()->value_of_string());
2951c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  __ j(equal, if_false);
2952fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  __ addp(r8, Immediate(DescriptorArray::kDescriptorSize * kPointerSize));
2953c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  __ bind(&entry);
29547a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ cmpp(r8, rcx);
2955c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  __ j(not_equal, &loop);
2956c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org
295706ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org  __ bind(&done);
29584a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
29594a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  // Set the bit in the map to indicate that there is no local valueOf field.
2960895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ orp(FieldOperand(rbx, Map::kBitField2Offset),
29614a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org         Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
29624a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
29634a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  __ bind(&skip_lookup);
2964c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org
296506ab2ec756e44eeaf7500b9794f9d2abc79dc8cfverwaest@chromium.org  // If a valueOf property is not found on the object check that its
2966c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  // prototype is the un-modified String prototype. If not result is false.
296743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
29687a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ testp(rcx, Immediate(kSmiTagMask));
2969c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  __ j(zero, if_false);
297043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
297143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
297243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdx, FieldOperand(rdx, GlobalObject::kNativeContextOffset));
29737a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ cmpp(rcx,
2974c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org          ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
2975c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
29764a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org  Split(equal, if_true, if_false, fall_through);
29774a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org
29784a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(if_true, if_false);
2979ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org}
2980ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org
2981ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org
2982c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
2983c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
29849dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 1);
29859dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
29864a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));
29879dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
29889dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label materialize_true, materialize_false;
29899dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_true = NULL;
29909dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_false = NULL;
299165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* fall_through = NULL;
29924a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
29934a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                         &if_true, &if_false, &fall_through);
29949dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
29959dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ JumpIfSmi(rax, if_false);
29969dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2997c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
299865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Split(equal, if_true, if_false, fall_through);
29999dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30004a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(if_true, if_false);
30019dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
30029dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30039dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30040cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.orgvoid FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
30050cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  ZoneList<Expression*>* args = expr->arguments();
30060cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  ASSERT(args->length() == 1);
30070cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org
30080cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
30090cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org
30100cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  Label materialize_true, materialize_false;
30110cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  Label* if_true = NULL;
30120cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  Label* if_false = NULL;
30130cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  Label* fall_through = NULL;
30140cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
30150cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org                         &if_true, &if_false, &fall_through);
30160cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org
30170cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
30180cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  __ CheckMap(rax, map, if_false, DO_SMI_CHECK);
30190cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  __ cmpl(FieldOperand(rax, HeapNumber::kExponentOffset),
3020a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org          Immediate(0x1));
3021a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  __ j(no_overflow, if_false);
30220cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  __ cmpl(FieldOperand(rax, HeapNumber::kMantissaOffset),
30230cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org          Immediate(0x00000000));
30240cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
30250cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  Split(equal, if_true, if_false, fall_through);
30260cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org
30270cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  context()->Plug(if_true, if_false);
30280cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org}
30290cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org
30300cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org
3031c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
3032c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
30339dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 1);
30349dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30354a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));
30369dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30379dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label materialize_true, materialize_false;
30389dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_true = NULL;
30399dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_false = NULL;
304065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* fall_through = NULL;
30414a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
30424a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                         &if_true, &if_false, &fall_through);
30439dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30449dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ JumpIfSmi(rax, if_false);
30459dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
3046c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
304765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Split(equal, if_true, if_false, fall_through);
30489dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30494a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(if_true, if_false);
30509dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
30519dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30529dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3053c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
3054c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
30559dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 1);
30569dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30574a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));
30589dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30599dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label materialize_true, materialize_false;
30609dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_true = NULL;
30619dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_false = NULL;
306265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* fall_through = NULL;
30634a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
30644a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                         &if_true, &if_false, &fall_through);
30659dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30669dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ JumpIfSmi(rax, if_false);
30679dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
3068c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
306965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Split(equal, if_true, if_false, fall_through);
30709dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30714a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(if_true, if_false);
30729dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
30739dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30749dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30759dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3076c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
3077c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ASSERT(expr->arguments()->length() == 0);
30789dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30799dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label materialize_true, materialize_false;
30809dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_true = NULL;
30819dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_false = NULL;
308265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* fall_through = NULL;
30834a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
30844a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                         &if_true, &if_false, &fall_through);
30859dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30869dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Get the frame pointer for the calling frame.
308743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
30889dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30899dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Skip the arguments adaptor frame if it exists.
30909dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label check_frame_marker;
3091badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset),
3092badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
30939dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ j(not_equal, &check_frame_marker);
309443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
30959dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
30969dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Check the marker in the calling frame.
30979dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&check_frame_marker);
3098badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset),
3099badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org         Smi::FromInt(StackFrame::CONSTRUCT));
3100c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
310165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Split(equal, if_true, if_false, fall_through);
31029dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
31034a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(if_true, if_false);
31049dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
31059dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
31069dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3107c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
3108c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
31099dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 2);
31109dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
31119dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Load the two objects into registers and perform the comparison.
31124a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(0));
31134a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(1));
31149dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
31159dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label materialize_true, materialize_false;
31169dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_true = NULL;
31179dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_false = NULL;
311865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* fall_through = NULL;
31194a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
31204a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                         &if_true, &if_false, &fall_through);
31219dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3122763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rbx);
31237a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ cmpp(rax, rbx);
3124c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
312565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Split(equal, if_true, if_false, fall_through);
31269dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
31274a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(if_true, if_false);
31289dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
31299dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
31309dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3131c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitArguments(CallRuntime* expr) {
3132c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
31339dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 1);
31349dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3135d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // ArgumentsAccessStub expects the key in rdx and the formal
3136d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // parameter count in rax.
31374a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));
313843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdx, rax);
31394f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
3140f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT);
31419dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CallStub(&stub);
31424a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
31439dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
31449dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
31459dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3146c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
3147c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ASSERT(expr->arguments()->length() == 0);
31489dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
314983a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label exit;
31509dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Get the number of formal parameters.
31514f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
31529dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
31539dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Check if the calling frame is an arguments adaptor frame.
315443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
3155badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org  __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
3156badaffc570baec00166b0ad3bdc96995751a7e13ricow@chromium.org         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
315783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(not_equal, &exit, Label::kNear);
31589dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
31599dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Arguments adaptor case: Read the arguments length from the
31609dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // adaptor frame.
316143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
31629dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
31639dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&exit);
3164c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  __ AssertSmi(rax);
31654a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
31669dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
31679dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
31689dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3169c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
3170c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
31719dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 1);
31729dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label done, null, function, non_function_constructor;
31739dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
31744a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));
31759dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
31769dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // If the object is a smi, we return null.
31779dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ JumpIfSmi(rax, &null);
31789dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
31799dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Check that the object is a JS object but take special care of JS
31809dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // functions to make sure they have 'Function' as their class.
3181c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Assume that there are only two callable types, and one of them is at
3182c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // either end of the type range for JS object types. Saves extra comparisons.
3183c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
3184d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org  __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax);
3185d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org  // Map is now in rax.
31869dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ j(below, &null);
3187c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
3188c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                FIRST_SPEC_OBJECT_TYPE + 1);
3189c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ j(equal, &function);
3190c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
3191c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE);
3192c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
3193c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                LAST_SPEC_OBJECT_TYPE - 1);
3194c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ j(equal, &function);
3195c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Assume that there is no larger type.
3196c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
3197c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
3198c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Check if the constructor in the map is a JS function.
319943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, FieldOperand(rax, Map::kConstructorOffset));
32009dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
32019dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ j(not_equal, &non_function_constructor);
32029dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32039dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // rax now contains the constructor function. Grab the
32049dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // instance class name from there.
320543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
320643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset));
32079dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ jmp(&done);
32089dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32099dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Functions have class 'Function'.
32109dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&function);
32114a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ Move(rax, isolate()->factory()->function_class_string());
32129dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ jmp(&done);
32139dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32149dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Objects with a non-function constructor have class 'Object'.
32159dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&non_function_constructor);
32164a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ Move(rax, isolate()->factory()->Object_string());
32179dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ jmp(&done);
32189dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32199dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Non-JS objects have class null.
32209dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&null);
32219dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ LoadRoot(rax, Heap::kNullValueRootIndex);
32229dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32239dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // All done.
32249dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&done);
32259dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32264a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
32279dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
32289dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32299dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3230c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitSubString(CallRuntime* expr) {
32319dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Load the arguments on the stack and call the stub.
3232f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  SubStringStub stub(isolate());
3233c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
32349dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 3);
32354a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(0));
32364a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(1));
32374a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(2));
32389dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CallStub(&stub);
32394a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
32409dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
32419dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32429dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3243c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
32449dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Load the arguments on the stack and call the stub.
3245f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  RegExpExecStub stub(isolate());
3246c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
32479dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 4);
32484a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(0));
32494a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(1));
32504a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(2));
32514a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(3));
32529dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CallStub(&stub);
32534a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
32549dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
32559dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32569dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3257c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
3258c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
32599dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 1);
32609dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32614a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));  // Load the object.
32629dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32639dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label done;
32649dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // If the object is a smi return the object.
32659dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ JumpIfSmi(rax, &done);
32669dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // If the object is not a value type, return the object.
32679dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CmpObjectType(rax, JS_VALUE_TYPE, rbx);
32689dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ j(not_equal, &done);
326943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, FieldOperand(rax, JSValue::kValueOffset));
32709dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32719dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&done);
32724a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
32739dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
32749dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32759dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32764efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.orgvoid FullCodeGenerator::EmitDateField(CallRuntime* expr) {
32774efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  ZoneList<Expression*>* args = expr->arguments();
32784efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  ASSERT(args->length() == 2);
32794efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  ASSERT_NE(NULL, args->at(1)->AsLiteral());
32801510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value()));
32814efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org
32824efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  VisitForAccumulatorValue(args->at(0));  // Load the object.
32834efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org
3284de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  Label runtime, done, not_date_object;
32854efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  Register object = rax;
32864efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  Register result = rax;
32874efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  Register scratch = rcx;
32884efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org
3289de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  __ JumpIfSmi(object, &not_date_object);
32904efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  __ CmpObjectType(object, JS_DATE_TYPE, scratch);
3291de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  __ j(not_equal, &not_date_object);
32924efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org
32934efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  if (index->value() == 0) {
329443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(result, FieldOperand(object, JSDate::kValueOffset));
3295de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    __ jmp(&done);
32964efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  } else {
32974efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    if (index->value() < JSDate::kFirstUncachedField) {
32984efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org      ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
32996e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      Operand stamp_operand = __ ExternalOperand(stamp);
330043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(scratch, stamp_operand);
33017a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org      __ cmpp(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
33024efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org      __ j(not_equal, &runtime, Label::kNear);
330343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(result, FieldOperand(object, JSDate::kValueOffset +
33044efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org                                           kPointerSize * index->value()));
33054efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org      __ jmp(&done);
33064efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    }
33074efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    __ bind(&runtime);
33084efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    __ PrepareCallCFunction(2);
330943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(arg_reg_1, object);
3310af4fba3c6d2a18866505de3e6798757dd1448c6dmachenbach@chromium.org    __ Move(arg_reg_2, index, Assembler::RelocInfoNone());
33114efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org    __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
331243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3313de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    __ jmp(&done);
33144efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  }
3315de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
3316de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  __ bind(&not_date_object);
3317895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ CallRuntime(Runtime::kHiddenThrowNotDateError, 0);
3318de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org  __ bind(&done);
33194efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org  context()->Plug(rax);
33204efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org}
33214efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org
33224efbdb18fa3063085682c44cc77cf5254cb3d75dsvenpanne@chromium.org
332332280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.orgvoid FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
332432280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org  ZoneList<Expression*>* args = expr->arguments();
332532280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org  ASSERT_EQ(3, args->length());
332632280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org
3327a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  Register string = rax;
3328a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  Register index = rbx;
3329a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  Register value = rcx;
3330a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org
333132280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org  VisitForStackValue(args->at(1));  // index
333232280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org  VisitForStackValue(args->at(2));  // value
33339af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  VisitForAccumulatorValue(args->at(0));  // string
3334763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(value);
3335763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(index);
333632280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org
3337a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  if (FLAG_debug_code) {
333805150ab746caefd8e734c394ecc7863200ca04cfmachenbach@chromium.org    __ Check(__ CheckSmi(value), kNonSmiValue);
333905150ab746caefd8e734c394ecc7863200ca04cfmachenbach@chromium.org    __ Check(__ CheckSmi(index), kNonSmiValue);
3340a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  }
3341a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org
3342a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  __ SmiToInteger32(value, value);
3343a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  __ SmiToInteger32(index, index);
33449af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
33459af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  if (FLAG_debug_code) {
33469af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
33479af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org    __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
33489af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  }
33499af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
3350a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  __ movb(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize),
3351a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org          value);
3352a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  context()->Plug(string);
335332280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org}
335432280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org
335532280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org
335632280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.orgvoid FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
335732280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org  ZoneList<Expression*>* args = expr->arguments();
335832280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org  ASSERT_EQ(3, args->length());
335932280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org
3360a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  Register string = rax;
3361a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  Register index = rbx;
3362a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  Register value = rcx;
3363a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org
336432280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org  VisitForStackValue(args->at(1));  // index
336532280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org  VisitForStackValue(args->at(2));  // value
33669af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  VisitForAccumulatorValue(args->at(0));  // string
3367763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(value);
3368763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(index);
336932280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org
3370a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  if (FLAG_debug_code) {
337105150ab746caefd8e734c394ecc7863200ca04cfmachenbach@chromium.org    __ Check(__ CheckSmi(value), kNonSmiValue);
337205150ab746caefd8e734c394ecc7863200ca04cfmachenbach@chromium.org    __ Check(__ CheckSmi(index), kNonSmiValue);
3373a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  }
3374a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org
3375a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  __ SmiToInteger32(value, value);
3376a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  __ SmiToInteger32(index, index);
33779af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
33789af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  if (FLAG_debug_code) {
33799af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
33809af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org    __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
33819af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org  }
33829af454f6b1c6a921ac79ba0b9a979c73adb2ca1emachenbach@chromium.org
3383a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org  __ movw(FieldOperand(string, index, times_2, SeqTwoByteString::kHeaderSize),
3384a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org          value);
338532280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org  context()->Plug(rax);
338632280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org}
338732280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org
338832280cf2786219b2d9a668f7f00778fb59ac40b3mstarzinger@chromium.org
3389c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
33909dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Load the arguments on the stack and call the runtime function.
3391c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
33929dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 2);
33934a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(0));
33944a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(1));
3395f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  MathPowStub stub(isolate(), MathPowStub::ON_STACK);
33969ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org  __ CallStub(&stub);
33974a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
33989dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
33999dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
34009dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3401c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
3402c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
34039dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 2);
34049dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
34054a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(0));  // Load the object.
34064a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(1));  // Load the value.
3407763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rbx);  // rax = value. rbx = object.
34089dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
34099dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label done;
34109dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // If the object is a smi, return the value.
34119dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ JumpIfSmi(rbx, &done);
34129dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
34139dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // If the object is not a value type, return the value.
34149dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx);
34159dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ j(not_equal, &done);
34169dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
34179dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Store the value.
341843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(FieldOperand(rbx, JSValue::kValueOffset), rax);
34199dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Update the write barrier.  Save the value as it will be
34209dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // overwritten by the write barrier code and is needed afterward.
342143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdx, rax);
3422c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs);
34239dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
34249dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&done);
34254a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
34269dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
34279dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
34289dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3429c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
3430c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
34319dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT_EQ(args->length(), 1);
34329dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
34333d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  // Load the argument into rax and call the stub.
34343d079fe881245e49c7ba803b54b4fe6d4b46113cmachenbach@chromium.org  VisitForAccumulatorValue(args->at(0));
34359dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3436f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  NumberToStringStub stub(isolate());
34379dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CallStub(&stub);
34384a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
34399dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
34409dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
34419dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3442c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
3443c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
34449dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 1);
34459dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
34464a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));
34479dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
344830ce411529579186181838984710b0b0980857aaricow@chromium.org  Label done;
344930ce411529579186181838984710b0b0980857aaricow@chromium.org  StringCharFromCodeGenerator generator(rax, rbx);
345030ce411529579186181838984710b0b0980857aaricow@chromium.org  generator.GenerateFast(masm_);
345130ce411529579186181838984710b0b0980857aaricow@chromium.org  __ jmp(&done);
34529dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
345330ce411529579186181838984710b0b0980857aaricow@chromium.org  NopRuntimeCallHelper call_helper;
345430ce411529579186181838984710b0b0980857aaricow@chromium.org  generator.GenerateSlow(masm_, call_helper);
34559dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
345630ce411529579186181838984710b0b0980857aaricow@chromium.org  __ bind(&done);
34574a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rbx);
345830ce411529579186181838984710b0b0980857aaricow@chromium.org}
345930ce411529579186181838984710b0b0980857aaricow@chromium.org
346030ce411529579186181838984710b0b0980857aaricow@chromium.org
3461c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
3462c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
346330ce411529579186181838984710b0b0980857aaricow@chromium.org  ASSERT(args->length() == 2);
346430ce411529579186181838984710b0b0980857aaricow@chromium.org
34654a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(0));
34664a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(1));
346730ce411529579186181838984710b0b0980857aaricow@chromium.org
346830ce411529579186181838984710b0b0980857aaricow@chromium.org  Register object = rbx;
346930ce411529579186181838984710b0b0980857aaricow@chromium.org  Register index = rax;
347030ce411529579186181838984710b0b0980857aaricow@chromium.org  Register result = rdx;
347130ce411529579186181838984710b0b0980857aaricow@chromium.org
3472763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(object);
347330ce411529579186181838984710b0b0980857aaricow@chromium.org
347430ce411529579186181838984710b0b0980857aaricow@chromium.org  Label need_conversion;
347530ce411529579186181838984710b0b0980857aaricow@chromium.org  Label index_out_of_range;
347630ce411529579186181838984710b0b0980857aaricow@chromium.org  Label done;
347730ce411529579186181838984710b0b0980857aaricow@chromium.org  StringCharCodeAtGenerator generator(object,
347830ce411529579186181838984710b0b0980857aaricow@chromium.org                                      index,
347930ce411529579186181838984710b0b0980857aaricow@chromium.org                                      result,
348030ce411529579186181838984710b0b0980857aaricow@chromium.org                                      &need_conversion,
348130ce411529579186181838984710b0b0980857aaricow@chromium.org                                      &need_conversion,
348230ce411529579186181838984710b0b0980857aaricow@chromium.org                                      &index_out_of_range,
348330ce411529579186181838984710b0b0980857aaricow@chromium.org                                      STRING_INDEX_IS_NUMBER);
348430ce411529579186181838984710b0b0980857aaricow@chromium.org  generator.GenerateFast(masm_);
34859dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ jmp(&done);
34869dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
348730ce411529579186181838984710b0b0980857aaricow@chromium.org  __ bind(&index_out_of_range);
348830ce411529579186181838984710b0b0980857aaricow@chromium.org  // When the index is out of range, the spec requires us to return
348930ce411529579186181838984710b0b0980857aaricow@chromium.org  // NaN.
349030ce411529579186181838984710b0b0980857aaricow@chromium.org  __ LoadRoot(result, Heap::kNanValueRootIndex);
349130ce411529579186181838984710b0b0980857aaricow@chromium.org  __ jmp(&done);
349230ce411529579186181838984710b0b0980857aaricow@chromium.org
349330ce411529579186181838984710b0b0980857aaricow@chromium.org  __ bind(&need_conversion);
349430ce411529579186181838984710b0b0980857aaricow@chromium.org  // Move the undefined value into the result register, which will
349530ce411529579186181838984710b0b0980857aaricow@chromium.org  // trigger conversion.
349630ce411529579186181838984710b0b0980857aaricow@chromium.org  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
349730ce411529579186181838984710b0b0980857aaricow@chromium.org  __ jmp(&done);
349830ce411529579186181838984710b0b0980857aaricow@chromium.org
349930ce411529579186181838984710b0b0980857aaricow@chromium.org  NopRuntimeCallHelper call_helper;
350030ce411529579186181838984710b0b0980857aaricow@chromium.org  generator.GenerateSlow(masm_, call_helper);
35019dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
35029dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&done);
35034a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(result);
35049dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
35059dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
35069dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3507c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
3508c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
350930ce411529579186181838984710b0b0980857aaricow@chromium.org  ASSERT(args->length() == 2);
351030ce411529579186181838984710b0b0980857aaricow@chromium.org
35114a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(0));
35124a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(1));
351330ce411529579186181838984710b0b0980857aaricow@chromium.org
351430ce411529579186181838984710b0b0980857aaricow@chromium.org  Register object = rbx;
351530ce411529579186181838984710b0b0980857aaricow@chromium.org  Register index = rax;
3516c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  Register scratch = rdx;
351730ce411529579186181838984710b0b0980857aaricow@chromium.org  Register result = rax;
351830ce411529579186181838984710b0b0980857aaricow@chromium.org
3519763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(object);
352030ce411529579186181838984710b0b0980857aaricow@chromium.org
352130ce411529579186181838984710b0b0980857aaricow@chromium.org  Label need_conversion;
352230ce411529579186181838984710b0b0980857aaricow@chromium.org  Label index_out_of_range;
352330ce411529579186181838984710b0b0980857aaricow@chromium.org  Label done;
352430ce411529579186181838984710b0b0980857aaricow@chromium.org  StringCharAtGenerator generator(object,
352530ce411529579186181838984710b0b0980857aaricow@chromium.org                                  index,
3526c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org                                  scratch,
352730ce411529579186181838984710b0b0980857aaricow@chromium.org                                  result,
352830ce411529579186181838984710b0b0980857aaricow@chromium.org                                  &need_conversion,
352930ce411529579186181838984710b0b0980857aaricow@chromium.org                                  &need_conversion,
353030ce411529579186181838984710b0b0980857aaricow@chromium.org                                  &index_out_of_range,
353130ce411529579186181838984710b0b0980857aaricow@chromium.org                                  STRING_INDEX_IS_NUMBER);
353230ce411529579186181838984710b0b0980857aaricow@chromium.org  generator.GenerateFast(masm_);
353330ce411529579186181838984710b0b0980857aaricow@chromium.org  __ jmp(&done);
353430ce411529579186181838984710b0b0980857aaricow@chromium.org
353530ce411529579186181838984710b0b0980857aaricow@chromium.org  __ bind(&index_out_of_range);
353630ce411529579186181838984710b0b0980857aaricow@chromium.org  // When the index is out of range, the spec requires us to return
353730ce411529579186181838984710b0b0980857aaricow@chromium.org  // the empty string.
35384a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ LoadRoot(result, Heap::kempty_stringRootIndex);
353930ce411529579186181838984710b0b0980857aaricow@chromium.org  __ jmp(&done);
354030ce411529579186181838984710b0b0980857aaricow@chromium.org
354130ce411529579186181838984710b0b0980857aaricow@chromium.org  __ bind(&need_conversion);
354230ce411529579186181838984710b0b0980857aaricow@chromium.org  // Move smi zero into the result register, which will trigger
354330ce411529579186181838984710b0b0980857aaricow@chromium.org  // conversion.
354430ce411529579186181838984710b0b0980857aaricow@chromium.org  __ Move(result, Smi::FromInt(0));
354530ce411529579186181838984710b0b0980857aaricow@chromium.org  __ jmp(&done);
354630ce411529579186181838984710b0b0980857aaricow@chromium.org
354730ce411529579186181838984710b0b0980857aaricow@chromium.org  NopRuntimeCallHelper call_helper;
354830ce411529579186181838984710b0b0980857aaricow@chromium.org  generator.GenerateSlow(masm_, call_helper);
354930ce411529579186181838984710b0b0980857aaricow@chromium.org
355030ce411529579186181838984710b0b0980857aaricow@chromium.org  __ bind(&done);
35514a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(result);
35529dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
35539dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
355430ce411529579186181838984710b0b0980857aaricow@chromium.org
3555c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3556c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
35579dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT_EQ(2, args->length());
3558bbbda924f939464825b508976aabe7ed128605cbmachenbach@chromium.org  VisitForStackValue(args->at(0));
3559bbbda924f939464825b508976aabe7ed128605cbmachenbach@chromium.org  VisitForAccumulatorValue(args->at(1));
35609dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3561763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rdx);
3562f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED);
3563bbbda924f939464825b508976aabe7ed128605cbmachenbach@chromium.org  __ CallStub(&stub);
35644a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
35659dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
35669dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
35679dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3568c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3569c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
35709dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT_EQ(2, args->length());
35719dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
35724a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(0));
35734a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(1));
35749dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3575f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  StringCompareStub stub(isolate());
35769dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ CallStub(&stub);
35774a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
35789dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
35799dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
35809dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3581c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
3582c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
35839dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() >= 2);
35849dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3585160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  int arg_count = args->length() - 2;  // 2 ~ receiver and function.
3586160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  for (int i = 0; i < arg_count + 1; i++) {
3587160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    VisitForStackValue(args->at(i));
35889dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  }
3589160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  VisitForAccumulatorValue(args->last());  // Function.
35909dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3591de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org  Label runtime, done;
3592de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org  // Check for non-function argument (including proxy).
3593de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org  __ JumpIfSmi(rax, &runtime);
3594de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
3595de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org  __ j(not_equal, &runtime);
3596c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org
3597160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org  // InvokeFunction requires the function in rdi. Move it in there.
359843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdi, result_register());
35999dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ParameterCount count(arg_count);
3600e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org  __ InvokeFunction(rdi, count, CALL_FUNCTION, NullCallWrapper());
360143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3602c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  __ jmp(&done);
3603c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org
3604de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org  __ bind(&runtime);
3605763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rax);
3606c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  __ CallRuntime(Runtime::kCall, args->length());
3607c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org  __ bind(&done);
3608c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org
36094a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
36109dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
36119dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
36129dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3613c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3614f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  RegExpConstructResultStub stub(isolate());
3615c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
36169dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT(args->length() == 3);
36174a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(0));
36184a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(args->at(1));
361909cae8d7af4e66e8d0088c19dcd0033042fa8a6bmachenbach@chromium.org  VisitForAccumulatorValue(args->at(2));
3620763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rbx);
3621763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rcx);
3622a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ CallStub(&stub);
36234a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
36249dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
36259dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
36269dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3627c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3628c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
36299dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT_EQ(2, args->length());
36309dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
36319dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  ASSERT_NE(NULL, args->at(0)->AsLiteral());
36321510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value();
36339dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
36349dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Handle<FixedArray> jsfunction_result_caches(
363546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org      isolate()->native_context()->jsfunction_result_caches());
36369dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  if (jsfunction_result_caches->length() <= cache_id) {
3637594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Abort(kAttemptToUseUndefinedCache);
36389dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
36394a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    context()->Plug(rax);
36409dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    return;
36419dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  }
36429dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
36434a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(1));
36449dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
36459dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Register key = rax;
36469dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Register cache = rbx;
36479dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Register tmp = rcx;
364843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(cache, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX));
364943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(cache,
365046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org          FieldOperand(cache, GlobalObject::kNativeContextOffset));
365143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(cache,
36522ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org          ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
365343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(cache,
36549dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com          FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
36559dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
365683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label done, not_found;
365780c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
365843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
36590a7303680fa9f3dc3945763aaa7c5a3859a7f855machenbach@chromium.org  // tmp now holds finger offset as a smi.
36609dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  SmiIndex index =
36619dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com      __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2);
36627a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ cmpp(key, FieldOperand(cache,
36639dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                            index.reg,
36649dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                            index.scale,
36659dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                            FixedArray::kHeaderSize));
366683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(not_equal, &not_found, Label::kNear);
366743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, FieldOperand(cache,
36689dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                            index.reg,
36699dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                            index.scale,
36709dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com                            FixedArray::kHeaderSize + kPointerSize));
367183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ jmp(&done, Label::kNear);
36729dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
36739dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&not_found);
36749dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  // Call runtime to perform the lookup.
3675763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(cache);
3676763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(key);
36779b95fd75bfb24acf6b51a360058331013e74fc73machenbach@chromium.org  __ CallRuntime(Runtime::kHiddenGetFromCache, 2);
36789dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
36799dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  __ bind(&done);
36804a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
36819dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
36829dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
36839dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3684c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3685c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3686d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  ASSERT(args->length() == 1);
3687d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
36884a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));
3689d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
3690d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  Label materialize_true, materialize_false;
3691d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  Label* if_true = NULL;
3692d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  Label* if_false = NULL;
3693d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  Label* fall_through = NULL;
36944a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
36954a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                         &if_true, &if_false, &fall_through);
3696d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
3697d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  __ testl(FieldOperand(rax, String::kHashFieldOffset),
3698d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org           Immediate(String::kContainsCachedArrayIndexMask));
3699c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3700d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  __ j(zero, if_true);
3701d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  __ jmp(if_false);
3702d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
37034a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(if_true, if_false);
3704d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org}
3705d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
3706d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
3707c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
3708c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
3709d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  ASSERT(args->length() == 1);
37104a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForAccumulatorValue(args->at(0));
3711d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
3712c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org  __ AssertString(rax);
37135d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org
3714d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  __ movl(rax, FieldOperand(rax, String::kHashFieldOffset));
3715d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  ASSERT(String::kHashShift >= kSmiTagSize);
3716d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  __ IndexFromHash(rax, rax);
3717d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
37184a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
3719d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org}
3720d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
3721d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org
3722c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgvoid FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
37237979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Label bailout, return_result, done, one_char_separator, long_separator,
37247979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org      non_trivial_array, not_size_one_array, loop,
37257979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org      loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
3726c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  ZoneList<Expression*>* args = expr->arguments();
37277979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  ASSERT(args->length() == 2);
37287979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // We will leave the separator on the stack until the end of the function.
37297979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  VisitForStackValue(args->at(1));
37307979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Load this to rax (= array)
37317979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  VisitForAccumulatorValue(args->at(0));
37327979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // All aliases of the same register have disjoint lifetimes.
37337979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Register array = rax;
37347979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Register elements = no_reg;  // Will be rax.
37357979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
37367979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Register index = rdx;
37377979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
37387979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Register string_length = rcx;
37397979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
37407979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Register string = rsi;
37417979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
37427979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Register scratch = rbx;
37437979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
37447979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Register array_length = rdi;
37457979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Register result_pos = no_reg;  // Will be rdi.
37467979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
37477979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Operand separator_operand =    Operand(rsp, 2 * kPointerSize);
37487979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Operand result_operand =       Operand(rsp, 1 * kPointerSize);
37497979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Operand array_length_operand = Operand(rsp, 0 * kPointerSize);
37507979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Separator operand is already pushed. Make room for the two
37517979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // other stack fields, and clear the direction flag in anticipation
37527979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // of calling CopyBytes.
3753fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  __ subp(rsp, Immediate(2 * kPointerSize));
37547979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ cld();
37557979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Check that the array is a JSArray
37567979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ JumpIfSmi(array, &bailout);
37577979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
37587979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ j(not_equal, &bailout);
37597979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
37607979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Check that the array has fast elements.
3761d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  __ CheckFastElements(scratch, &bailout);
37627979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
37637979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Array has fast elements, so its length must be a smi.
37647979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // If the array has length zero, return the empty string.
376543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(array_length, FieldOperand(array, JSArray::kLengthOffset));
37667979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ SmiCompare(array_length, Smi::FromInt(0));
37677979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ j(not_zero, &non_trivial_array);
37684a9f6553038df6b893b3d3ccae351723f4cbbae7yangguo@chromium.org  __ LoadRoot(rax, Heap::kempty_stringRootIndex);
37697979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ jmp(&return_result);
37707979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
37717979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Save the array length on the stack.
37727979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ bind(&non_trivial_array);
37737979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ SmiToInteger32(array_length, array_length);
37747979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ movl(array_length_operand, array_length);
37757979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
37767979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Save the FixedArray containing array's elements.
37777979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // End of array's live range.
37787979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  elements = array;
377943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(elements, FieldOperand(array, JSArray::kElementsOffset));
37807979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  array = no_reg;
37817979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
37827979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
37837979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Check that all array elements are sequential ASCII strings, and
37847979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // accumulate the sum of their lengths, as a smi-encoded value.
37857979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ Set(index, 0);
37867979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ Set(string_length, 0);
37877979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Loop condition: while (index < array_length).
37887979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Live loop registers: index(int32), array_length(int32), string(String*),
37897979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //                      scratch, string_length(int32), elements(FixedArray*).
3790000f7fbc1dfa59e414332fd2898b5da4d44eedd6jkummerow@chromium.org  if (generate_debug_code_) {
37917a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org    __ cmpp(index, array_length);
3792594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org    __ Assert(below, kNoEmptyArraysHereInEmitFastAsciiArrayJoin);
37937979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  }
37947979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ bind(&loop);
379543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(string, FieldOperand(elements,
37967979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                               index,
37977979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                               times_pointer_size,
37987979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                               FixedArray::kHeaderSize));
37997979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ JumpIfSmi(string, &bailout);
380043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(scratch, FieldOperand(string, HeapObject::kMapOffset));
38017979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
38027979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ andb(scratch, Immediate(
38037979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3804e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  __ cmpb(scratch, Immediate(kStringTag | kOneByteStringTag | kSeqStringTag));
38057979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ j(not_equal, &bailout);
38067979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ AddSmiField(string_length,
3807fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                 FieldOperand(string, SeqOneByteString::kLengthOffset));
38087979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ j(overflow, &bailout);
38097979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ incl(index);
38107979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ cmpl(index, array_length);
38117979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ j(less, &loop);
38127979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
38137979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Live registers:
38147979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // string_length: Sum of string lengths.
38157979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // elements: FixedArray of strings.
38167979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // index: Array length.
38177979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // array_length: Array length.
38187979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
38197979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // If array_length is 1, return elements[0], a string.
38207979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ cmpl(array_length, Immediate(1));
38217979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ j(not_equal, &not_size_one_array);
382243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, FieldOperand(elements, FixedArray::kHeaderSize));
38237979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ jmp(&return_result);
38247979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
38257979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ bind(&not_size_one_array);
38267979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
38277979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // End of array_length live range.
38287979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  result_pos = array_length;
38297979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  array_length = no_reg;
38307979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
38317979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Live registers:
38327979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // string_length: Sum of string lengths.
38337979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // elements: FixedArray of strings.
38347979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // index: Array length.
38357979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
38367979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Check that the separator is a sequential ASCII string.
383743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(string, separator_operand);
38387979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ JumpIfSmi(string, &bailout);
383943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(scratch, FieldOperand(string, HeapObject::kMapOffset));
38407979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
38417979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ andb(scratch, Immediate(
38427979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3843e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org  __ cmpb(scratch, Immediate(kStringTag | kOneByteStringTag | kSeqStringTag));
38447979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ j(not_equal, &bailout);
38457979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
38467979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Live registers:
38477979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // string_length: Sum of string lengths.
38487979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // elements: FixedArray of strings.
38497979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // index: Array length.
38507979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // string: Separator string.
38517979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
38527979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Add (separator length times (array_length - 1)) to string_length.
38537979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ SmiToInteger32(scratch,
3854fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org                    FieldOperand(string, SeqOneByteString::kLengthOffset));
38557979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ decl(index);
38567979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ imull(scratch, index);
38577979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ j(overflow, &bailout);
38587979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ addl(string_length, scratch);
38597979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ j(overflow, &bailout);
38607979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
38617979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Live registers and stack values:
38627979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //   string_length: Total length of result string.
38637979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //   elements: FixedArray of strings.
38647979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ AllocateAsciiString(result_pos, string_length, scratch,
38657979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                         index, string, &bailout);
386643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(result_operand, result_pos);
3867895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ leap(result_pos, FieldOperand(result_pos, SeqOneByteString::kHeaderSize));
38687979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
386943c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(string, separator_operand);
3870fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ SmiCompare(FieldOperand(string, SeqOneByteString::kLengthOffset),
38717979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                Smi::FromInt(1));
38727979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ j(equal, &one_char_separator);
38737979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ j(greater, &long_separator);
38747979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
38757979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
38767979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Empty separator case:
38777979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ Set(index, 0);
38787979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ movl(scratch, array_length_operand);
38797979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ jmp(&loop_1_condition);
38807979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Loop condition: while (index < array_length).
38817979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ bind(&loop_1);
38827979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Each iteration of the loop concatenates one string to the result.
38837979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Live values in registers:
38847979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //   index: which element of the elements array we are adding to the result.
38857979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //   result_pos: the position to which we are currently copying characters.
38867979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //   elements: the FixedArray of strings we are joining.
38877979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //   scratch: array length.
38887979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
38897979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Get string = array[index].
389043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(string, FieldOperand(elements, index,
38917979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                               times_pointer_size,
38927979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                               FixedArray::kHeaderSize));
38937979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ SmiToInteger32(string_length,
38947979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                    FieldOperand(string, String::kLengthOffset));
3895895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ leap(string,
3896fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org         FieldOperand(string, SeqOneByteString::kHeaderSize));
38977979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ CopyBytes(result_pos, string, string_length);
38987979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ incl(index);
38997979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ bind(&loop_1_condition);
39007979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ cmpl(index, scratch);
39017979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ j(less, &loop_1);  // Loop while (index < array_length).
39027979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ jmp(&done);
39037979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
39047979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Generic bailout code used from several places.
39057979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ bind(&bailout);
39067979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
39077979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ jmp(&return_result);
39087979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
39097979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
39107979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // One-character separator case
39117979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ bind(&one_char_separator);
39122efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // Get the separator ASCII character value.
39137979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Register "string" holds the separator.
3914fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ movzxbl(scratch, FieldOperand(string, SeqOneByteString::kHeaderSize));
39157979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ Set(index, 0);
39167979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Jump into the loop after the code that copies the separator, so the first
39177979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // element is not preceded by a separator
39187979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ jmp(&loop_2_entry);
39197979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Loop condition: while (index < length).
39207979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ bind(&loop_2);
39217979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Each iteration of the loop concatenates one string to the result.
39227979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Live values in registers:
39237979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //   elements: The FixedArray of strings we are joining.
39247979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //   index: which element of the elements array we are adding to the result.
39257979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //   result_pos: the position to which we are currently copying characters.
39267979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //   scratch: Separator character.
39277979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
39287979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Copy the separator character to the result.
39297979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ movb(Operand(result_pos, 0), scratch);
39307a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ incp(result_pos);
39317979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
39327979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ bind(&loop_2_entry);
39337979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Get string = array[index].
393443c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(string, FieldOperand(elements, index,
39357979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                               times_pointer_size,
39367979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                               FixedArray::kHeaderSize));
39377979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ SmiToInteger32(string_length,
39387979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                    FieldOperand(string, String::kLengthOffset));
3939895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ leap(string,
3940fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org         FieldOperand(string, SeqOneByteString::kHeaderSize));
39417979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ CopyBytes(result_pos, string, string_length);
39427979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ incl(index);
39437979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ cmpl(index, array_length_operand);
39447979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ j(less, &loop_2);  // End while (index < length).
39457979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ jmp(&done);
39467979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
39477979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
39487979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Long separator case (separator is more than one character).
39497979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ bind(&long_separator);
39507979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
39517979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Make elements point to end of elements array, and index
39527979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // count from -array_length to zero, so we don't need to maintain
39537979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // a loop limit.
39547979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ movl(index, array_length_operand);
3955895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ leap(elements, FieldOperand(elements, index, times_pointer_size,
39567979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                                FixedArray::kHeaderSize));
39577a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org  __ negq(index);
39587979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
39597979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Replace separator string with pointer to its first character, and
39607979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // make scratch be its length.
396143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(string, separator_operand);
39627979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ SmiToInteger32(scratch,
39637979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                    FieldOperand(string, String::kLengthOffset));
3964895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ leap(string,
3965fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org         FieldOperand(string, SeqOneByteString::kHeaderSize));
396643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(separator_operand, string);
39677979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
39687979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Jump into the loop after the code that copies the separator, so the first
39697979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // element is not preceded by a separator
39707979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ jmp(&loop_3_entry);
39717979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Loop condition: while (index < length).
39727979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ bind(&loop_3);
39737979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Each iteration of the loop concatenates one string to the result.
39747979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Live values in registers:
39757979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //   index: which element of the elements array we are adding to the result.
39767979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //   result_pos: the position to which we are currently copying characters.
39777979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //   scratch: Separator length.
39787979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  //   separator_operand (rsp[0x10]): Address of first char of separator.
39797979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
39807979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Copy the separator to the result.
398143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(string, separator_operand);
39827979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ movl(string_length, scratch);
39837979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ CopyBytes(result_pos, string, string_length, 2);
39847979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
39857979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ bind(&loop_3_entry);
39867979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Get string = array[index].
398743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(string, Operand(elements, index, times_pointer_size, 0));
39887979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ SmiToInteger32(string_length,
39897979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                    FieldOperand(string, String::kLengthOffset));
3990895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org  __ leap(string,
3991fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org         FieldOperand(string, SeqOneByteString::kHeaderSize));
39927979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ CopyBytes(result_pos, string, string_length);
39937979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ incq(index);
39947979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ j(not_equal, &loop_3);  // Loop while (index < 0).
39957979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
39967979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ bind(&done);
399743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, result_operand);
39987979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
39997979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  __ bind(&return_result);
40007979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Drop temp values from the stack, and restore context register.
4001fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  __ addp(rsp, Immediate(3 * kPointerSize));
400243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
40037979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  context()->Plug(rax);
400421b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org}
400521b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org
400621b5e95db1c650dfc2ba8e11d010bb01293f85c5vegorov@chromium.org
4007b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
40089b95fd75bfb24acf6b51a360058331013e74fc73machenbach@chromium.org  if (expr->function() != NULL &&
40099b95fd75bfb24acf6b51a360058331013e74fc73machenbach@chromium.org      expr->function()->intrinsic_type == Runtime::INLINE) {
40109dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    Comment cmnt(masm_, "[ InlineRuntimeCall");
40119dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    EmitInlineRuntimeCall(expr);
40129dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    return;
40139dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  }
40149dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
4015b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Comment cmnt(masm_, "[ CallRuntime");
4016b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ZoneList<Expression*>* args = expr->arguments();
4017a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org  int arg_count = args->length();
4018b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4019b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  if (expr->is_jsruntime()) {
4020a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    // Push the builtins object as receiver.
402143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rax, GlobalObjectOperand());
4022763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
4023b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4024a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    // Load the function from the receiver.
4025a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    __ movp(rax, Operand(rsp, 0));
40265c838251403b0be9a882540f1922577abba4c872ager@chromium.org    __ Move(rcx, expr->name());
4027a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
4028a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org
4029a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    // Push the target function under the receiver.
4030763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(Operand(rsp, 0));
4031a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    __ movp(Operand(rsp, kPointerSize), rax);
4032a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org
4033a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    // Push the arguments ("left-to-right").
4034a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    for (int i = 0; i < arg_count; i++) {
4035a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org      VisitForStackValue(args->at(i));
4036a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    }
4037a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org
4038a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    // Record source position of the IC call.
4039a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    SetSourcePosition(expr->position());
4040f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org    CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
4041a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
4042a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    __ CallStub(&stub);
4043a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org
4044b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    // Restore context register.
404543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4046a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    context()->DropAndPlug(1, rax);
4047a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org
4048b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  } else {
4049a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    // Push the arguments ("left-to-right").
4050a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    for (int i = 0; i < arg_count; i++) {
4051a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org      VisitForStackValue(args->at(i));
4052a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    }
4053a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org
4054a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    // Call the C runtime.
4055b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ CallRuntime(expr->function(), arg_count);
4056a03ba1e53fa6a04b8e56747536f226380bb6269bmachenbach@chromium.org    context()->Plug(rax);
4057b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
4058b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
4059b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4060b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4061b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4062b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  switch (expr->op()) {
40639dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    case Token::DELETE: {
40649dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
4065486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      Property* property = expr->expression()->AsProperty();
4066486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      VariableProxy* proxy = expr->expression()->AsVariableProxy();
406749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
4068486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      if (property != NULL) {
4069486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org        VisitForStackValue(property->obj());
4070486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org        VisitForStackValue(property->key());
4071486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        __ Push(Smi::FromInt(strict_mode()));
40724668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
40734668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org        context()->Plug(rax);
4074486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org      } else if (proxy != NULL) {
4075486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org        Variable* var = proxy->var();
407649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org        // Delete of an unqualified identifier is disallowed in strict mode
4077486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org        // but "delete this" is allowed.
4078486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        ASSERT(strict_mode() == SLOPPY || var->is_this());
4079486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org        if (var->IsUnallocated()) {
4080763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org          __ Push(GlobalObjectOperand());
408149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org          __ Push(var->name());
4082486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org          __ Push(Smi::FromInt(SLOPPY));
408349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org          __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
408449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org          context()->Plug(rax);
4085486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org        } else if (var->IsStackAllocated() || var->IsContextSlot()) {
4086486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org          // Result of deleting non-global variables is false.  'this' is
4087486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org          // not really a variable, though we implement it as one.  The
4088486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org          // subexpression does not have side effects.
4089486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org          context()->Plug(var->is_this());
409049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org        } else {
409149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org          // Non-global variable.  Call the runtime to try to delete from the
409249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org          // context where the variable was introduced.
4093763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org          __ Push(context_register());
409449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org          __ Push(var->name());
4095895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org          __ CallRuntime(Runtime::kHiddenDeleteContextSlot, 2);
409649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org          context()->Plug(rax);
409749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org        }
4098496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      } else {
409949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org        // Result of deleting non-property, non-variable reference is true.
410049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org        // The subexpression may have side effects.
410149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org        VisitForEffect(expr->expression());
410249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org        context()->Plug(true);
41039dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com      }
41049dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com      break;
41059dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    }
41069dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
4107b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    case Token::VOID: {
4108b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
4109b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      VisitForEffect(expr->expression());
41104a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      context()->Plug(Heap::kUndefinedValueRootIndex);
4111b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      break;
4112b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
4113b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4114b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    case Token::NOT: {
4115b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
41163a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      if (context()->IsEffect()) {
41173a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        // Unary NOT has no side effects so it's only necessary to visit the
41183a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        // subexpression.  Match the optimizing compiler by not branching.
41193a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org        VisitForEffect(expr->expression());
4120c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      } else if (context()->IsTest()) {
4121c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        const TestContext* test = TestContext::cast(context());
4122c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        // The labels are swapped for the recursive call.
4123c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        VisitForControl(expr->expression(),
4124c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        test->false_label(),
4125c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        test->true_label(),
4126c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        test->fall_through());
4127c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        context()->Plug(test->true_label(), test->false_label());
41283a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      } else {
4129c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        // We handle value contexts explicitly rather than simply visiting
4130c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        // for control and plugging the control flow into the context,
4131c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        // because we need to prepare a pair of extra administrative AST ids
4132c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        // for the optimizing compiler.
4133c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
4134c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        Label materialize_true, materialize_false, done;
4135c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        VisitForControl(expr->expression(),
4136c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        &materialize_false,
4137c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        &materialize_true,
4138c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                        &materialize_true);
4139c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        __ bind(&materialize_true);
4140c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
4141c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        if (context()->IsAccumulatorValue()) {
4142c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          __ LoadRoot(rax, Heap::kTrueValueRootIndex);
4143c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        } else {
4144c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          __ PushRoot(Heap::kTrueValueRootIndex);
4145c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        }
4146c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        __ jmp(&done, Label::kNear);
4147c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        __ bind(&materialize_false);
4148c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
4149c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        if (context()->IsAccumulatorValue()) {
4150c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          __ LoadRoot(rax, Heap::kFalseValueRootIndex);
4151c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        } else {
4152c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org          __ PushRoot(Heap::kFalseValueRootIndex);
4153c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        }
4154c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org        __ bind(&done);
41553a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org      }
4156b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      break;
4157b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
4158b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4159b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    case Token::TYPEOF: {
4160b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
41614a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      { StackValueContext context(this);
41624a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        VisitForTypeofValue(expr->expression());
41634a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      }
4164b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ CallRuntime(Runtime::kTypeof, 1);
41654a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      context()->Plug(rax);
4166b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      break;
4167b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
4168b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4169b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    default:
4170b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      UNREACHABLE();
4171b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
4172b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
4173b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4174b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4175b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
41764edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org  ASSERT(expr->expression()->IsValidReferenceExpression());
41772904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org
4178b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Comment cmnt(masm_, "[ CountOperation");
417965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  SetSourcePosition(expr->position());
4180b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4181b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Expression can only be a property, a global or a (parameter or local)
41827b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // slot.
4183b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
4184b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  LhsKind assign_type = VARIABLE;
4185b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Property* prop = expr->expression()->AsProperty();
4186b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // In case of a property we use the uninitialized expression context
4187b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // of the key to detect a named property.
4188b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  if (prop != NULL) {
4189b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    assign_type =
4190b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
4191b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
4192b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4193b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Evaluate expression and get value.
4194b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  if (assign_type == VARIABLE) {
4195b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
41964a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    AccumulatorValueContext context(this);
4197030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.org    EmitVariableLoad(expr->expression()->AsVariableProxy());
41989dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  } else {
4199b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    // Reserve space for result of postfix operation.
42004a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    if (expr->is_postfix() && !context()->IsEffect()) {
4201b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ Push(Smi::FromInt(0));
4202b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
4203b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    if (assign_type == NAMED_PROPERTY) {
42044a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      VisitForAccumulatorValue(prop->obj());
4205763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);  // Copy of receiver, needed for later store.
4206b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      EmitNamedPropertyLoad(prop);
4207b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    } else {
42087b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      VisitForStackValue(prop->obj());
42097b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      VisitForAccumulatorValue(prop->key());
421043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org      __ movp(rdx, Operand(rsp, 0));  // Leave receiver on stack
4211763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Push(rax);  // Copy of key, needed for later store.
4212b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      EmitKeyedPropertyLoad(prop);
4213b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
4214b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
4215b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4216d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // We need a second deoptimization point after loading the value
4217d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org  // in case evaluating the property load my have a side effect.
4218c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  if (assign_type == VARIABLE) {
4219c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    PrepareForBailout(expr->expression(), TOS_REG);
4220c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  } else {
4221471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org    PrepareForBailoutForId(prop->LoadId(), TOS_REG);
4222c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  }
4223d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
4224e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  // Inline smi case if we are in a loop.
4225e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  Label done, stub_call;
4226e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  JumpPatchSite patch_site(masm_);
4227ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  if (ShouldInlineSmiCase(expr->op())) {
4228e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    Label slow;
4229e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    patch_site.EmitJumpIfNotSmi(rax, &slow, Label::kNear);
4230e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org
4231e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    // Save result for postfix expressions.
4232e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    if (expr->is_postfix()) {
4233e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      if (!context()->IsEffect()) {
4234e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        // Save the result on the stack. If we have a named or keyed property
4235e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        // we store the result under the receiver that is currently on top
4236e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        // of the stack.
4237e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        switch (assign_type) {
4238e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org          case VARIABLE:
4239763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org            __ Push(rax);
4240e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org            break;
4241e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org          case NAMED_PROPERTY:
424243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org            __ movp(Operand(rsp, kPointerSize), rax);
4243e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org            break;
4244e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org          case KEYED_PROPERTY:
424543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org            __ movp(Operand(rsp, 2 * kPointerSize), rax);
4246e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org            break;
4247e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org        }
4248e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      }
4249e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    }
4250e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org
4251e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    SmiOperationExecutionMode mode;
4252e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    mode.Add(PRESERVE_SOURCE_REGISTER);
4253e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    mode.Add(BAILOUT_ON_NO_OVERFLOW);
4254e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    if (expr->op() == Token::INC) {
4255e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      __ SmiAddConstant(rax, rax, Smi::FromInt(1), mode, &done, Label::kNear);
4256e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    } else {
4257e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org      __ SmiSubConstant(rax, rax, Smi::FromInt(1), mode, &done, Label::kNear);
4258e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    }
4259e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    __ jmp(&stub_call, Label::kNear);
4260e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org    __ bind(&slow);
4261ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  }
4262e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org
4263f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  ToNumberStub convert_stub(isolate());
42647a392b3bfb39dbbc1ff22f0b53109aa5763fde57whesse@chromium.org  __ CallStub(&convert_stub);
4265b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4266b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Save result for postfix expressions.
4267b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  if (expr->is_postfix()) {
42684a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    if (!context()->IsEffect()) {
42694a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      // Save the result on the stack. If we have a named or keyed property
42704a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      // we store the result under the receiver that is currently on top
42714a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      // of the stack.
42724a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      switch (assign_type) {
42734a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        case VARIABLE:
4274763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org          __ Push(rax);
42754a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          break;
42764a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        case NAMED_PROPERTY:
427743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org          __ movp(Operand(rsp, kPointerSize), rax);
42784a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          break;
42794a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        case KEYED_PROPERTY:
428043c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org          __ movp(Operand(rsp, 2 * kPointerSize), rax);
42814a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          break;
42824a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      }
4283b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
4284b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
4285b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4286a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Record position before stub call.
4287a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  SetSourcePosition(expr->position());
4288a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4289b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Call stub for +1/-1.
4290e8412be858dc48afaec4959e42c5932f71a7f29bmachenbach@chromium.org  __ bind(&stub_call);
429143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rdx, rax);
4292fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org  __ Move(rax, Smi::FromInt(1));
4293f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  BinaryOpICStub stub(isolate(), expr->binary_op(), NO_OVERWRITE);
4294f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org  CallIC(stub.GetCode(), expr->CountBinOpFeedbackId());
42954f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  patch_site.EmitPatchInfo();
429683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  __ bind(&done);
4297d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com
4298b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Store the value returned in rax.
4299b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  switch (assign_type) {
4300b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    case VARIABLE:
4301b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      if (expr->is_postfix()) {
43029dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com        // Perform the assignment as if via '='.
43034a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        { EffectContext context(this);
43044a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
43054a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                                 Token::ASSIGN);
4306d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
43075f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org          context.Plug(rax);
43084a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        }
4309b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        // For all contexts except kEffect: We have the result on
4310b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        // top of the stack.
43114a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        if (!context()->IsEffect()) {
43124a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          context()->PlugTOS();
4313b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        }
4314b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      } else {
43159dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com        // Perform the assignment as if via '='.
4316b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
43174a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                               Token::ASSIGN);
4318d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
43195f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org        context()->Plug(rax);
4320b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      }
4321b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      break;
4322b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    case NAMED_PROPERTY: {
43231510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org      __ Move(rcx, prop->key()->AsLiteral()->value());
4324763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Pop(rdx);
4325f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      CallStoreIC(expr->CountStoreFeedbackId());
4326d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4327b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      if (expr->is_postfix()) {
43284a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        if (!context()->IsEffect()) {
43294a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          context()->PlugTOS();
4330b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        }
4331b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      } else {
43324a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        context()->Plug(rax);
4333b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      }
4334b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      break;
4335b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
4336b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    case KEYED_PROPERTY: {
4337763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Pop(rcx);
4338763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Pop(rdx);
4339486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      Handle<Code> ic = strict_mode() == SLOPPY
43401b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          ? isolate()->builtins()->KeyedStoreIC_Initialize()
43411b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
4342f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      CallIC(ic, expr->CountStoreFeedbackId());
4343d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4344b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      if (expr->is_postfix()) {
43454a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        if (!context()->IsEffect()) {
43464a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org          context()->PlugTOS();
4347b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org        }
4348b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      } else {
43494a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org        context()->Plug(rax);
4350b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      }
4351b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      break;
4352b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
4353b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
4354b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
4355b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4356b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
43574a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
435865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  VariableProxy* proxy = expr->AsVariableProxy();
43594a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  ASSERT(!context()->IsEffect());
43604a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  ASSERT(!context()->IsTest());
43614a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
4362486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  if (proxy != NULL && proxy->var()->IsUnallocated()) {
4363f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Comment cmnt(masm_, "[ Global variable");
436465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ Move(rcx, proxy->name());
436543c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rax, GlobalObjectOperand());
436665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Use a regular load, not a contextual load, to avoid a reference
436765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // error.
43689cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org    CallLoadIC(NOT_CONTEXTUAL);
4369d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    PrepareForBailout(expr, TOS_REG);
43704a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    context()->Plug(rax);
4371486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4372f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Comment cmnt(masm_, "[ Lookup slot");
43732ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    Label done, slow;
43742ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
43752ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    // Generate code for loading from variables potentially shadowed
43762ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    // by eval-introduced variables.
4377486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
43782ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
43792ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    __ bind(&slow);
4380763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(rsi);
438165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ Push(proxy->name());
4382895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org    __ CallRuntime(Runtime::kHiddenLoadContextSlotNoReferenceError, 2);
4383d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    PrepareForBailout(expr, TOS_REG);
43842ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org    __ bind(&done);
43852ec107fe650fe56eed094ca017940f26af46644bsgjesse@chromium.org
43864a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org    context()->Plug(rax);
43879dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  } else {
438865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // This expression cannot throw a reference error at the top level.
4389c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    VisitInDuplicateContext(expr);
439065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
439165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
439265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
439365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
439404921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.orgvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
4395c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org                                                 Expression* sub_expr,
4396c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                                 Handle<String> check) {
4397c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label materialize_true, materialize_false;
4398c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label* if_true = NULL;
4399c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label* if_false = NULL;
4400c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Label* fall_through = NULL;
4401c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  context()->PrepareTest(&materialize_true, &materialize_false,
4402c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                         &if_true, &if_false, &fall_through);
4403c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
44044a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  { AccumulatorValueContext context(this);
4405c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org    VisitForTypeofValue(sub_expr);
44064a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  }
4407c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
44084a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org
44092ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  Factory* factory = isolate()->factory();
44102ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  if (String::Equals(check, factory->number_string())) {
44118f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ JumpIfSmi(rax, if_true);
441243c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
441365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
441465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Split(equal, if_true, if_false, fall_through);
44152ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  } else if (String::Equals(check, factory->string_string())) {
44168f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ JumpIfSmi(rax, if_false);
441765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Check for undetectable objects => false.
44188f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
44198f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ j(above_equal, if_false);
442065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
442165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org             Immediate(1 << Map::kIsUndetectable));
44228f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    Split(zero, if_true, if_false, fall_through);
44232ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  } else if (String::Equals(check, factory->symbol_string())) {
4424f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    __ JumpIfSmi(rax, if_false);
4425f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    __ CmpObjectType(rax, SYMBOL_TYPE, rdx);
4426f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    Split(equal, if_true, if_false, fall_through);
44272ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  } else if (String::Equals(check, factory->boolean_string())) {
442865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
44299dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    __ j(equal, if_true);
443065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CompareRoot(rax, Heap::kFalseValueRootIndex);
443165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Split(equal, if_true, if_false, fall_through);
44324acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  } else if (FLAG_harmony_typeof &&
44332ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org             String::Equals(check, factory->null_string())) {
44344acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    __ CompareRoot(rax, Heap::kNullValueRootIndex);
44354acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    Split(equal, if_true, if_false, fall_through);
44362ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  } else if (String::Equals(check, factory->undefined_string())) {
443765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
44389dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com    __ j(equal, if_true);
44398f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ JumpIfSmi(rax, if_false);
444065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Check for undetectable objects => true.
444143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rdx, FieldOperand(rax, HeapObject::kMapOffset));
444265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
44439dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com             Immediate(1 << Map::kIsUndetectable));
444465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Split(not_zero, if_true, if_false, fall_through);
44452ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  } else if (String::Equals(check, factory->function_string())) {
44468f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ JumpIfSmi(rax, if_false);
4447c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
4448c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx);
4449c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ j(equal, if_true);
4450c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE);
4451c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Split(equal, if_true, if_false, fall_through);
44522ebef182c49d59eba907b120c3c2a50808bd1f12machenbach@chromium.org  } else if (String::Equals(check, factory->object_string())) {
44538f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ JumpIfSmi(rax, if_false);
44544acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    if (!FLAG_harmony_typeof) {
44554acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org      __ CompareRoot(rax, Heap::kNullValueRootIndex);
44564acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org      __ j(equal, if_true);
44574acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    }
4458d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    __ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx);
44598f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    __ j(below, if_false);
4460d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
4461d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org    __ j(above, if_false);
446265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    // Check for undetectable objects => false.
446365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
446465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org             Immediate(1 << Map::kIsUndetectable));
44658f806e8b8f108ca2c8899c5d31861ef1273dcd4akarlklose@chromium.org    Split(zero, if_true, if_false, fall_through);
446665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
446765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (if_false != fall_through) __ jmp(if_false);
44689dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  }
4469c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  context()->Plug(if_true, if_false);
44709dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com}
44719dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
44729dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
4473b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4474b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  Comment cmnt(masm_, "[ CompareOperation");
447565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  SetSourcePosition(expr->position());
4476b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4477c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // First we try a fast inlined version of the compare when one of
4478c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // the operands is a literal.
4479c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (TryLiteralCompare(expr)) return;
4480c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
4481b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Always perform the comparison for its control flow.  Pack the result
4482b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // into the expression's context after the comparison is performed.
44839dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label materialize_true, materialize_false;
44849dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_true = NULL;
44859dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com  Label* if_false = NULL;
448665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* fall_through = NULL;
44874a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
44884a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                         &if_true, &if_false, &fall_through);
448965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
449004921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org  Token::Value op = expr->op();
44914a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  VisitForStackValue(expr->left());
449265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  switch (op) {
4493b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    case Token::IN:
44944a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      VisitForStackValue(expr->right());
4495b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
4496c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
4497b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ CompareRoot(rax, Heap::kTrueValueRootIndex);
449865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      Split(equal, if_true, if_false, fall_through);
4499b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      break;
4500b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4501b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    case Token::INSTANCEOF: {
45024a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      VisitForStackValue(expr->right());
4503f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org      InstanceofStub stub(isolate(), InstanceofStub::kNoFlags);
4504b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ CallStub(&stub);
4505c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
45067a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org      __ testp(rax, rax);
450765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org       // The stub returns 0 for true.
450865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      Split(zero, if_true, if_false, fall_through);
4509b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      break;
4510b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
4511b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4512b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    default: {
45134a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org      VisitForAccumulatorValue(expr->right());
4514fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org      Condition cc = CompareIC::ComputeCondition(op);
4515763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org      __ Pop(rdx);
4516b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4517d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      bool inline_smi_code = ShouldInlineSmiCase(op);
4518d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com      JumpPatchSite patch_site(masm_);
4519d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      if (inline_smi_code) {
452083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        Label slow_case;
452143c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org        __ movp(rcx, rdx);
4522895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org        __ orp(rcx, rax);
452383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org        patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
45247a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org        __ cmpp(rdx, rax);
452565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org        Split(cc, if_true, if_false, NULL);
452665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org        __ bind(&slow_case);
452765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      }
4528b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4529d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com      // Record position and call the compare IC.
4530d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com      SetSourcePosition(expr->position());
45318432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org      Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
4532f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      CallIC(ic, expr->CompareOperationFeedbackId());
45334f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org      patch_site.EmitPatchInfo();
4534d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org
4535c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
45367a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org      __ testp(rax, rax);
453765fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      Split(cc, if_true, if_false, fall_through);
4538b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
4539b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
4540b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4541b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Convert the result of the comparison into one expected for this
4542b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // expression's context.
45434a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(if_true, if_false);
4544b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
4545b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4546b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4547c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
4548c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                              Expression* sub_expr,
4549c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                              NilValue nil) {
455065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label materialize_true, materialize_false;
455165fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* if_true = NULL;
455265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* if_false = NULL;
455365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  Label* fall_through = NULL;
45544a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->PrepareTest(&materialize_true, &materialize_false,
45554a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org                         &if_true, &if_false, &fall_through);
455665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
4557c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  VisitForAccumulatorValue(sub_expr);
4558c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4559837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org  if (expr->op() == Token::EQ_STRICT) {
4560ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    Heap::RootListIndex nil_value = nil == kNullValue ?
4561ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org        Heap::kNullValueRootIndex :
4562ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org        Heap::kUndefinedValueRootIndex;
4563ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org    __ CompareRoot(rax, nil_value);
456465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Split(equal, if_true, if_false, fall_through);
456565fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  } else {
4566837a67edd9afdbfe1b59482b41693f59c48846ffulan@chromium.org    Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
4567f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    CallIC(ic, expr->CompareOperationFeedbackId());
45687a1bfbe9bc8295770315c55f7ce40822b7951aabmachenbach@chromium.org    __ testp(rax, rax);
456965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    Split(not_zero, if_true, if_false, fall_through);
457065fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
45714a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(if_true, if_false);
457265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org}
457365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
457465fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
4575b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
457643c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
45774a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org  context()->Plug(rax);
4578b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
4579b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4580b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4581c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.orgRegister FullCodeGenerator::result_register() {
4582c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  return rax;
4583c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org}
4584c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org
4585c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org
4586c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.orgRegister FullCodeGenerator::context_register() {
4587c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org  return rsi;
4588c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org}
4589c20610af4f0ca150977ca140a1174f98ee46f5aafschneider@chromium.org
4590b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4591b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4592b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ASSERT(IsAligned(frame_offset, kPointerSize));
459343c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(Operand(rbp, frame_offset), value);
4594b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
4595b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4596b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4597b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::LoadContextField(Register dst, int context_index) {
459843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org  __ movp(dst, ContextOperand(rsi, context_index));
4599b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
4600b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4601b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
46023cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.orgvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
46034f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  Scope* declaration_scope = scope()->DeclarationScope();
4604ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  if (declaration_scope->is_global_scope() ||
4605ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      declaration_scope->is_module_scope()) {
460646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    // Contexts nested in the native context have a canonical empty function
46073cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    // as their closure, not the anonymous closure containing the global
46083cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    // code.  Pass a smi sentinel and let the runtime look up the empty
46093cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    // function.
46103cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    __ Push(Smi::FromInt(0));
46114f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  } else if (declaration_scope->is_eval_scope()) {
46123cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    // Contexts created by a call to eval have the same closure as the
46133cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    // context calling eval, not the anonymous closure containing the eval
46143cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org    // code.  Fetch it from the context.
4615763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(ContextOperand(rsi, Context::CLOSURE_INDEX));
46163cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  } else {
46174f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    ASSERT(declaration_scope->is_function_scope());
4618763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org    __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
46193cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org  }
46203cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org}
46213cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
46223cf47318da216c319ecf1f7a59de23455f117197vegorov@chromium.org
4623b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// ----------------------------------------------------------------------------
4624b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// Non-local control flow support.
4625b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4626b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4627b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::EnterFinallyBlock() {
4628b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ASSERT(!result_register().is(rdx));
4629b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ASSERT(!result_register().is(rcx));
4630b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Cook return address on top of stack (smi encoded Code* delta)
4631594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  __ PopReturnAddressTo(rdx);
4632b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  __ Move(rcx, masm_->CodeObject());
4633fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  __ subp(rdx, rcx);
4634b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  __ Integer32ToSmi(rdx, rdx);
4635763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rdx);
46367028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
4637b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Store result register while executing finally block.
4638763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(result_register());
46397028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
46407028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // Store pending message while executing finally block.
46417028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ExternalReference pending_message_obj =
46427028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      ExternalReference::address_of_pending_message_obj(isolate());
46437028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  __ Load(rdx, pending_message_obj);
4644763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rdx);
46457028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
46467028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ExternalReference has_pending_message =
46477028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      ExternalReference::address_of_has_pending_message(isolate());
46487028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  __ Load(rdx, has_pending_message);
4649753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  __ Integer32ToSmi(rdx, rdx);
4650763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rdx);
46517028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
46527028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ExternalReference pending_message_script =
46537028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      ExternalReference::address_of_pending_message_script(isolate());
46547028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  __ Load(rdx, pending_message_script);
4655763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Push(rdx);
4656b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
4657b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4658b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4659b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid FullCodeGenerator::ExitFinallyBlock() {
4660b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ASSERT(!result_register().is(rdx));
4661b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  ASSERT(!result_register().is(rcx));
46627028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // Restore pending message from stack.
4663763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rdx);
46647028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ExternalReference pending_message_script =
46657028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      ExternalReference::address_of_pending_message_script(isolate());
46667028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  __ Store(pending_message_script, rdx);
46677028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
4668763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rdx);
4669753aee4dcf0868130789b5af7c1eeb6ab2ab24f9verwaest@chromium.org  __ SmiToInteger32(rdx, rdx);
46707028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ExternalReference has_pending_message =
46717028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      ExternalReference::address_of_has_pending_message(isolate());
46727028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  __ Store(has_pending_message, rdx);
46737028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
4674763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rdx);
46757028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ExternalReference pending_message_obj =
46767028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      ExternalReference::address_of_pending_message_obj(isolate());
46777028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  __ Store(pending_message_obj, rdx);
46787028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
46797028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  // Restore result register from stack.
4680763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(result_register());
46817028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
4682b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  // Uncook return address.
4683763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  __ Pop(rdx);
4684b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  __ SmiToInteger32(rdx, rdx);
4685b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  __ Move(rcx, masm_->CodeObject());
4686fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  __ addp(rdx, rcx);
46874f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  __ jmp(rdx);
4688b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org}
4689b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4690b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4691b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org#undef __
4692b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4693486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org#define __ ACCESS_MASM(masm())
4694486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org
4695486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.orgFullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
4696486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    int* stack_depth,
4697486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    int* context_length) {
4698486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // The macros used here must preserve the result register.
4699486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org
4700486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // Because the handler block contains the context of the finally
4701486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // code, we can restore it directly from there for the finally code
4702486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // rather than iteratively unwinding contexts via their previous
4703486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  // links.
4704486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  __ Drop(*stack_depth);  // Down to the handler block.
4705486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  if (*context_length > 0) {
4706486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // Restore the context to its dedicated register and the stack.
470743c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(rsi, Operand(rsp, StackHandlerConstants::kContextOffset));
470843c51e51fafad9405752a3d7e953367531469575machenbach@chromium.org    __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
4709486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  }
4710486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  __ PopTryHandler();
4711486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  __ call(finally_entry_);
4712486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org
4713486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  *stack_depth = 0;
4714486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  *context_length = 0;
4715486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  return previous_;
4716486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org}
4717486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org
4718486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org
4719486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org#undef __
4720b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
4721528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
4722528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgstatic const byte kJnsInstruction = 0x79;
4723528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgstatic const byte kNopByteOne = 0x66;
4724528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgstatic const byte kNopByteTwo = 0x90;
4725afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org#ifdef DEBUG
4726afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.orgstatic const byte kCallInstruction = 0xe8;
4727afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org#endif
4728528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
4729528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
4730528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgvoid BackEdgeTable::PatchAt(Code* unoptimized_code,
47318e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org                            Address pc,
47328e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org                            BackEdgeState target_state,
4733528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                            Code* replacement_code) {
47348e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  Address call_target_address = pc - kIntSize;
47358e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  Address jns_instr_address = call_target_address - 3;
47368e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  Address jns_offset_address = call_target_address - 2;
47378e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
47388e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  switch (target_state) {
47398e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org    case INTERRUPT:
47408e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      //     sub <profiling_counter>, <delta>  ;; Not changed
47418e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      //     jns ok
47428e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      //     call <interrupt stub>
47438e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      //   ok:
47448e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      *jns_instr_address = kJnsInstruction;
47458e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      *jns_offset_address = kJnsOffset;
47468e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      break;
47478e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org    case ON_STACK_REPLACEMENT:
47488e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org    case OSR_AFTER_STACK_CHECK:
47498e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      //     sub <profiling_counter>, <delta>  ;; Not changed
47508e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      //     nop
47518e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      //     nop
47528e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      //     call <on-stack replacment>
47538e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      //   ok:
47548e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      *jns_instr_address = kNopByteOne;
47558e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      *jns_offset_address = kNopByteTwo;
47568e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      break;
47578e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  }
47588e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
4759528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Assembler::set_target_address_at(call_target_address,
476097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                   unoptimized_code,
4761528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org                                   replacement_code->entry());
4762528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
4763528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org      unoptimized_code, call_target_address, replacement_code);
4764528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org}
4765528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
4766528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
4767528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.orgBackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
4768528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    Isolate* isolate,
4769528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    Code* unoptimized_code,
47708e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org    Address pc) {
47718e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  Address call_target_address = pc - kIntSize;
47728e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  Address jns_instr_address = call_target_address - 3;
4773528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  ASSERT_EQ(kCallInstruction, *(call_target_address - 1));
47748e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
47758e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  if (*jns_instr_address == kJnsInstruction) {
47768e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org    ASSERT_EQ(kJnsOffset, *(call_target_address - 2));
47778e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org    ASSERT_EQ(isolate->builtins()->InterruptCheck()->entry(),
477897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org              Assembler::target_address_at(call_target_address,
477997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                           unoptimized_code));
4780528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org    return INTERRUPT;
4781528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  }
47828e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
47838e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  ASSERT_EQ(kNopByteOne, *jns_instr_address);
47848e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  ASSERT_EQ(kNopByteTwo, *(call_target_address - 2));
47858e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
478697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  if (Assembler::target_address_at(call_target_address,
478797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                   unoptimized_code) ==
47888e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org      isolate->builtins()->OnStackReplacement()->entry()) {
47898e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org    return ON_STACK_REPLACEMENT;
47908e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  }
47918e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org
47928e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
479397b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org            Assembler::target_address_at(call_target_address,
479497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                         unoptimized_code));
47958e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org  return OSR_AFTER_STACK_CHECK;
4796528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org}
4797528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
4798528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
4799b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org} }  // namespace v8::internal
48009dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
48019dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif  // V8_TARGET_ARCH_X64
4802