1// Copyright 2012 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#if defined(V8_TARGET_ARCH_X64)
31
32#include "code-stubs.h"
33#include "codegen.h"
34#include "compiler.h"
35#include "debug.h"
36#include "full-codegen.h"
37#include "parser.h"
38#include "scopes.h"
39#include "stub-cache.h"
40
41namespace v8 {
42namespace internal {
43
44#define __ ACCESS_MASM(masm_)
45
46
47class JumpPatchSite BASE_EMBEDDED {
48 public:
49  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
50#ifdef DEBUG
51    info_emitted_ = false;
52#endif
53  }
54
55  ~JumpPatchSite() {
56    ASSERT(patch_site_.is_bound() == info_emitted_);
57  }
58
59  void EmitJumpIfNotSmi(Register reg,
60                        Label* target,
61                        Label::Distance near_jump = Label::kFar) {
62    __ testb(reg, Immediate(kSmiTagMask));
63    EmitJump(not_carry, target, near_jump);   // Always taken before patched.
64  }
65
66  void EmitJumpIfSmi(Register reg,
67                     Label* target,
68                     Label::Distance near_jump = Label::kFar) {
69    __ testb(reg, Immediate(kSmiTagMask));
70    EmitJump(carry, target, near_jump);  // Never taken before patched.
71  }
72
73  void EmitPatchInfo() {
74    if (patch_site_.is_bound()) {
75      int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
76      ASSERT(is_int8(delta_to_patch_site));
77      __ testl(rax, Immediate(delta_to_patch_site));
78#ifdef DEBUG
79      info_emitted_ = true;
80#endif
81    } else {
82      __ nop();  // Signals no inlined code.
83    }
84  }
85
86 private:
87  // jc will be patched with jz, jnc will become jnz.
88  void EmitJump(Condition cc, Label* target, Label::Distance near_jump) {
89    ASSERT(!patch_site_.is_bound() && !info_emitted_);
90    ASSERT(cc == carry || cc == not_carry);
91    __ bind(&patch_site_);
92    __ j(cc, target, near_jump);
93  }
94
95  MacroAssembler* masm_;
96  Label patch_site_;
97#ifdef DEBUG
98  bool info_emitted_;
99#endif
100};
101
102
103int FullCodeGenerator::self_optimization_header_size() {
104  return 20;
105}
106
107
108// Generate code for a JS function.  On entry to the function the receiver
109// and arguments have been pushed on the stack left to right, with the
110// return address on top of them.  The actual argument count matches the
111// formal parameter count expected by the function.
112//
113// The live registers are:
114//   o rdi: the JS function object being called (i.e. ourselves)
115//   o rsi: our context
116//   o rbp: our caller's frame pointer
117//   o rsp: stack pointer (pointing to return address)
118//
119// The function builds a JS frame.  Please see JavaScriptFrameConstants in
120// frames-x64.h for its layout.
121void FullCodeGenerator::Generate() {
122  CompilationInfo* info = info_;
123  handler_table_ =
124      isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
125  SetFunctionPosition(function());
126  Comment cmnt(masm_, "[ function compiled by full code generator");
127
128  // We can optionally optimize based on counters rather than statistical
129  // sampling.
130  if (info->ShouldSelfOptimize()) {
131    if (FLAG_trace_opt_verbose) {
132      PrintF("[adding self-optimization header to %s]\n",
133             *info->function()->debug_name()->ToCString());
134    }
135    has_self_optimization_header_ = true;
136    MaybeObject* maybe_cell = isolate()->heap()->AllocateJSGlobalPropertyCell(
137        Smi::FromInt(Compiler::kCallsUntilPrimitiveOpt));
138    JSGlobalPropertyCell* cell;
139    if (maybe_cell->To(&cell)) {
140      __ movq(rax, Handle<JSGlobalPropertyCell>(cell),
141              RelocInfo::EMBEDDED_OBJECT);
142      __ SmiAddConstant(FieldOperand(rax, JSGlobalPropertyCell::kValueOffset),
143                        Smi::FromInt(-1));
144      Handle<Code> compile_stub(
145          isolate()->builtins()->builtin(Builtins::kLazyRecompile));
146      __ j(zero, compile_stub, RelocInfo::CODE_TARGET);
147      ASSERT(masm_->pc_offset() == self_optimization_header_size());
148    }
149  }
150
151#ifdef DEBUG
152  if (strlen(FLAG_stop_at) > 0 &&
153      info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
154    __ int3();
155  }
156#endif
157
158  // Strict mode functions and builtins need to replace the receiver
159  // with undefined when called as functions (without an explicit
160  // receiver object). rcx is zero for method calls and non-zero for
161  // function calls.
162  if (!info->is_classic_mode() || info->is_native()) {
163    Label ok;
164    __ testq(rcx, rcx);
165    __ j(zero, &ok, Label::kNear);
166    // +1 for return address.
167    int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
168    __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
169    __ movq(Operand(rsp, receiver_offset), kScratchRegister);
170    __ bind(&ok);
171  }
172
173  // Open a frame scope to indicate that there is a frame on the stack.  The
174  // MANUAL indicates that the scope shouldn't actually generate code to set up
175  // the frame (that is done below).
176  FrameScope frame_scope(masm_, StackFrame::MANUAL);
177
178  __ push(rbp);  // Caller's frame pointer.
179  __ movq(rbp, rsp);
180  __ push(rsi);  // Callee's context.
181  __ push(rdi);  // Callee's JS Function.
182
183  { Comment cmnt(masm_, "[ Allocate locals");
184    int locals_count = info->scope()->num_stack_slots();
185    if (locals_count == 1) {
186      __ PushRoot(Heap::kUndefinedValueRootIndex);
187    } else if (locals_count > 1) {
188      __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
189      for (int i = 0; i < locals_count; i++) {
190        __ push(rdx);
191      }
192    }
193  }
194
195  bool function_in_register = true;
196
197  // Possibly allocate a local context.
198  int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
199  if (heap_slots > 0) {
200    Comment cmnt(masm_, "[ Allocate local context");
201    // Argument to NewContext is the function, which is still in rdi.
202    __ push(rdi);
203    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
204      FastNewContextStub stub(heap_slots);
205      __ CallStub(&stub);
206    } else {
207      __ CallRuntime(Runtime::kNewFunctionContext, 1);
208    }
209    function_in_register = false;
210    // Context is returned in both rax and rsi.  It replaces the context
211    // passed to us.  It's saved in the stack and kept live in rsi.
212    __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
213
214    // Copy any necessary parameters into the context.
215    int num_parameters = info->scope()->num_parameters();
216    for (int i = 0; i < num_parameters; i++) {
217      Variable* var = scope()->parameter(i);
218      if (var->IsContextSlot()) {
219        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
220            (num_parameters - 1 - i) * kPointerSize;
221        // Load parameter from stack.
222        __ movq(rax, Operand(rbp, parameter_offset));
223        // Store it in the context.
224        int context_offset = Context::SlotOffset(var->index());
225        __ movq(Operand(rsi, context_offset), rax);
226        // Update the write barrier.  This clobbers rax and rbx.
227        __ RecordWriteContextSlot(
228            rsi, context_offset, rax, rbx, kDontSaveFPRegs);
229      }
230    }
231  }
232
233  // Possibly allocate an arguments object.
234  Variable* arguments = scope()->arguments();
235  if (arguments != NULL) {
236    // Arguments object must be allocated after the context object, in
237    // case the "arguments" or ".arguments" variables are in the context.
238    Comment cmnt(masm_, "[ Allocate arguments object");
239    if (function_in_register) {
240      __ push(rdi);
241    } else {
242      __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
243    }
244    // The receiver is just before the parameters on the caller's stack.
245    int num_parameters = info->scope()->num_parameters();
246    int offset = num_parameters * kPointerSize;
247    __ lea(rdx,
248           Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
249    __ push(rdx);
250    __ Push(Smi::FromInt(num_parameters));
251    // Arguments to ArgumentsAccessStub:
252    //   function, receiver address, parameter count.
253    // The stub will rewrite receiver and parameter count if the previous
254    // stack frame was an arguments adapter frame.
255    ArgumentsAccessStub::Type type;
256    if (!is_classic_mode()) {
257      type = ArgumentsAccessStub::NEW_STRICT;
258    } else if (function()->has_duplicate_parameters()) {
259      type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
260    } else {
261      type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
262    }
263    ArgumentsAccessStub stub(type);
264    __ CallStub(&stub);
265
266    SetVar(arguments, rax, rbx, rdx);
267  }
268
269  if (FLAG_trace) {
270    __ CallRuntime(Runtime::kTraceEnter, 0);
271  }
272
273  // Visit the declarations and body unless there is an illegal
274  // redeclaration.
275  if (scope()->HasIllegalRedeclaration()) {
276    Comment cmnt(masm_, "[ Declarations");
277    scope()->VisitIllegalRedeclaration(this);
278
279  } else {
280    PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
281    { Comment cmnt(masm_, "[ Declarations");
282      // For named function expressions, declare the function name as a
283      // constant.
284      if (scope()->is_function_scope() && scope()->function() != NULL) {
285        VariableProxy* proxy = scope()->function();
286        ASSERT(proxy->var()->mode() == CONST ||
287               proxy->var()->mode() == CONST_HARMONY);
288        ASSERT(proxy->var()->location() != Variable::UNALLOCATED);
289        EmitDeclaration(proxy, proxy->var()->mode(), NULL);
290      }
291      VisitDeclarations(scope()->declarations());
292    }
293
294    { Comment cmnt(masm_, "[ Stack check");
295      PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS);
296      Label ok;
297      __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
298      __ j(above_equal, &ok, Label::kNear);
299      StackCheckStub stub;
300      __ CallStub(&stub);
301      __ bind(&ok);
302    }
303
304    { Comment cmnt(masm_, "[ Body");
305      ASSERT(loop_depth() == 0);
306      VisitStatements(function()->body());
307      ASSERT(loop_depth() == 0);
308    }
309  }
310
311  // Always emit a 'return undefined' in case control fell off the end of
312  // the body.
313  { Comment cmnt(masm_, "[ return <undefined>;");
314    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
315    EmitReturnSequence();
316  }
317}
318
319
320void FullCodeGenerator::ClearAccumulator() {
321  __ Set(rax, 0);
322}
323
324
325void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt,
326                                       Label* back_edge_target) {
327  Comment cmnt(masm_, "[ Stack check");
328  Label ok;
329  __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
330  __ j(above_equal, &ok, Label::kNear);
331  StackCheckStub stub;
332  __ CallStub(&stub);
333  // Record a mapping of this PC offset to the OSR id.  This is used to find
334  // the AST id from the unoptimized code in order to use it as a key into
335  // the deoptimization input data found in the optimized code.
336  RecordStackCheck(stmt->OsrEntryId());
337
338  // Loop stack checks can be patched to perform on-stack replacement. In
339  // order to decide whether or not to perform OSR we embed the loop depth
340  // in a test instruction after the call so we can extract it from the OSR
341  // builtin.
342  ASSERT(loop_depth() > 0);
343  __ testl(rax, Immediate(Min(loop_depth(), Code::kMaxLoopNestingMarker)));
344
345  __ bind(&ok);
346  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
347  // Record a mapping of the OSR id to this PC.  This is used if the OSR
348  // entry becomes the target of a bailout.  We don't expect it to be, but
349  // we want it to work if it is.
350  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
351}
352
353
354void FullCodeGenerator::EmitReturnSequence() {
355  Comment cmnt(masm_, "[ Return sequence");
356  if (return_label_.is_bound()) {
357    __ jmp(&return_label_);
358  } else {
359    __ bind(&return_label_);
360    if (FLAG_trace) {
361      __ push(rax);
362      __ CallRuntime(Runtime::kTraceExit, 1);
363    }
364#ifdef DEBUG
365    // Add a label for checking the size of the code used for returning.
366    Label check_exit_codesize;
367    masm_->bind(&check_exit_codesize);
368#endif
369    CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
370    __ RecordJSReturn();
371    // Do not use the leave instruction here because it is too short to
372    // patch with the code required by the debugger.
373    __ movq(rsp, rbp);
374    __ pop(rbp);
375
376    int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize;
377    __ Ret(arguments_bytes, rcx);
378
379#ifdef ENABLE_DEBUGGER_SUPPORT
380    // Add padding that will be overwritten by a debugger breakpoint.  We
381    // have just generated at least 7 bytes: "movq rsp, rbp; pop rbp; ret k"
382    // (3 + 1 + 3).
383    const int kPadding = Assembler::kJSReturnSequenceLength - 7;
384    for (int i = 0; i < kPadding; ++i) {
385      masm_->int3();
386    }
387    // Check that the size of the code used for returning is large enough
388    // for the debugger's requirements.
389    ASSERT(Assembler::kJSReturnSequenceLength <=
390           masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
391#endif
392  }
393}
394
395
396void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
397  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
398}
399
400
401void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
402  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
403  codegen()->GetVar(result_register(), var);
404}
405
406
407void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
408  ASSERT(var->IsStackAllocated() || var->IsContextSlot());
409  MemOperand operand = codegen()->VarOperand(var, result_register());
410  __ push(operand);
411}
412
413
414void FullCodeGenerator::TestContext::Plug(Variable* var) const {
415  codegen()->GetVar(result_register(), var);
416  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
417  codegen()->DoTest(this);
418}
419
420
421void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
422}
423
424
425void FullCodeGenerator::AccumulatorValueContext::Plug(
426    Heap::RootListIndex index) const {
427  __ LoadRoot(result_register(), index);
428}
429
430
431void FullCodeGenerator::StackValueContext::Plug(
432    Heap::RootListIndex index) const {
433  __ PushRoot(index);
434}
435
436
437void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
438  codegen()->PrepareForBailoutBeforeSplit(condition(),
439                                          true,
440                                          true_label_,
441                                          false_label_);
442  if (index == Heap::kUndefinedValueRootIndex ||
443      index == Heap::kNullValueRootIndex ||
444      index == Heap::kFalseValueRootIndex) {
445    if (false_label_ != fall_through_) __ jmp(false_label_);
446  } else if (index == Heap::kTrueValueRootIndex) {
447    if (true_label_ != fall_through_) __ jmp(true_label_);
448  } else {
449    __ LoadRoot(result_register(), index);
450    codegen()->DoTest(this);
451  }
452}
453
454
455void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
456}
457
458
459void FullCodeGenerator::AccumulatorValueContext::Plug(
460    Handle<Object> lit) const {
461  __ Move(result_register(), lit);
462}
463
464
465void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
466  __ Push(lit);
467}
468
469
470void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
471  codegen()->PrepareForBailoutBeforeSplit(condition(),
472                                          true,
473                                          true_label_,
474                                          false_label_);
475  ASSERT(!lit->IsUndetectableObject());  // There are no undetectable literals.
476  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
477    if (false_label_ != fall_through_) __ jmp(false_label_);
478  } else if (lit->IsTrue() || lit->IsJSObject()) {
479    if (true_label_ != fall_through_) __ jmp(true_label_);
480  } else if (lit->IsString()) {
481    if (String::cast(*lit)->length() == 0) {
482      if (false_label_ != fall_through_) __ jmp(false_label_);
483    } else {
484      if (true_label_ != fall_through_) __ jmp(true_label_);
485    }
486  } else if (lit->IsSmi()) {
487    if (Smi::cast(*lit)->value() == 0) {
488      if (false_label_ != fall_through_) __ jmp(false_label_);
489    } else {
490      if (true_label_ != fall_through_) __ jmp(true_label_);
491    }
492  } else {
493    // For simplicity we always test the accumulator register.
494    __ Move(result_register(), lit);
495    codegen()->DoTest(this);
496  }
497}
498
499
500void FullCodeGenerator::EffectContext::DropAndPlug(int count,
501                                                   Register reg) const {
502  ASSERT(count > 0);
503  __ Drop(count);
504}
505
506
507void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
508    int count,
509    Register reg) const {
510  ASSERT(count > 0);
511  __ Drop(count);
512  __ Move(result_register(), reg);
513}
514
515
516void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
517                                                       Register reg) const {
518  ASSERT(count > 0);
519  if (count > 1) __ Drop(count - 1);
520  __ movq(Operand(rsp, 0), reg);
521}
522
523
524void FullCodeGenerator::TestContext::DropAndPlug(int count,
525                                                 Register reg) const {
526  ASSERT(count > 0);
527  // For simplicity we always test the accumulator register.
528  __ Drop(count);
529  __ Move(result_register(), reg);
530  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
531  codegen()->DoTest(this);
532}
533
534
535void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
536                                            Label* materialize_false) const {
537  ASSERT(materialize_true == materialize_false);
538  __ bind(materialize_true);
539}
540
541
542void FullCodeGenerator::AccumulatorValueContext::Plug(
543    Label* materialize_true,
544    Label* materialize_false) const {
545  Label done;
546  __ bind(materialize_true);
547  __ Move(result_register(), isolate()->factory()->true_value());
548  __ jmp(&done, Label::kNear);
549  __ bind(materialize_false);
550  __ Move(result_register(), isolate()->factory()->false_value());
551  __ bind(&done);
552}
553
554
555void FullCodeGenerator::StackValueContext::Plug(
556    Label* materialize_true,
557    Label* materialize_false) const {
558  Label done;
559  __ bind(materialize_true);
560  __ Push(isolate()->factory()->true_value());
561  __ jmp(&done, Label::kNear);
562  __ bind(materialize_false);
563  __ Push(isolate()->factory()->false_value());
564  __ bind(&done);
565}
566
567
568void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
569                                          Label* materialize_false) const {
570  ASSERT(materialize_true == true_label_);
571  ASSERT(materialize_false == false_label_);
572}
573
574
575void FullCodeGenerator::EffectContext::Plug(bool flag) const {
576}
577
578
579void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
580  Heap::RootListIndex value_root_index =
581      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
582  __ LoadRoot(result_register(), value_root_index);
583}
584
585
586void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
587  Heap::RootListIndex value_root_index =
588      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
589  __ PushRoot(value_root_index);
590}
591
592
593void FullCodeGenerator::TestContext::Plug(bool flag) const {
594  codegen()->PrepareForBailoutBeforeSplit(condition(),
595                                          true,
596                                          true_label_,
597                                          false_label_);
598  if (flag) {
599    if (true_label_ != fall_through_) __ jmp(true_label_);
600  } else {
601    if (false_label_ != fall_through_) __ jmp(false_label_);
602  }
603}
604
605
606void FullCodeGenerator::DoTest(Expression* condition,
607                               Label* if_true,
608                               Label* if_false,
609                               Label* fall_through) {
610  ToBooleanStub stub(result_register());
611  __ push(result_register());
612  __ CallStub(&stub);
613  __ testq(result_register(), result_register());
614  // The stub returns nonzero for true.
615  Split(not_zero, if_true, if_false, fall_through);
616}
617
618
619void FullCodeGenerator::Split(Condition cc,
620                              Label* if_true,
621                              Label* if_false,
622                              Label* fall_through) {
623  if (if_false == fall_through) {
624    __ j(cc, if_true);
625  } else if (if_true == fall_through) {
626    __ j(NegateCondition(cc), if_false);
627  } else {
628    __ j(cc, if_true);
629    __ jmp(if_false);
630  }
631}
632
633
634MemOperand FullCodeGenerator::StackOperand(Variable* var) {
635  ASSERT(var->IsStackAllocated());
636  // Offset is negative because higher indexes are at lower addresses.
637  int offset = -var->index() * kPointerSize;
638  // Adjust by a (parameter or local) base offset.
639  if (var->IsParameter()) {
640    offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
641  } else {
642    offset += JavaScriptFrameConstants::kLocal0Offset;
643  }
644  return Operand(rbp, offset);
645}
646
647
648MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
649  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
650  if (var->IsContextSlot()) {
651    int context_chain_length = scope()->ContextChainLength(var->scope());
652    __ LoadContext(scratch, context_chain_length);
653    return ContextOperand(scratch, var->index());
654  } else {
655    return StackOperand(var);
656  }
657}
658
659
660void FullCodeGenerator::GetVar(Register dest, Variable* var) {
661  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
662  MemOperand location = VarOperand(var, dest);
663  __ movq(dest, location);
664}
665
666
667void FullCodeGenerator::SetVar(Variable* var,
668                               Register src,
669                               Register scratch0,
670                               Register scratch1) {
671  ASSERT(var->IsContextSlot() || var->IsStackAllocated());
672  ASSERT(!scratch0.is(src));
673  ASSERT(!scratch0.is(scratch1));
674  ASSERT(!scratch1.is(src));
675  MemOperand location = VarOperand(var, scratch0);
676  __ movq(location, src);
677
678  // Emit the write barrier code if the location is in the heap.
679  if (var->IsContextSlot()) {
680    int offset = Context::SlotOffset(var->index());
681    __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
682  }
683}
684
685
686void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
687                                                     bool should_normalize,
688                                                     Label* if_true,
689                                                     Label* if_false) {
690  // Only prepare for bailouts before splits if we're in a test
691  // context. Otherwise, we let the Visit function deal with the
692  // preparation to avoid preparing with the same AST id twice.
693  if (!context()->IsTest() || !info_->IsOptimizable()) return;
694
695  Label skip;
696  if (should_normalize) __ jmp(&skip, Label::kNear);
697  PrepareForBailout(expr, TOS_REG);
698  if (should_normalize) {
699    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
700    Split(equal, if_true, if_false, NULL);
701    __ bind(&skip);
702  }
703}
704
705
706void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
707                                        VariableMode mode,
708                                        FunctionLiteral* function) {
709  // If it was not possible to allocate the variable at compile time, we
710  // need to "declare" it at runtime to make sure it actually exists in the
711  // local context.
712  Variable* variable = proxy->var();
713  bool binding_needs_init = (function == NULL) &&
714      (mode == CONST || mode == CONST_HARMONY || mode == LET);
715  switch (variable->location()) {
716    case Variable::UNALLOCATED:
717      ++global_count_;
718      break;
719
720    case Variable::PARAMETER:
721    case Variable::LOCAL:
722      if (function != NULL) {
723        Comment cmnt(masm_, "[ Declaration");
724        VisitForAccumulatorValue(function);
725        __ movq(StackOperand(variable), result_register());
726      } else if (binding_needs_init) {
727        Comment cmnt(masm_, "[ Declaration");
728        __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
729        __ movq(StackOperand(variable), kScratchRegister);
730      }
731      break;
732
733    case Variable::CONTEXT:
734      // The variable in the decl always resides in the current function
735      // context.
736      ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
737      if (FLAG_debug_code) {
738        // Check that we're not inside a with or catch context.
739        __ movq(rbx, FieldOperand(rsi, HeapObject::kMapOffset));
740        __ CompareRoot(rbx, Heap::kWithContextMapRootIndex);
741        __ Check(not_equal, "Declaration in with context.");
742        __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
743        __ Check(not_equal, "Declaration in catch context.");
744      }
745      if (function != NULL) {
746        Comment cmnt(masm_, "[ Declaration");
747        VisitForAccumulatorValue(function);
748        __ movq(ContextOperand(rsi, variable->index()), result_register());
749        int offset = Context::SlotOffset(variable->index());
750        // We know that we have written a function, which is not a smi.
751        __ RecordWriteContextSlot(rsi,
752                                  offset,
753                                  result_register(),
754                                  rcx,
755                                  kDontSaveFPRegs,
756                                  EMIT_REMEMBERED_SET,
757                                  OMIT_SMI_CHECK);
758        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
759      } else if (binding_needs_init) {
760        Comment cmnt(masm_, "[ Declaration");
761        __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
762        __ movq(ContextOperand(rsi, variable->index()), kScratchRegister);
763        // No write barrier since the hole value is in old space.
764        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
765      }
766      break;
767
768    case Variable::LOOKUP: {
769      Comment cmnt(masm_, "[ Declaration");
770      __ push(rsi);
771      __ Push(variable->name());
772      // Declaration nodes are always introduced in one of four modes.
773      ASSERT(mode == VAR ||
774             mode == CONST ||
775             mode == CONST_HARMONY ||
776             mode == LET);
777      PropertyAttributes attr =
778          (mode == CONST || mode == CONST_HARMONY) ? READ_ONLY : NONE;
779      __ Push(Smi::FromInt(attr));
780      // Push initial value, if any.
781      // Note: For variables we must not push an initial value (such as
782      // 'undefined') because we may have a (legal) redeclaration and we
783      // must not destroy the current value.
784      if (function != NULL) {
785        VisitForStackValue(function);
786      } else if (binding_needs_init) {
787        __ PushRoot(Heap::kTheHoleValueRootIndex);
788      } else {
789        __ Push(Smi::FromInt(0));  // Indicates no initial value.
790      }
791      __ CallRuntime(Runtime::kDeclareContextSlot, 4);
792      break;
793    }
794  }
795}
796
797
798void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
799  // Call the runtime to declare the globals.
800  __ push(rsi);  // The context is the first argument.
801  __ Push(pairs);
802  __ Push(Smi::FromInt(DeclareGlobalsFlags()));
803  __ CallRuntime(Runtime::kDeclareGlobals, 3);
804  // Return value is ignored.
805}
806
807
808void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
809  Comment cmnt(masm_, "[ SwitchStatement");
810  Breakable nested_statement(this, stmt);
811  SetStatementPosition(stmt);
812
813  // Keep the switch value on the stack until a case matches.
814  VisitForStackValue(stmt->tag());
815  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
816
817  ZoneList<CaseClause*>* clauses = stmt->cases();
818  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
819
820  Label next_test;  // Recycled for each test.
821  // Compile all the tests with branches to their bodies.
822  for (int i = 0; i < clauses->length(); i++) {
823    CaseClause* clause = clauses->at(i);
824    clause->body_target()->Unuse();
825
826    // The default is not a test, but remember it as final fall through.
827    if (clause->is_default()) {
828      default_clause = clause;
829      continue;
830    }
831
832    Comment cmnt(masm_, "[ Case comparison");
833    __ bind(&next_test);
834    next_test.Unuse();
835
836    // Compile the label expression.
837    VisitForAccumulatorValue(clause->label());
838
839    // Perform the comparison as if via '==='.
840    __ movq(rdx, Operand(rsp, 0));  // Switch value.
841    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
842    JumpPatchSite patch_site(masm_);
843    if (inline_smi_code) {
844      Label slow_case;
845      __ movq(rcx, rdx);
846      __ or_(rcx, rax);
847      patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
848
849      __ cmpq(rdx, rax);
850      __ j(not_equal, &next_test);
851      __ Drop(1);  // Switch value is no longer needed.
852      __ jmp(clause->body_target());
853      __ bind(&slow_case);
854    }
855
856    // Record position before stub call for type feedback.
857    SetSourcePosition(clause->position());
858    Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
859    __ call(ic, RelocInfo::CODE_TARGET, clause->CompareId());
860    patch_site.EmitPatchInfo();
861
862    __ testq(rax, rax);
863    __ j(not_equal, &next_test);
864    __ Drop(1);  // Switch value is no longer needed.
865    __ jmp(clause->body_target());
866  }
867
868  // Discard the test value and jump to the default if present, otherwise to
869  // the end of the statement.
870  __ bind(&next_test);
871  __ Drop(1);  // Switch value is no longer needed.
872  if (default_clause == NULL) {
873    __ jmp(nested_statement.break_label());
874  } else {
875    __ jmp(default_clause->body_target());
876  }
877
878  // Compile all the case bodies.
879  for (int i = 0; i < clauses->length(); i++) {
880    Comment cmnt(masm_, "[ Case body");
881    CaseClause* clause = clauses->at(i);
882    __ bind(clause->body_target());
883    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
884    VisitStatements(clause->statements());
885  }
886
887  __ bind(nested_statement.break_label());
888  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
889}
890
891
892void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
893  Comment cmnt(masm_, "[ ForInStatement");
894  SetStatementPosition(stmt);
895
896  Label loop, exit;
897  ForIn loop_statement(this, stmt);
898  increment_loop_depth();
899
900  // Get the object to enumerate over. Both SpiderMonkey and JSC
901  // ignore null and undefined in contrast to the specification; see
902  // ECMA-262 section 12.6.4.
903  VisitForAccumulatorValue(stmt->enumerable());
904  __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
905  __ j(equal, &exit);
906  Register null_value = rdi;
907  __ LoadRoot(null_value, Heap::kNullValueRootIndex);
908  __ cmpq(rax, null_value);
909  __ j(equal, &exit);
910
911  PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
912
913  // Convert the object to a JS object.
914  Label convert, done_convert;
915  __ JumpIfSmi(rax, &convert);
916  __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
917  __ j(above_equal, &done_convert);
918  __ bind(&convert);
919  __ push(rax);
920  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
921  __ bind(&done_convert);
922  __ push(rax);
923
924  // Check for proxies.
925  Label call_runtime;
926  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
927  __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx);
928  __ j(below_equal, &call_runtime);
929
930  // Check cache validity in generated code. This is a fast case for
931  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
932  // guarantee cache validity, call the runtime system to check cache
933  // validity or get the property names in a fixed array.
934  __ CheckEnumCache(null_value, &call_runtime);
935
936  // The enum cache is valid.  Load the map of the object being
937  // iterated over and use the cache for the iteration.
938  Label use_cache;
939  __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
940  __ jmp(&use_cache, Label::kNear);
941
942  // Get the set of properties to enumerate.
943  __ bind(&call_runtime);
944  __ push(rax);  // Duplicate the enumerable object on the stack.
945  __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
946
947  // If we got a map from the runtime call, we can do a fast
948  // modification check. Otherwise, we got a fixed array, and we have
949  // to do a slow check.
950  Label fixed_array;
951  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
952                 Heap::kMetaMapRootIndex);
953  __ j(not_equal, &fixed_array, Label::kNear);
954
955  // We got a map in register rax. Get the enumeration cache from it.
956  __ bind(&use_cache);
957  __ LoadInstanceDescriptors(rax, rcx);
958  __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset));
959  __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
960
961  // Set up the four remaining stack slots.
962  __ push(rax);  // Map.
963  __ push(rdx);  // Enumeration cache.
964  __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset));
965  __ push(rax);  // Enumeration cache length (as smi).
966  __ Push(Smi::FromInt(0));  // Initial index.
967  __ jmp(&loop);
968
969  // We got a fixed array in register rax. Iterate through that.
970  Label non_proxy;
971  __ bind(&fixed_array);
972
973  Handle<JSGlobalPropertyCell> cell =
974      isolate()->factory()->NewJSGlobalPropertyCell(
975          Handle<Object>(
976              Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker)));
977  RecordTypeFeedbackCell(stmt->PrepareId(), cell);
978  __ LoadHeapObject(rbx, cell);
979  __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
980          Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker));
981
982  __ Move(rbx, Smi::FromInt(1));  // Smi indicates slow check
983  __ movq(rcx, Operand(rsp, 0 * kPointerSize));  // Get enumerated object
984  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
985  __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx);
986  __ j(above, &non_proxy);
987  __ Move(rbx, Smi::FromInt(0));  // Zero indicates proxy
988  __ bind(&non_proxy);
989  __ push(rbx);  // Smi
990  __ push(rax);  // Array
991  __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset));
992  __ push(rax);  // Fixed array length (as smi).
993  __ Push(Smi::FromInt(0));  // Initial index.
994
995  // Generate code for doing the condition check.
996  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
997  __ bind(&loop);
998  __ movq(rax, Operand(rsp, 0 * kPointerSize));  // Get the current index.
999  __ cmpq(rax, Operand(rsp, 1 * kPointerSize));  // Compare to the array length.
1000  __ j(above_equal, loop_statement.break_label());
1001
1002  // Get the current entry of the array into register rbx.
1003  __ movq(rbx, Operand(rsp, 2 * kPointerSize));
1004  SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2);
1005  __ movq(rbx, FieldOperand(rbx,
1006                            index.reg,
1007                            index.scale,
1008                            FixedArray::kHeaderSize));
1009
1010  // Get the expected map from the stack or a smi in the
1011  // permanent slow case into register rdx.
1012  __ movq(rdx, Operand(rsp, 3 * kPointerSize));
1013
1014  // Check if the expected map still matches that of the enumerable.
1015  // If not, we may have to filter the key.
1016  Label update_each;
1017  __ movq(rcx, Operand(rsp, 4 * kPointerSize));
1018  __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset));
1019  __ j(equal, &update_each, Label::kNear);
1020
1021  // For proxies, no filtering is done.
1022  // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
1023  __ Cmp(rdx, Smi::FromInt(0));
1024  __ j(equal, &update_each, Label::kNear);
1025
1026  // Convert the entry to a string or null if it isn't a property
1027  // anymore. If the property has been removed while iterating, we
1028  // just skip it.
1029  __ push(rcx);  // Enumerable.
1030  __ push(rbx);  // Current entry.
1031  __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1032  __ Cmp(rax, Smi::FromInt(0));
1033  __ j(equal, loop_statement.continue_label());
1034  __ movq(rbx, rax);
1035
1036  // Update the 'each' property or variable from the possibly filtered
1037  // entry in register rbx.
1038  __ bind(&update_each);
1039  __ movq(result_register(), rbx);
1040  // Perform the assignment as if via '='.
1041  { EffectContext context(this);
1042    EmitAssignment(stmt->each());
1043  }
1044
1045  // Generate code for the body of the loop.
1046  Visit(stmt->body());
1047
1048  // Generate code for going to the next element by incrementing the
1049  // index (smi) stored on top of the stack.
1050  __ bind(loop_statement.continue_label());
1051  __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1));
1052
1053  EmitStackCheck(stmt, &loop);
1054  __ jmp(&loop);
1055
1056  // Remove the pointers stored on the stack.
1057  __ bind(loop_statement.break_label());
1058  __ addq(rsp, Immediate(5 * kPointerSize));
1059
1060  // Exit and decrement the loop depth.
1061  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1062  __ bind(&exit);
1063  decrement_loop_depth();
1064}
1065
1066
1067void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
1068                                       bool pretenure) {
1069  // Use the fast case closure allocation code that allocates in new
1070  // space for nested functions that don't need literals cloning. If
1071  // we're running with the --always-opt or the --prepare-always-opt
1072  // flag, we need to use the runtime function so that the new function
1073  // we are creating here gets a chance to have its code optimized and
1074  // doesn't just get a copy of the existing unoptimized code.
1075  if (!FLAG_always_opt &&
1076      !FLAG_prepare_always_opt &&
1077      !pretenure &&
1078      scope()->is_function_scope() &&
1079      info->num_literals() == 0) {
1080    FastNewClosureStub stub(info->language_mode());
1081    __ Push(info);
1082    __ CallStub(&stub);
1083  } else {
1084    __ push(rsi);
1085    __ Push(info);
1086    __ Push(pretenure
1087            ? isolate()->factory()->true_value()
1088            : isolate()->factory()->false_value());
1089    __ CallRuntime(Runtime::kNewClosure, 3);
1090  }
1091  context()->Plug(rax);
1092}
1093
1094
1095void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
1096  Comment cmnt(masm_, "[ VariableProxy");
1097  EmitVariableLoad(expr);
1098}
1099
1100
1101void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
1102                                                      TypeofState typeof_state,
1103                                                      Label* slow) {
1104  Register context = rsi;
1105  Register temp = rdx;
1106
1107  Scope* s = scope();
1108  while (s != NULL) {
1109    if (s->num_heap_slots() > 0) {
1110      if (s->calls_non_strict_eval()) {
1111        // Check that extension is NULL.
1112        __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
1113                Immediate(0));
1114        __ j(not_equal, slow);
1115      }
1116      // Load next context in chain.
1117      __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1118      // Walk the rest of the chain without clobbering rsi.
1119      context = temp;
1120    }
1121    // If no outer scope calls eval, we do not need to check more
1122    // context extensions.  If we have reached an eval scope, we check
1123    // all extensions from this point.
1124    if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break;
1125    s = s->outer_scope();
1126  }
1127
1128  if (s != NULL && s->is_eval_scope()) {
1129    // Loop up the context chain.  There is no frame effect so it is
1130    // safe to use raw labels here.
1131    Label next, fast;
1132    if (!context.is(temp)) {
1133      __ movq(temp, context);
1134    }
1135    // Load map for comparison into register, outside loop.
1136    __ LoadRoot(kScratchRegister, Heap::kGlobalContextMapRootIndex);
1137    __ bind(&next);
1138    // Terminate at global context.
1139    __ cmpq(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset));
1140    __ j(equal, &fast, Label::kNear);
1141    // Check that extension is NULL.
1142    __ cmpq(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
1143    __ j(not_equal, slow);
1144    // Load next context in chain.
1145    __ movq(temp, ContextOperand(temp, Context::PREVIOUS_INDEX));
1146    __ jmp(&next);
1147    __ bind(&fast);
1148  }
1149
1150  // All extension objects were empty and it is safe to use a global
1151  // load IC call.
1152  __ movq(rax, GlobalObjectOperand());
1153  __ Move(rcx, var->name());
1154  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1155  RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
1156      ? RelocInfo::CODE_TARGET
1157      : RelocInfo::CODE_TARGET_CONTEXT;
1158  __ call(ic, mode);
1159}
1160
1161
1162MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1163                                                                Label* slow) {
1164  ASSERT(var->IsContextSlot());
1165  Register context = rsi;
1166  Register temp = rbx;
1167
1168  for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
1169    if (s->num_heap_slots() > 0) {
1170      if (s->calls_non_strict_eval()) {
1171        // Check that extension is NULL.
1172        __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
1173                Immediate(0));
1174        __ j(not_equal, slow);
1175      }
1176      __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1177      // Walk the rest of the chain without clobbering rsi.
1178      context = temp;
1179    }
1180  }
1181  // Check that last extension is NULL.
1182  __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
1183  __ j(not_equal, slow);
1184
1185  // This function is used only for loads, not stores, so it's safe to
1186  // return an rsi-based operand (the write barrier cannot be allowed to
1187  // destroy the rsi register).
1188  return ContextOperand(context, var->index());
1189}
1190
1191
1192void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
1193                                                  TypeofState typeof_state,
1194                                                  Label* slow,
1195                                                  Label* done) {
1196  // Generate fast-case code for variables that might be shadowed by
1197  // eval-introduced variables.  Eval is used a lot without
1198  // introducing variables.  In those cases, we do not want to
1199  // perform a runtime call for all variables in the scope
1200  // containing the eval.
1201  if (var->mode() == DYNAMIC_GLOBAL) {
1202    EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
1203    __ jmp(done);
1204  } else if (var->mode() == DYNAMIC_LOCAL) {
1205    Variable* local = var->local_if_not_shadowed();
1206    __ movq(rax, ContextSlotOperandCheckExtensions(local, slow));
1207    if (local->mode() == CONST ||
1208        local->mode() == CONST_HARMONY ||
1209        local->mode() == LET) {
1210      __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1211      __ j(not_equal, done);
1212      if (local->mode() == CONST) {
1213        __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1214      } else {  // LET || CONST_HARMONY
1215        __ Push(var->name());
1216        __ CallRuntime(Runtime::kThrowReferenceError, 1);
1217      }
1218    }
1219    __ jmp(done);
1220  }
1221}
1222
1223
1224void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
1225  // Record position before possible IC call.
1226  SetSourcePosition(proxy->position());
1227  Variable* var = proxy->var();
1228
1229  // Three cases: global variables, lookup variables, and all other types of
1230  // variables.
1231  switch (var->location()) {
1232    case Variable::UNALLOCATED: {
1233      Comment cmnt(masm_, "Global variable");
1234      // Use inline caching. Variable name is passed in rcx and the global
1235      // object on the stack.
1236      __ Move(rcx, var->name());
1237      __ movq(rax, GlobalObjectOperand());
1238      Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1239      __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1240      context()->Plug(rax);
1241      break;
1242    }
1243
1244    case Variable::PARAMETER:
1245    case Variable::LOCAL:
1246    case Variable::CONTEXT: {
1247      Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot");
1248      if (var->binding_needs_init()) {
1249        // var->scope() may be NULL when the proxy is located in eval code and
1250        // refers to a potential outside binding. Currently those bindings are
1251        // always looked up dynamically, i.e. in that case
1252        //     var->location() == LOOKUP.
1253        // always holds.
1254        ASSERT(var->scope() != NULL);
1255
1256        // Check if the binding really needs an initialization check. The check
1257        // can be skipped in the following situation: we have a LET or CONST
1258        // binding in harmony mode, both the Variable and the VariableProxy have
1259        // the same declaration scope (i.e. they are both in global code, in the
1260        // same function or in the same eval code) and the VariableProxy is in
1261        // the source physically located after the initializer of the variable.
1262        //
1263        // We cannot skip any initialization checks for CONST in non-harmony
1264        // mode because const variables may be declared but never initialized:
1265        //   if (false) { const x; }; var y = x;
1266        //
1267        // The condition on the declaration scopes is a conservative check for
1268        // nested functions that access a binding and are called before the
1269        // binding is initialized:
1270        //   function() { f(); let x = 1; function f() { x = 2; } }
1271        //
1272        bool skip_init_check;
1273        if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
1274          skip_init_check = false;
1275        } else {
1276          // Check that we always have valid source position.
1277          ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
1278          ASSERT(proxy->position() != RelocInfo::kNoPosition);
1279          skip_init_check = var->mode() != CONST &&
1280              var->initializer_position() < proxy->position();
1281        }
1282
1283        if (!skip_init_check) {
1284          // Let and const need a read barrier.
1285          Label done;
1286          GetVar(rax, var);
1287          __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1288          __ j(not_equal, &done, Label::kNear);
1289          if (var->mode() == LET || var->mode() == CONST_HARMONY) {
1290            // Throw a reference error when using an uninitialized let/const
1291            // binding in harmony mode.
1292            __ Push(var->name());
1293            __ CallRuntime(Runtime::kThrowReferenceError, 1);
1294          } else {
1295            // Uninitalized const bindings outside of harmony mode are unholed.
1296            ASSERT(var->mode() == CONST);
1297            __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1298          }
1299          __ bind(&done);
1300          context()->Plug(rax);
1301          break;
1302        }
1303      }
1304      context()->Plug(var);
1305      break;
1306    }
1307
1308    case Variable::LOOKUP: {
1309      Label done, slow;
1310      // Generate code for loading from variables potentially shadowed
1311      // by eval-introduced variables.
1312      EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
1313      __ bind(&slow);
1314      Comment cmnt(masm_, "Lookup slot");
1315      __ push(rsi);  // Context.
1316      __ Push(var->name());
1317      __ CallRuntime(Runtime::kLoadContextSlot, 2);
1318      __ bind(&done);
1319      context()->Plug(rax);
1320      break;
1321    }
1322  }
1323}
1324
1325
1326void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1327  Comment cmnt(masm_, "[ RegExpLiteral");
1328  Label materialized;
1329  // Registers will be used as follows:
1330  // rdi = JS function.
1331  // rcx = literals array.
1332  // rbx = regexp literal.
1333  // rax = regexp literal clone.
1334  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1335  __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
1336  int literal_offset =
1337      FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1338  __ movq(rbx, FieldOperand(rcx, literal_offset));
1339  __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
1340  __ j(not_equal, &materialized, Label::kNear);
1341
1342  // Create regexp literal using runtime function
1343  // Result will be in rax.
1344  __ push(rcx);
1345  __ Push(Smi::FromInt(expr->literal_index()));
1346  __ Push(expr->pattern());
1347  __ Push(expr->flags());
1348  __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1349  __ movq(rbx, rax);
1350
1351  __ bind(&materialized);
1352  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1353  Label allocated, runtime_allocate;
1354  __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
1355  __ jmp(&allocated);
1356
1357  __ bind(&runtime_allocate);
1358  __ push(rbx);
1359  __ Push(Smi::FromInt(size));
1360  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1361  __ pop(rbx);
1362
1363  __ bind(&allocated);
1364  // Copy the content into the newly allocated memory.
1365  // (Unroll copy loop once for better throughput).
1366  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
1367    __ movq(rdx, FieldOperand(rbx, i));
1368    __ movq(rcx, FieldOperand(rbx, i + kPointerSize));
1369    __ movq(FieldOperand(rax, i), rdx);
1370    __ movq(FieldOperand(rax, i + kPointerSize), rcx);
1371  }
1372  if ((size % (2 * kPointerSize)) != 0) {
1373    __ movq(rdx, FieldOperand(rbx, size - kPointerSize));
1374    __ movq(FieldOperand(rax, size - kPointerSize), rdx);
1375  }
1376  context()->Plug(rax);
1377}
1378
1379
1380void FullCodeGenerator::EmitAccessor(Expression* expression) {
1381  if (expression == NULL) {
1382    __ PushRoot(Heap::kNullValueRootIndex);
1383  } else {
1384    VisitForStackValue(expression);
1385  }
1386}
1387
1388
1389void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1390  Comment cmnt(masm_, "[ ObjectLiteral");
1391  Handle<FixedArray> constant_properties = expr->constant_properties();
1392  __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1393  __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
1394  __ Push(Smi::FromInt(expr->literal_index()));
1395  __ Push(constant_properties);
1396  int flags = expr->fast_elements()
1397      ? ObjectLiteral::kFastElements
1398      : ObjectLiteral::kNoFlags;
1399  flags |= expr->has_function()
1400      ? ObjectLiteral::kHasFunction
1401      : ObjectLiteral::kNoFlags;
1402  __ Push(Smi::FromInt(flags));
1403  int properties_count = constant_properties->length() / 2;
1404  if (expr->depth() > 1) {
1405    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
1406  } else if (flags != ObjectLiteral::kFastElements ||
1407      properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
1408    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
1409  } else {
1410    FastCloneShallowObjectStub stub(properties_count);
1411    __ CallStub(&stub);
1412  }
1413
1414  // If result_saved is true the result is on top of the stack.  If
1415  // result_saved is false the result is in rax.
1416  bool result_saved = false;
1417
1418  // Mark all computed expressions that are bound to a key that
1419  // is shadowed by a later occurrence of the same key. For the
1420  // marked expressions, no store code is emitted.
1421  expr->CalculateEmitStore();
1422
1423  AccessorTable accessor_table(isolate()->zone());
1424  for (int i = 0; i < expr->properties()->length(); i++) {
1425    ObjectLiteral::Property* property = expr->properties()->at(i);
1426    if (property->IsCompileTimeValue()) continue;
1427
1428    Literal* key = property->key();
1429    Expression* value = property->value();
1430    if (!result_saved) {
1431      __ push(rax);  // Save result on the stack
1432      result_saved = true;
1433    }
1434    switch (property->kind()) {
1435      case ObjectLiteral::Property::CONSTANT:
1436        UNREACHABLE();
1437      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1438        ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1439        // Fall through.
1440      case ObjectLiteral::Property::COMPUTED:
1441        if (key->handle()->IsSymbol()) {
1442          if (property->emit_store()) {
1443            VisitForAccumulatorValue(value);
1444            __ Move(rcx, key->handle());
1445            __ movq(rdx, Operand(rsp, 0));
1446            Handle<Code> ic = is_classic_mode()
1447                ? isolate()->builtins()->StoreIC_Initialize()
1448                : isolate()->builtins()->StoreIC_Initialize_Strict();
1449            __ call(ic, RelocInfo::CODE_TARGET, key->id());
1450            PrepareForBailoutForId(key->id(), NO_REGISTERS);
1451          } else {
1452            VisitForEffect(value);
1453          }
1454          break;
1455        }
1456        // Fall through.
1457      case ObjectLiteral::Property::PROTOTYPE:
1458        __ push(Operand(rsp, 0));  // Duplicate receiver.
1459        VisitForStackValue(key);
1460        VisitForStackValue(value);
1461        if (property->emit_store()) {
1462          __ Push(Smi::FromInt(NONE));    // PropertyAttributes
1463          __ CallRuntime(Runtime::kSetProperty, 4);
1464        } else {
1465          __ Drop(3);
1466        }
1467        break;
1468      case ObjectLiteral::Property::GETTER:
1469        accessor_table.lookup(key)->second->getter = value;
1470        break;
1471      case ObjectLiteral::Property::SETTER:
1472        accessor_table.lookup(key)->second->setter = value;
1473        break;
1474    }
1475  }
1476
1477  // Emit code to define accessors, using only a single call to the runtime for
1478  // each pair of corresponding getters and setters.
1479  for (AccessorTable::Iterator it = accessor_table.begin();
1480       it != accessor_table.end();
1481       ++it) {
1482    __ push(Operand(rsp, 0));  // Duplicate receiver.
1483    VisitForStackValue(it->first);
1484    EmitAccessor(it->second->getter);
1485    EmitAccessor(it->second->setter);
1486    __ Push(Smi::FromInt(NONE));
1487    __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
1488  }
1489
1490  if (expr->has_function()) {
1491    ASSERT(result_saved);
1492    __ push(Operand(rsp, 0));
1493    __ CallRuntime(Runtime::kToFastProperties, 1);
1494  }
1495
1496  if (result_saved) {
1497    context()->PlugTOS();
1498  } else {
1499    context()->Plug(rax);
1500  }
1501}
1502
1503
1504void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1505  Comment cmnt(masm_, "[ ArrayLiteral");
1506
1507  ZoneList<Expression*>* subexprs = expr->values();
1508  int length = subexprs->length();
1509  Handle<FixedArray> constant_elements = expr->constant_elements();
1510  ASSERT_EQ(2, constant_elements->length());
1511  ElementsKind constant_elements_kind =
1512      static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1513  bool has_constant_fast_elements = constant_elements_kind == FAST_ELEMENTS;
1514  Handle<FixedArrayBase> constant_elements_values(
1515      FixedArrayBase::cast(constant_elements->get(1)));
1516
1517  __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1518  __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
1519  __ Push(Smi::FromInt(expr->literal_index()));
1520  __ Push(constant_elements);
1521  Heap* heap = isolate()->heap();
1522  if (has_constant_fast_elements &&
1523      constant_elements_values->map() == heap->fixed_cow_array_map()) {
1524    // If the elements are already FAST_ELEMENTS, the boilerplate cannot
1525    // change, so it's possible to specialize the stub in advance.
1526    __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1);
1527    FastCloneShallowArrayStub stub(
1528        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS,
1529        length);
1530    __ CallStub(&stub);
1531  } else if (expr->depth() > 1) {
1532    __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
1533  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1534    __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1535  } else {
1536    ASSERT(constant_elements_kind == FAST_ELEMENTS ||
1537           constant_elements_kind == FAST_SMI_ONLY_ELEMENTS ||
1538           FLAG_smi_only_arrays);
1539    // If the elements are already FAST_ELEMENTS, the boilerplate cannot
1540    // change, so it's possible to specialize the stub in advance.
1541    FastCloneShallowArrayStub::Mode mode = has_constant_fast_elements
1542        ? FastCloneShallowArrayStub::CLONE_ELEMENTS
1543        : FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS;
1544    FastCloneShallowArrayStub stub(mode, length);
1545    __ CallStub(&stub);
1546  }
1547
1548  bool result_saved = false;  // Is the result saved to the stack?
1549
1550  // Emit code to evaluate all the non-constant subexpressions and to store
1551  // them into the newly cloned array.
1552  for (int i = 0; i < length; i++) {
1553    Expression* subexpr = subexprs->at(i);
1554    // If the subexpression is a literal or a simple materialized literal it
1555    // is already set in the cloned array.
1556    if (subexpr->AsLiteral() != NULL ||
1557        CompileTimeValue::IsCompileTimeValue(subexpr)) {
1558      continue;
1559    }
1560
1561    if (!result_saved) {
1562      __ push(rax);
1563      result_saved = true;
1564    }
1565    VisitForAccumulatorValue(subexpr);
1566
1567    if (constant_elements_kind == FAST_ELEMENTS) {
1568      // Fast-case array literal with ElementsKind of FAST_ELEMENTS, they cannot
1569      // transition and don't need to call the runtime stub.
1570      int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1571      __ movq(rbx, Operand(rsp, 0));  // Copy of array literal.
1572      __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
1573      // Store the subexpression value in the array's elements.
1574      __ movq(FieldOperand(rbx, offset), result_register());
1575      // Update the write barrier for the array store.
1576      __ RecordWriteField(rbx, offset, result_register(), rcx,
1577                          kDontSaveFPRegs,
1578                          EMIT_REMEMBERED_SET,
1579                          INLINE_SMI_CHECK);
1580    } else {
1581      // Store the subexpression value in the array's elements.
1582      __ movq(rbx, Operand(rsp, 0));  // Copy of array literal.
1583      __ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset));
1584      __ Move(rcx, Smi::FromInt(i));
1585      __ Move(rdx, Smi::FromInt(expr->literal_index()));
1586      StoreArrayLiteralElementStub stub;
1587      __ CallStub(&stub);
1588    }
1589
1590    PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
1591  }
1592
1593  if (result_saved) {
1594    context()->PlugTOS();
1595  } else {
1596    context()->Plug(rax);
1597  }
1598}
1599
1600
1601void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1602  Comment cmnt(masm_, "[ Assignment");
1603  // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1604  // on the left-hand side.
1605  if (!expr->target()->IsValidLeftHandSide()) {
1606    VisitForEffect(expr->target());
1607    return;
1608  }
1609
1610  // Left-hand side can only be a property, a global or a (parameter or local)
1611  // slot.
1612  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1613  LhsKind assign_type = VARIABLE;
1614  Property* property = expr->target()->AsProperty();
1615  if (property != NULL) {
1616    assign_type = (property->key()->IsPropertyName())
1617        ? NAMED_PROPERTY
1618        : KEYED_PROPERTY;
1619  }
1620
1621  // Evaluate LHS expression.
1622  switch (assign_type) {
1623    case VARIABLE:
1624      // Nothing to do here.
1625      break;
1626    case NAMED_PROPERTY:
1627      if (expr->is_compound()) {
1628        // We need the receiver both on the stack and in the accumulator.
1629        VisitForAccumulatorValue(property->obj());
1630        __ push(result_register());
1631      } else {
1632        VisitForStackValue(property->obj());
1633      }
1634      break;
1635    case KEYED_PROPERTY: {
1636      if (expr->is_compound()) {
1637        VisitForStackValue(property->obj());
1638        VisitForAccumulatorValue(property->key());
1639        __ movq(rdx, Operand(rsp, 0));
1640        __ push(rax);
1641      } else {
1642        VisitForStackValue(property->obj());
1643        VisitForStackValue(property->key());
1644      }
1645      break;
1646    }
1647  }
1648
1649  // For compound assignments we need another deoptimization point after the
1650  // variable/property load.
1651  if (expr->is_compound()) {
1652    { AccumulatorValueContext context(this);
1653      switch (assign_type) {
1654        case VARIABLE:
1655          EmitVariableLoad(expr->target()->AsVariableProxy());
1656          PrepareForBailout(expr->target(), TOS_REG);
1657          break;
1658        case NAMED_PROPERTY:
1659          EmitNamedPropertyLoad(property);
1660          PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
1661          break;
1662        case KEYED_PROPERTY:
1663          EmitKeyedPropertyLoad(property);
1664          PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
1665          break;
1666      }
1667    }
1668
1669    Token::Value op = expr->binary_op();
1670    __ push(rax);  // Left operand goes on the stack.
1671    VisitForAccumulatorValue(expr->value());
1672
1673    OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
1674        ? OVERWRITE_RIGHT
1675        : NO_OVERWRITE;
1676    SetSourcePosition(expr->position() + 1);
1677    AccumulatorValueContext context(this);
1678    if (ShouldInlineSmiCase(op)) {
1679      EmitInlineSmiBinaryOp(expr->binary_operation(),
1680                            op,
1681                            mode,
1682                            expr->target(),
1683                            expr->value());
1684    } else {
1685      EmitBinaryOp(expr->binary_operation(), op, mode);
1686    }
1687    // Deoptimization point in case the binary operation may have side effects.
1688    PrepareForBailout(expr->binary_operation(), TOS_REG);
1689  } else {
1690    VisitForAccumulatorValue(expr->value());
1691  }
1692
1693  // Record source position before possible IC call.
1694  SetSourcePosition(expr->position());
1695
1696  // Store the value.
1697  switch (assign_type) {
1698    case VARIABLE:
1699      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1700                             expr->op());
1701      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1702      context()->Plug(rax);
1703      break;
1704    case NAMED_PROPERTY:
1705      EmitNamedPropertyAssignment(expr);
1706      break;
1707    case KEYED_PROPERTY:
1708      EmitKeyedPropertyAssignment(expr);
1709      break;
1710  }
1711}
1712
1713
1714void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1715  SetSourcePosition(prop->position());
1716  Literal* key = prop->key()->AsLiteral();
1717  __ Move(rcx, key->handle());
1718  Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
1719  __ call(ic, RelocInfo::CODE_TARGET, prop->id());
1720}
1721
1722
1723void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1724  SetSourcePosition(prop->position());
1725  Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
1726  __ call(ic, RelocInfo::CODE_TARGET, prop->id());
1727}
1728
1729
1730void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
1731                                              Token::Value op,
1732                                              OverwriteMode mode,
1733                                              Expression* left,
1734                                              Expression* right) {
1735  // Do combined smi check of the operands. Left operand is on the
1736  // stack (popped into rdx). Right operand is in rax but moved into
1737  // rcx to make the shifts easier.
1738  Label done, stub_call, smi_case;
1739  __ pop(rdx);
1740  __ movq(rcx, rax);
1741  __ or_(rax, rdx);
1742  JumpPatchSite patch_site(masm_);
1743  patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear);
1744
1745  __ bind(&stub_call);
1746  __ movq(rax, rcx);
1747  BinaryOpStub stub(op, mode);
1748  __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
1749  patch_site.EmitPatchInfo();
1750  __ jmp(&done, Label::kNear);
1751
1752  __ bind(&smi_case);
1753  switch (op) {
1754    case Token::SAR:
1755      __ SmiShiftArithmeticRight(rax, rdx, rcx);
1756      break;
1757    case Token::SHL:
1758      __ SmiShiftLeft(rax, rdx, rcx);
1759      break;
1760    case Token::SHR:
1761      __ SmiShiftLogicalRight(rax, rdx, rcx, &stub_call);
1762      break;
1763    case Token::ADD:
1764      __ SmiAdd(rax, rdx, rcx, &stub_call);
1765      break;
1766    case Token::SUB:
1767      __ SmiSub(rax, rdx, rcx, &stub_call);
1768      break;
1769    case Token::MUL:
1770      __ SmiMul(rax, rdx, rcx, &stub_call);
1771      break;
1772    case Token::BIT_OR:
1773      __ SmiOr(rax, rdx, rcx);
1774      break;
1775    case Token::BIT_AND:
1776      __ SmiAnd(rax, rdx, rcx);
1777      break;
1778    case Token::BIT_XOR:
1779      __ SmiXor(rax, rdx, rcx);
1780      break;
1781    default:
1782      UNREACHABLE();
1783      break;
1784  }
1785
1786  __ bind(&done);
1787  context()->Plug(rax);
1788}
1789
1790
1791void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
1792                                     Token::Value op,
1793                                     OverwriteMode mode) {
1794  __ pop(rdx);
1795  BinaryOpStub stub(op, mode);
1796  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
1797  __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
1798  patch_site.EmitPatchInfo();
1799  context()->Plug(rax);
1800}
1801
1802
1803void FullCodeGenerator::EmitAssignment(Expression* expr) {
1804  // Invalid left-hand sides are rewritten to have a 'throw
1805  // ReferenceError' on the left-hand side.
1806  if (!expr->IsValidLeftHandSide()) {
1807    VisitForEffect(expr);
1808    return;
1809  }
1810
1811  // Left-hand side can only be a property, a global or a (parameter or local)
1812  // slot.
1813  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1814  LhsKind assign_type = VARIABLE;
1815  Property* prop = expr->AsProperty();
1816  if (prop != NULL) {
1817    assign_type = (prop->key()->IsPropertyName())
1818        ? NAMED_PROPERTY
1819        : KEYED_PROPERTY;
1820  }
1821
1822  switch (assign_type) {
1823    case VARIABLE: {
1824      Variable* var = expr->AsVariableProxy()->var();
1825      EffectContext context(this);
1826      EmitVariableAssignment(var, Token::ASSIGN);
1827      break;
1828    }
1829    case NAMED_PROPERTY: {
1830      __ push(rax);  // Preserve value.
1831      VisitForAccumulatorValue(prop->obj());
1832      __ movq(rdx, rax);
1833      __ pop(rax);  // Restore value.
1834      __ Move(rcx, prop->key()->AsLiteral()->handle());
1835      Handle<Code> ic = is_classic_mode()
1836          ? isolate()->builtins()->StoreIC_Initialize()
1837          : isolate()->builtins()->StoreIC_Initialize_Strict();
1838      __ call(ic);
1839      break;
1840    }
1841    case KEYED_PROPERTY: {
1842      __ push(rax);  // Preserve value.
1843      VisitForStackValue(prop->obj());
1844      VisitForAccumulatorValue(prop->key());
1845      __ movq(rcx, rax);
1846      __ pop(rdx);
1847      __ pop(rax);  // Restore value.
1848      Handle<Code> ic = is_classic_mode()
1849          ? isolate()->builtins()->KeyedStoreIC_Initialize()
1850          : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
1851      __ call(ic);
1852      break;
1853    }
1854  }
1855  context()->Plug(rax);
1856}
1857
1858
1859void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1860                                               Token::Value op) {
1861  if (var->IsUnallocated()) {
1862    // Global var, const, or let.
1863    __ Move(rcx, var->name());
1864    __ movq(rdx, GlobalObjectOperand());
1865    Handle<Code> ic = is_classic_mode()
1866        ? isolate()->builtins()->StoreIC_Initialize()
1867        : isolate()->builtins()->StoreIC_Initialize_Strict();
1868    __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1869  } else if (op == Token::INIT_CONST) {
1870    // Const initializers need a write barrier.
1871    ASSERT(!var->IsParameter());  // No const parameters.
1872    if (var->IsStackLocal()) {
1873      Label skip;
1874      __ movq(rdx, StackOperand(var));
1875      __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1876      __ j(not_equal, &skip);
1877      __ movq(StackOperand(var), rax);
1878      __ bind(&skip);
1879    } else {
1880      ASSERT(var->IsContextSlot() || var->IsLookupSlot());
1881      // Like var declarations, const declarations are hoisted to function
1882      // scope.  However, unlike var initializers, const initializers are
1883      // able to drill a hole to that function context, even from inside a
1884      // 'with' context.  We thus bypass the normal static scope lookup for
1885      // var->IsContextSlot().
1886      __ push(rax);
1887      __ push(rsi);
1888      __ Push(var->name());
1889      __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
1890    }
1891
1892  } else if (var->mode() == LET && op != Token::INIT_LET) {
1893    // Non-initializing assignment to let variable needs a write barrier.
1894    if (var->IsLookupSlot()) {
1895      __ push(rax);  // Value.
1896      __ push(rsi);  // Context.
1897      __ Push(var->name());
1898      __ Push(Smi::FromInt(language_mode()));
1899      __ CallRuntime(Runtime::kStoreContextSlot, 4);
1900    } else {
1901      ASSERT(var->IsStackAllocated() || var->IsContextSlot());
1902      Label assign;
1903      MemOperand location = VarOperand(var, rcx);
1904      __ movq(rdx, location);
1905      __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1906      __ j(not_equal, &assign, Label::kNear);
1907      __ Push(var->name());
1908      __ CallRuntime(Runtime::kThrowReferenceError, 1);
1909      __ bind(&assign);
1910      __ movq(location, rax);
1911      if (var->IsContextSlot()) {
1912        __ movq(rdx, rax);
1913        __ RecordWriteContextSlot(
1914            rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
1915      }
1916    }
1917
1918  } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
1919    // Assignment to var or initializing assignment to let/const
1920    // in harmony mode.
1921    if (var->IsStackAllocated() || var->IsContextSlot()) {
1922      MemOperand location = VarOperand(var, rcx);
1923      if (FLAG_debug_code && op == Token::INIT_LET) {
1924        // Check for an uninitialized let binding.
1925        __ movq(rdx, location);
1926        __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
1927        __ Check(equal, "Let binding re-initialization.");
1928      }
1929      // Perform the assignment.
1930      __ movq(location, rax);
1931      if (var->IsContextSlot()) {
1932        __ movq(rdx, rax);
1933        __ RecordWriteContextSlot(
1934            rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
1935      }
1936    } else {
1937      ASSERT(var->IsLookupSlot());
1938      __ push(rax);  // Value.
1939      __ push(rsi);  // Context.
1940      __ Push(var->name());
1941      __ Push(Smi::FromInt(language_mode()));
1942      __ CallRuntime(Runtime::kStoreContextSlot, 4);
1943    }
1944  }
1945  // Non-initializing assignments to consts are ignored.
1946}
1947
1948
1949void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1950  // Assignment to a property, using a named store IC.
1951  Property* prop = expr->target()->AsProperty();
1952  ASSERT(prop != NULL);
1953  ASSERT(prop->key()->AsLiteral() != NULL);
1954
1955  // If the assignment starts a block of assignments to the same object,
1956  // change to slow case to avoid the quadratic behavior of repeatedly
1957  // adding fast properties.
1958  if (expr->starts_initialization_block()) {
1959    __ push(result_register());
1960    __ push(Operand(rsp, kPointerSize));  // Receiver is now under value.
1961    __ CallRuntime(Runtime::kToSlowProperties, 1);
1962    __ pop(result_register());
1963  }
1964
1965  // Record source code position before IC call.
1966  SetSourcePosition(expr->position());
1967  __ Move(rcx, prop->key()->AsLiteral()->handle());
1968  if (expr->ends_initialization_block()) {
1969    __ movq(rdx, Operand(rsp, 0));
1970  } else {
1971    __ pop(rdx);
1972  }
1973  Handle<Code> ic = is_classic_mode()
1974      ? isolate()->builtins()->StoreIC_Initialize()
1975      : isolate()->builtins()->StoreIC_Initialize_Strict();
1976  __ call(ic, RelocInfo::CODE_TARGET, expr->id());
1977
1978  // If the assignment ends an initialization block, revert to fast case.
1979  if (expr->ends_initialization_block()) {
1980    __ push(rax);  // Result of assignment, saved even if not needed.
1981    __ push(Operand(rsp, kPointerSize));  // Receiver is under value.
1982    __ CallRuntime(Runtime::kToFastProperties, 1);
1983    __ pop(rax);
1984    __ Drop(1);
1985  }
1986  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1987  context()->Plug(rax);
1988}
1989
1990
1991void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1992  // Assignment to a property, using a keyed store IC.
1993
1994  // If the assignment starts a block of assignments to the same object,
1995  // change to slow case to avoid the quadratic behavior of repeatedly
1996  // adding fast properties.
1997  if (expr->starts_initialization_block()) {
1998    __ push(result_register());
1999    // Receiver is now under the key and value.
2000    __ push(Operand(rsp, 2 * kPointerSize));
2001    __ CallRuntime(Runtime::kToSlowProperties, 1);
2002    __ pop(result_register());
2003  }
2004
2005  __ pop(rcx);
2006  if (expr->ends_initialization_block()) {
2007    __ movq(rdx, Operand(rsp, 0));  // Leave receiver on the stack for later.
2008  } else {
2009    __ pop(rdx);
2010  }
2011  // Record source code position before IC call.
2012  SetSourcePosition(expr->position());
2013  Handle<Code> ic = is_classic_mode()
2014      ? isolate()->builtins()->KeyedStoreIC_Initialize()
2015      : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2016  __ call(ic, RelocInfo::CODE_TARGET, expr->id());
2017
2018  // If the assignment ends an initialization block, revert to fast case.
2019  if (expr->ends_initialization_block()) {
2020    __ pop(rdx);
2021    __ push(rax);  // Result of assignment, saved even if not needed.
2022    __ push(rdx);
2023    __ CallRuntime(Runtime::kToFastProperties, 1);
2024    __ pop(rax);
2025  }
2026
2027  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2028  context()->Plug(rax);
2029}
2030
2031
2032void FullCodeGenerator::VisitProperty(Property* expr) {
2033  Comment cmnt(masm_, "[ Property");
2034  Expression* key = expr->key();
2035
2036  if (key->IsPropertyName()) {
2037    VisitForAccumulatorValue(expr->obj());
2038    EmitNamedPropertyLoad(expr);
2039    context()->Plug(rax);
2040  } else {
2041    VisitForStackValue(expr->obj());
2042    VisitForAccumulatorValue(expr->key());
2043    __ pop(rdx);
2044    EmitKeyedPropertyLoad(expr);
2045    context()->Plug(rax);
2046  }
2047}
2048
2049
2050void FullCodeGenerator::EmitCallWithIC(Call* expr,
2051                                       Handle<Object> name,
2052                                       RelocInfo::Mode mode) {
2053  // Code common for calls using the IC.
2054  ZoneList<Expression*>* args = expr->arguments();
2055  int arg_count = args->length();
2056  { PreservePositionScope scope(masm()->positions_recorder());
2057    for (int i = 0; i < arg_count; i++) {
2058      VisitForStackValue(args->at(i));
2059    }
2060    __ Move(rcx, name);
2061  }
2062  // Record source position for debugger.
2063  SetSourcePosition(expr->position());
2064  // Call the IC initialization code.
2065  Handle<Code> ic =
2066      isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
2067  __ call(ic, mode, expr->id());
2068  RecordJSReturnSite(expr);
2069  // Restore context register.
2070  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2071  context()->Plug(rax);
2072}
2073
2074
2075void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2076                                            Expression* key) {
2077  // Load the key.
2078  VisitForAccumulatorValue(key);
2079
2080  // Swap the name of the function and the receiver on the stack to follow
2081  // the calling convention for call ICs.
2082  __ pop(rcx);
2083  __ push(rax);
2084  __ push(rcx);
2085
2086  // Load the arguments.
2087  ZoneList<Expression*>* args = expr->arguments();
2088  int arg_count = args->length();
2089  { PreservePositionScope scope(masm()->positions_recorder());
2090    for (int i = 0; i < arg_count; i++) {
2091      VisitForStackValue(args->at(i));
2092    }
2093  }
2094  // Record source position for debugger.
2095  SetSourcePosition(expr->position());
2096  // Call the IC initialization code.
2097  Handle<Code> ic =
2098      isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
2099  __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize));  // Key.
2100  __ call(ic, RelocInfo::CODE_TARGET, expr->id());
2101  RecordJSReturnSite(expr);
2102  // Restore context register.
2103  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2104  context()->DropAndPlug(1, rax);  // Drop the key still on the stack.
2105}
2106
2107
2108void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
2109  // Code common for calls using the call stub.
2110  ZoneList<Expression*>* args = expr->arguments();
2111  int arg_count = args->length();
2112  { PreservePositionScope scope(masm()->positions_recorder());
2113    for (int i = 0; i < arg_count; i++) {
2114      VisitForStackValue(args->at(i));
2115    }
2116  }
2117  // Record source position for debugger.
2118  SetSourcePosition(expr->position());
2119  CallFunctionStub stub(arg_count, flags);
2120  __ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2121  __ CallStub(&stub);
2122  RecordJSReturnSite(expr);
2123  // Restore context register.
2124  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2125  // Discard the function left on TOS.
2126  context()->DropAndPlug(1, rax);
2127}
2128
2129
2130void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2131  // Push copy of the first argument or undefined if it doesn't exist.
2132  if (arg_count > 0) {
2133    __ push(Operand(rsp, arg_count * kPointerSize));
2134  } else {
2135    __ PushRoot(Heap::kUndefinedValueRootIndex);
2136  }
2137
2138  // Push the receiver of the enclosing function and do runtime call.
2139  __ push(Operand(rbp, (2 + info_->scope()->num_parameters()) * kPointerSize));
2140
2141  // Push the language mode.
2142  __ Push(Smi::FromInt(language_mode()));
2143
2144  // Push the start position of the scope the calls resides in.
2145  __ Push(Smi::FromInt(scope()->start_position()));
2146
2147  // Do the runtime call.
2148  __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
2149}
2150
2151
2152void FullCodeGenerator::VisitCall(Call* expr) {
2153#ifdef DEBUG
2154  // We want to verify that RecordJSReturnSite gets called on all paths
2155  // through this function.  Avoid early returns.
2156  expr->return_is_recorded_ = false;
2157#endif
2158
2159  Comment cmnt(masm_, "[ Call");
2160  Expression* callee = expr->expression();
2161  VariableProxy* proxy = callee->AsVariableProxy();
2162  Property* property = callee->AsProperty();
2163
2164  if (proxy != NULL && proxy->var()->is_possibly_eval()) {
2165    // In a call to eval, we first call %ResolvePossiblyDirectEval to
2166    // resolve the function we need to call and the receiver of the call.
2167    // Then we call the resolved function using the given arguments.
2168    ZoneList<Expression*>* args = expr->arguments();
2169    int arg_count = args->length();
2170    { PreservePositionScope pos_scope(masm()->positions_recorder());
2171      VisitForStackValue(callee);
2172      __ PushRoot(Heap::kUndefinedValueRootIndex);  // Reserved receiver slot.
2173
2174      // Push the arguments.
2175      for (int i = 0; i < arg_count; i++) {
2176        VisitForStackValue(args->at(i));
2177      }
2178
2179      // Push a copy of the function (found below the arguments) and resolve
2180      // eval.
2181      __ push(Operand(rsp, (arg_count + 1) * kPointerSize));
2182      EmitResolvePossiblyDirectEval(arg_count);
2183
2184      // The runtime call returns a pair of values in rax (function) and
2185      // rdx (receiver). Touch up the stack with the right values.
2186      __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
2187      __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
2188    }
2189    // Record source position for debugger.
2190    SetSourcePosition(expr->position());
2191    CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT);
2192    __ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2193    __ CallStub(&stub);
2194    RecordJSReturnSite(expr);
2195    // Restore context register.
2196    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2197    context()->DropAndPlug(1, rax);
2198  } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
2199    // Call to a global variable.  Push global object as receiver for the
2200    // call IC lookup.
2201    __ push(GlobalObjectOperand());
2202    EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT);
2203  } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
2204    // Call to a lookup slot (dynamically introduced variable).
2205    Label slow, done;
2206
2207    { PreservePositionScope scope(masm()->positions_recorder());
2208      // Generate code for loading from variables potentially shadowed by
2209      // eval-introduced variables.
2210      EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
2211    }
2212    __ bind(&slow);
2213    // Call the runtime to find the function to call (returned in rax) and
2214    // the object holding it (returned in rdx).
2215    __ push(context_register());
2216    __ Push(proxy->name());
2217    __ CallRuntime(Runtime::kLoadContextSlot, 2);
2218    __ push(rax);  // Function.
2219    __ push(rdx);  // Receiver.
2220
2221    // If fast case code has been generated, emit code to push the function
2222    // and receiver and have the slow path jump around this code.
2223    if (done.is_linked()) {
2224      Label call;
2225      __ jmp(&call, Label::kNear);
2226      __ bind(&done);
2227      // Push function.
2228      __ push(rax);
2229      // The receiver is implicitly the global receiver. Indicate this by
2230      // passing the hole to the call function stub.
2231      __ PushRoot(Heap::kTheHoleValueRootIndex);
2232      __ bind(&call);
2233    }
2234
2235    // The receiver is either the global receiver or an object found by
2236    // LoadContextSlot. That object could be the hole if the receiver is
2237    // implicitly the global object.
2238    EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
2239  } else if (property != NULL) {
2240    { PreservePositionScope scope(masm()->positions_recorder());
2241      VisitForStackValue(property->obj());
2242    }
2243    if (property->key()->IsPropertyName()) {
2244      EmitCallWithIC(expr,
2245                     property->key()->AsLiteral()->handle(),
2246                     RelocInfo::CODE_TARGET);
2247    } else {
2248      EmitKeyedCallWithIC(expr, property->key());
2249    }
2250  } else {
2251    // Call to an arbitrary expression not handled specially above.
2252    { PreservePositionScope scope(masm()->positions_recorder());
2253      VisitForStackValue(callee);
2254    }
2255    // Load global receiver object.
2256    __ movq(rbx, GlobalObjectOperand());
2257    __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
2258    // Emit function call.
2259    EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
2260  }
2261
2262#ifdef DEBUG
2263  // RecordJSReturnSite should have been called.
2264  ASSERT(expr->return_is_recorded_);
2265#endif
2266}
2267
2268
2269void FullCodeGenerator::VisitCallNew(CallNew* expr) {
2270  Comment cmnt(masm_, "[ CallNew");
2271  // According to ECMA-262, section 11.2.2, page 44, the function
2272  // expression in new calls must be evaluated before the
2273  // arguments.
2274
2275  // Push constructor on the stack.  If it's not a function it's used as
2276  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
2277  // ignored.
2278  VisitForStackValue(expr->expression());
2279
2280  // Push the arguments ("left-to-right") on the stack.
2281  ZoneList<Expression*>* args = expr->arguments();
2282  int arg_count = args->length();
2283  for (int i = 0; i < arg_count; i++) {
2284    VisitForStackValue(args->at(i));
2285  }
2286
2287  // Call the construct call builtin that handles allocation and
2288  // constructor invocation.
2289  SetSourcePosition(expr->position());
2290
2291  // Load function and argument count into rdi and rax.
2292  __ Set(rax, arg_count);
2293  __ movq(rdi, Operand(rsp, arg_count * kPointerSize));
2294
2295  // Record call targets in unoptimized code, but not in the snapshot.
2296  CallFunctionFlags flags;
2297  if (!Serializer::enabled()) {
2298    flags = RECORD_CALL_TARGET;
2299    Handle<Object> uninitialized =
2300        TypeFeedbackCells::UninitializedSentinel(isolate());
2301    Handle<JSGlobalPropertyCell> cell =
2302        isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
2303    RecordTypeFeedbackCell(expr->id(), cell);
2304    __ Move(rbx, cell);
2305  } else {
2306    flags = NO_CALL_FUNCTION_FLAGS;
2307  }
2308
2309  CallConstructStub stub(flags);
2310  __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
2311  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
2312  context()->Plug(rax);
2313}
2314
2315
2316void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2317  ZoneList<Expression*>* args = expr->arguments();
2318  ASSERT(args->length() == 1);
2319
2320  VisitForAccumulatorValue(args->at(0));
2321
2322  Label materialize_true, materialize_false;
2323  Label* if_true = NULL;
2324  Label* if_false = NULL;
2325  Label* fall_through = NULL;
2326  context()->PrepareTest(&materialize_true, &materialize_false,
2327                         &if_true, &if_false, &fall_through);
2328
2329  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2330  __ JumpIfSmi(rax, if_true);
2331  __ jmp(if_false);
2332
2333  context()->Plug(if_true, if_false);
2334}
2335
2336
2337void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
2338  ZoneList<Expression*>* args = expr->arguments();
2339  ASSERT(args->length() == 1);
2340
2341  VisitForAccumulatorValue(args->at(0));
2342
2343  Label materialize_true, materialize_false;
2344  Label* if_true = NULL;
2345  Label* if_false = NULL;
2346  Label* fall_through = NULL;
2347  context()->PrepareTest(&materialize_true, &materialize_false,
2348                         &if_true, &if_false, &fall_through);
2349
2350  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2351  Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
2352  Split(non_negative_smi, if_true, if_false, fall_through);
2353
2354  context()->Plug(if_true, if_false);
2355}
2356
2357
2358void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
2359  ZoneList<Expression*>* args = expr->arguments();
2360  ASSERT(args->length() == 1);
2361
2362  VisitForAccumulatorValue(args->at(0));
2363
2364  Label materialize_true, materialize_false;
2365  Label* if_true = NULL;
2366  Label* if_false = NULL;
2367  Label* fall_through = NULL;
2368  context()->PrepareTest(&materialize_true, &materialize_false,
2369                         &if_true, &if_false, &fall_through);
2370
2371  __ JumpIfSmi(rax, if_false);
2372  __ CompareRoot(rax, Heap::kNullValueRootIndex);
2373  __ j(equal, if_true);
2374  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2375  // Undetectable objects behave like undefined when tested with typeof.
2376  __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2377           Immediate(1 << Map::kIsUndetectable));
2378  __ j(not_zero, if_false);
2379  __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2380  __ cmpq(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2381  __ j(below, if_false);
2382  __ cmpq(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
2383  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2384  Split(below_equal, if_true, if_false, fall_through);
2385
2386  context()->Plug(if_true, if_false);
2387}
2388
2389
2390void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
2391  ZoneList<Expression*>* args = expr->arguments();
2392  ASSERT(args->length() == 1);
2393
2394  VisitForAccumulatorValue(args->at(0));
2395
2396  Label materialize_true, materialize_false;
2397  Label* if_true = NULL;
2398  Label* if_false = NULL;
2399  Label* fall_through = NULL;
2400  context()->PrepareTest(&materialize_true, &materialize_false,
2401                         &if_true, &if_false, &fall_through);
2402
2403  __ JumpIfSmi(rax, if_false);
2404  __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx);
2405  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2406  Split(above_equal, if_true, if_false, fall_through);
2407
2408  context()->Plug(if_true, if_false);
2409}
2410
2411
2412void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
2413  ZoneList<Expression*>* args = expr->arguments();
2414  ASSERT(args->length() == 1);
2415
2416  VisitForAccumulatorValue(args->at(0));
2417
2418  Label materialize_true, materialize_false;
2419  Label* if_true = NULL;
2420  Label* if_false = NULL;
2421  Label* fall_through = NULL;
2422  context()->PrepareTest(&materialize_true, &materialize_false,
2423                         &if_true, &if_false, &fall_through);
2424
2425  __ JumpIfSmi(rax, if_false);
2426  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2427  __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2428           Immediate(1 << Map::kIsUndetectable));
2429  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2430  Split(not_zero, if_true, if_false, fall_through);
2431
2432  context()->Plug(if_true, if_false);
2433}
2434
2435
2436void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2437    CallRuntime* expr) {
2438  ZoneList<Expression*>* args = expr->arguments();
2439  ASSERT(args->length() == 1);
2440
2441  VisitForAccumulatorValue(args->at(0));
2442
2443  Label materialize_true, materialize_false;
2444  Label* if_true = NULL;
2445  Label* if_false = NULL;
2446  Label* fall_through = NULL;
2447  context()->PrepareTest(&materialize_true, &materialize_false,
2448                         &if_true, &if_false, &fall_through);
2449
2450  if (FLAG_debug_code) __ AbortIfSmi(rax);
2451
2452  // Check whether this map has already been checked to be safe for default
2453  // valueOf.
2454  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2455  __ testb(FieldOperand(rbx, Map::kBitField2Offset),
2456           Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
2457  __ j(not_zero, if_true);
2458
2459  // Check for fast case object. Generate false result for slow case object.
2460  __ movq(rcx, FieldOperand(rax, JSObject::kPropertiesOffset));
2461  __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
2462  __ CompareRoot(rcx, Heap::kHashTableMapRootIndex);
2463  __ j(equal, if_false);
2464
2465  // Look for valueOf symbol in the descriptor array, and indicate false if
2466  // found. The type is not checked, so if it is a transition it is a false
2467  // negative.
2468  __ LoadInstanceDescriptors(rbx, rbx);
2469  __ movq(rcx, FieldOperand(rbx, FixedArray::kLengthOffset));
2470  // rbx: descriptor array
2471  // rcx: length of descriptor array
2472  // Calculate the end of the descriptor array.
2473  SmiIndex index = masm_->SmiToIndex(rdx, rcx, kPointerSizeLog2);
2474  __ lea(rcx,
2475         Operand(
2476             rbx, index.reg, index.scale, FixedArray::kHeaderSize));
2477  // Calculate location of the first key name.
2478  __ addq(rbx,
2479          Immediate(FixedArray::kHeaderSize +
2480                    DescriptorArray::kFirstIndex * kPointerSize));
2481  // Loop through all the keys in the descriptor array. If one of these is the
2482  // symbol valueOf the result is false.
2483  Label entry, loop;
2484  __ jmp(&entry);
2485  __ bind(&loop);
2486  __ movq(rdx, FieldOperand(rbx, 0));
2487  __ Cmp(rdx, FACTORY->value_of_symbol());
2488  __ j(equal, if_false);
2489  __ addq(rbx, Immediate(kPointerSize));
2490  __ bind(&entry);
2491  __ cmpq(rbx, rcx);
2492  __ j(not_equal, &loop);
2493
2494  // Reload map as register rbx was used as temporary above.
2495  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2496
2497  // If a valueOf property is not found on the object check that it's
2498  // prototype is the un-modified String prototype. If not result is false.
2499  __ movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
2500  __ testq(rcx, Immediate(kSmiTagMask));
2501  __ j(zero, if_false);
2502  __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
2503  __ movq(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
2504  __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalContextOffset));
2505  __ cmpq(rcx,
2506          ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
2507  __ j(not_equal, if_false);
2508  // Set the bit in the map to indicate that it has been checked safe for
2509  // default valueOf and set true result.
2510  __ or_(FieldOperand(rbx, Map::kBitField2Offset),
2511         Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
2512  __ jmp(if_true);
2513
2514  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2515  context()->Plug(if_true, if_false);
2516}
2517
2518
2519void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
2520  ZoneList<Expression*>* args = expr->arguments();
2521  ASSERT(args->length() == 1);
2522
2523  VisitForAccumulatorValue(args->at(0));
2524
2525  Label materialize_true, materialize_false;
2526  Label* if_true = NULL;
2527  Label* if_false = NULL;
2528  Label* fall_through = NULL;
2529  context()->PrepareTest(&materialize_true, &materialize_false,
2530                         &if_true, &if_false, &fall_through);
2531
2532  __ JumpIfSmi(rax, if_false);
2533  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2534  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2535  Split(equal, if_true, if_false, fall_through);
2536
2537  context()->Plug(if_true, if_false);
2538}
2539
2540
2541void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
2542  ZoneList<Expression*>* args = expr->arguments();
2543  ASSERT(args->length() == 1);
2544
2545  VisitForAccumulatorValue(args->at(0));
2546
2547  Label materialize_true, materialize_false;
2548  Label* if_true = NULL;
2549  Label* if_false = NULL;
2550  Label* fall_through = NULL;
2551  context()->PrepareTest(&materialize_true, &materialize_false,
2552                         &if_true, &if_false, &fall_through);
2553
2554  __ JumpIfSmi(rax, if_false);
2555  __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
2556  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2557  Split(equal, if_true, if_false, fall_through);
2558
2559  context()->Plug(if_true, if_false);
2560}
2561
2562
2563void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
2564  ZoneList<Expression*>* args = expr->arguments();
2565  ASSERT(args->length() == 1);
2566
2567  VisitForAccumulatorValue(args->at(0));
2568
2569  Label materialize_true, materialize_false;
2570  Label* if_true = NULL;
2571  Label* if_false = NULL;
2572  Label* fall_through = NULL;
2573  context()->PrepareTest(&materialize_true, &materialize_false,
2574                         &if_true, &if_false, &fall_through);
2575
2576  __ JumpIfSmi(rax, if_false);
2577  __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
2578  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2579  Split(equal, if_true, if_false, fall_through);
2580
2581  context()->Plug(if_true, if_false);
2582}
2583
2584
2585
2586void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
2587  ASSERT(expr->arguments()->length() == 0);
2588
2589  Label materialize_true, materialize_false;
2590  Label* if_true = NULL;
2591  Label* if_false = NULL;
2592  Label* fall_through = NULL;
2593  context()->PrepareTest(&materialize_true, &materialize_false,
2594                         &if_true, &if_false, &fall_through);
2595
2596  // Get the frame pointer for the calling frame.
2597  __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2598
2599  // Skip the arguments adaptor frame if it exists.
2600  Label check_frame_marker;
2601  __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset),
2602         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2603  __ j(not_equal, &check_frame_marker);
2604  __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
2605
2606  // Check the marker in the calling frame.
2607  __ bind(&check_frame_marker);
2608  __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset),
2609         Smi::FromInt(StackFrame::CONSTRUCT));
2610  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2611  Split(equal, if_true, if_false, fall_through);
2612
2613  context()->Plug(if_true, if_false);
2614}
2615
2616
2617void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
2618  ZoneList<Expression*>* args = expr->arguments();
2619  ASSERT(args->length() == 2);
2620
2621  // Load the two objects into registers and perform the comparison.
2622  VisitForStackValue(args->at(0));
2623  VisitForAccumulatorValue(args->at(1));
2624
2625  Label materialize_true, materialize_false;
2626  Label* if_true = NULL;
2627  Label* if_false = NULL;
2628  Label* fall_through = NULL;
2629  context()->PrepareTest(&materialize_true, &materialize_false,
2630                         &if_true, &if_false, &fall_through);
2631
2632  __ pop(rbx);
2633  __ cmpq(rax, rbx);
2634  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2635  Split(equal, if_true, if_false, fall_through);
2636
2637  context()->Plug(if_true, if_false);
2638}
2639
2640
2641void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
2642  ZoneList<Expression*>* args = expr->arguments();
2643  ASSERT(args->length() == 1);
2644
2645  // ArgumentsAccessStub expects the key in rdx and the formal
2646  // parameter count in rax.
2647  VisitForAccumulatorValue(args->at(0));
2648  __ movq(rdx, rax);
2649  __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
2650  ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2651  __ CallStub(&stub);
2652  context()->Plug(rax);
2653}
2654
2655
2656void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
2657  ASSERT(expr->arguments()->length() == 0);
2658
2659  Label exit;
2660  // Get the number of formal parameters.
2661  __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
2662
2663  // Check if the calling frame is an arguments adaptor frame.
2664  __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2665  __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
2666         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2667  __ j(not_equal, &exit, Label::kNear);
2668
2669  // Arguments adaptor case: Read the arguments length from the
2670  // adaptor frame.
2671  __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2672
2673  __ bind(&exit);
2674  if (FLAG_debug_code) __ AbortIfNotSmi(rax);
2675  context()->Plug(rax);
2676}
2677
2678
2679void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
2680  ZoneList<Expression*>* args = expr->arguments();
2681  ASSERT(args->length() == 1);
2682  Label done, null, function, non_function_constructor;
2683
2684  VisitForAccumulatorValue(args->at(0));
2685
2686  // If the object is a smi, we return null.
2687  __ JumpIfSmi(rax, &null);
2688
2689  // Check that the object is a JS object but take special care of JS
2690  // functions to make sure they have 'Function' as their class.
2691  // Assume that there are only two callable types, and one of them is at
2692  // either end of the type range for JS object types. Saves extra comparisons.
2693  STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
2694  __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax);
2695  // Map is now in rax.
2696  __ j(below, &null);
2697  STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2698                FIRST_SPEC_OBJECT_TYPE + 1);
2699  __ j(equal, &function);
2700
2701  __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE);
2702  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2703                LAST_SPEC_OBJECT_TYPE - 1);
2704  __ j(equal, &function);
2705  // Assume that there is no larger type.
2706  STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
2707
2708  // Check if the constructor in the map is a JS function.
2709  __ movq(rax, FieldOperand(rax, Map::kConstructorOffset));
2710  __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2711  __ j(not_equal, &non_function_constructor);
2712
2713  // rax now contains the constructor function. Grab the
2714  // instance class name from there.
2715  __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
2716  __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset));
2717  __ jmp(&done);
2718
2719  // Functions have class 'Function'.
2720  __ bind(&function);
2721  __ Move(rax, isolate()->factory()->function_class_symbol());
2722  __ jmp(&done);
2723
2724  // Objects with a non-function constructor have class 'Object'.
2725  __ bind(&non_function_constructor);
2726  __ Move(rax, isolate()->factory()->Object_symbol());
2727  __ jmp(&done);
2728
2729  // Non-JS objects have class null.
2730  __ bind(&null);
2731  __ LoadRoot(rax, Heap::kNullValueRootIndex);
2732
2733  // All done.
2734  __ bind(&done);
2735
2736  context()->Plug(rax);
2737}
2738
2739
2740void FullCodeGenerator::EmitLog(CallRuntime* expr) {
2741  // Conditionally generate a log call.
2742  // Args:
2743  //   0 (literal string): The type of logging (corresponds to the flags).
2744  //     This is used to determine whether or not to generate the log call.
2745  //   1 (string): Format string.  Access the string at argument index 2
2746  //     with '%2s' (see Logger::LogRuntime for all the formats).
2747  //   2 (array): Arguments to the format string.
2748  ZoneList<Expression*>* args = expr->arguments();
2749  ASSERT_EQ(args->length(), 3);
2750  if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
2751    VisitForStackValue(args->at(1));
2752    VisitForStackValue(args->at(2));
2753    __ CallRuntime(Runtime::kLog, 2);
2754  }
2755  // Finally, we're expected to leave a value on the top of the stack.
2756  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2757  context()->Plug(rax);
2758}
2759
2760
2761void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
2762  ASSERT(expr->arguments()->length() == 0);
2763
2764  Label slow_allocate_heapnumber;
2765  Label heapnumber_allocated;
2766
2767  __ AllocateHeapNumber(rbx, rcx, &slow_allocate_heapnumber);
2768  __ jmp(&heapnumber_allocated);
2769
2770  __ bind(&slow_allocate_heapnumber);
2771  // Allocate a heap number.
2772  __ CallRuntime(Runtime::kNumberAlloc, 0);
2773  __ movq(rbx, rax);
2774
2775  __ bind(&heapnumber_allocated);
2776
2777  // Return a random uint32 number in rax.
2778  // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs.
2779  __ PrepareCallCFunction(1);
2780#ifdef _WIN64
2781  __ movq(rcx, ContextOperand(context_register(), Context::GLOBAL_INDEX));
2782  __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalContextOffset));
2783
2784#else
2785  __ movq(rdi, ContextOperand(context_register(), Context::GLOBAL_INDEX));
2786  __ movq(rdi, FieldOperand(rdi, GlobalObject::kGlobalContextOffset));
2787#endif
2788  __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
2789
2790  // Convert 32 random bits in rax to 0.(32 random bits) in a double
2791  // by computing:
2792  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
2793  __ movl(rcx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
2794  __ movd(xmm1, rcx);
2795  __ movd(xmm0, rax);
2796  __ cvtss2sd(xmm1, xmm1);
2797  __ xorps(xmm0, xmm1);
2798  __ subsd(xmm0, xmm1);
2799  __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0);
2800
2801  __ movq(rax, rbx);
2802  context()->Plug(rax);
2803}
2804
2805
2806void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
2807  // Load the arguments on the stack and call the stub.
2808  SubStringStub stub;
2809  ZoneList<Expression*>* args = expr->arguments();
2810  ASSERT(args->length() == 3);
2811  VisitForStackValue(args->at(0));
2812  VisitForStackValue(args->at(1));
2813  VisitForStackValue(args->at(2));
2814  __ CallStub(&stub);
2815  context()->Plug(rax);
2816}
2817
2818
2819void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
2820  // Load the arguments on the stack and call the stub.
2821  RegExpExecStub stub;
2822  ZoneList<Expression*>* args = expr->arguments();
2823  ASSERT(args->length() == 4);
2824  VisitForStackValue(args->at(0));
2825  VisitForStackValue(args->at(1));
2826  VisitForStackValue(args->at(2));
2827  VisitForStackValue(args->at(3));
2828  __ CallStub(&stub);
2829  context()->Plug(rax);
2830}
2831
2832
2833void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
2834  ZoneList<Expression*>* args = expr->arguments();
2835  ASSERT(args->length() == 1);
2836
2837  VisitForAccumulatorValue(args->at(0));  // Load the object.
2838
2839  Label done;
2840  // If the object is a smi return the object.
2841  __ JumpIfSmi(rax, &done);
2842  // If the object is not a value type, return the object.
2843  __ CmpObjectType(rax, JS_VALUE_TYPE, rbx);
2844  __ j(not_equal, &done);
2845  __ movq(rax, FieldOperand(rax, JSValue::kValueOffset));
2846
2847  __ bind(&done);
2848  context()->Plug(rax);
2849}
2850
2851
2852void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
2853  ZoneList<Expression*>* args = expr->arguments();
2854  ASSERT(args->length() == 2);
2855  ASSERT_NE(NULL, args->at(1)->AsLiteral());
2856  Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->handle()));
2857
2858  VisitForAccumulatorValue(args->at(0));  // Load the object.
2859
2860  Label runtime, done;
2861  Register object = rax;
2862  Register result = rax;
2863  Register scratch = rcx;
2864
2865#ifdef DEBUG
2866  __ AbortIfSmi(object);
2867  __ CmpObjectType(object, JS_DATE_TYPE, scratch);
2868  __ Assert(equal, "Trying to get date field from non-date.");
2869#endif
2870
2871  if (index->value() == 0) {
2872    __ movq(result, FieldOperand(object, JSDate::kValueOffset));
2873  } else {
2874    if (index->value() < JSDate::kFirstUncachedField) {
2875      ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
2876      __ movq(scratch, stamp);
2877      __ cmpq(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
2878      __ j(not_equal, &runtime, Label::kNear);
2879      __ movq(result, FieldOperand(object, JSDate::kValueOffset +
2880                                           kPointerSize * index->value()));
2881      __ jmp(&done);
2882    }
2883    __ bind(&runtime);
2884    __ PrepareCallCFunction(2);
2885#ifdef _WIN64
2886  __ movq(rcx, object);
2887  __ movq(rdx, index, RelocInfo::NONE);
2888#else
2889  __ movq(rdi, object);
2890  __ movq(rsi, index, RelocInfo::NONE);
2891#endif
2892    __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
2893    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2894    __ bind(&done);
2895  }
2896  context()->Plug(rax);
2897}
2898
2899
2900void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
2901  // Load the arguments on the stack and call the runtime function.
2902  ZoneList<Expression*>* args = expr->arguments();
2903  ASSERT(args->length() == 2);
2904  VisitForStackValue(args->at(0));
2905  VisitForStackValue(args->at(1));
2906  MathPowStub stub(MathPowStub::ON_STACK);
2907  __ CallStub(&stub);
2908  context()->Plug(rax);
2909}
2910
2911
2912void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
2913  ZoneList<Expression*>* args = expr->arguments();
2914  ASSERT(args->length() == 2);
2915
2916  VisitForStackValue(args->at(0));  // Load the object.
2917  VisitForAccumulatorValue(args->at(1));  // Load the value.
2918  __ pop(rbx);  // rax = value. rbx = object.
2919
2920  Label done;
2921  // If the object is a smi, return the value.
2922  __ JumpIfSmi(rbx, &done);
2923
2924  // If the object is not a value type, return the value.
2925  __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx);
2926  __ j(not_equal, &done);
2927
2928  // Store the value.
2929  __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax);
2930  // Update the write barrier.  Save the value as it will be
2931  // overwritten by the write barrier code and is needed afterward.
2932  __ movq(rdx, rax);
2933  __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs);
2934
2935  __ bind(&done);
2936  context()->Plug(rax);
2937}
2938
2939
2940void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
2941  ZoneList<Expression*>* args = expr->arguments();
2942  ASSERT_EQ(args->length(), 1);
2943
2944  // Load the argument on the stack and call the stub.
2945  VisitForStackValue(args->at(0));
2946
2947  NumberToStringStub stub;
2948  __ CallStub(&stub);
2949  context()->Plug(rax);
2950}
2951
2952
2953void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
2954  ZoneList<Expression*>* args = expr->arguments();
2955  ASSERT(args->length() == 1);
2956
2957  VisitForAccumulatorValue(args->at(0));
2958
2959  Label done;
2960  StringCharFromCodeGenerator generator(rax, rbx);
2961  generator.GenerateFast(masm_);
2962  __ jmp(&done);
2963
2964  NopRuntimeCallHelper call_helper;
2965  generator.GenerateSlow(masm_, call_helper);
2966
2967  __ bind(&done);
2968  context()->Plug(rbx);
2969}
2970
2971
2972void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
2973  ZoneList<Expression*>* args = expr->arguments();
2974  ASSERT(args->length() == 2);
2975
2976  VisitForStackValue(args->at(0));
2977  VisitForAccumulatorValue(args->at(1));
2978
2979  Register object = rbx;
2980  Register index = rax;
2981  Register result = rdx;
2982
2983  __ pop(object);
2984
2985  Label need_conversion;
2986  Label index_out_of_range;
2987  Label done;
2988  StringCharCodeAtGenerator generator(object,
2989                                      index,
2990                                      result,
2991                                      &need_conversion,
2992                                      &need_conversion,
2993                                      &index_out_of_range,
2994                                      STRING_INDEX_IS_NUMBER);
2995  generator.GenerateFast(masm_);
2996  __ jmp(&done);
2997
2998  __ bind(&index_out_of_range);
2999  // When the index is out of range, the spec requires us to return
3000  // NaN.
3001  __ LoadRoot(result, Heap::kNanValueRootIndex);
3002  __ jmp(&done);
3003
3004  __ bind(&need_conversion);
3005  // Move the undefined value into the result register, which will
3006  // trigger conversion.
3007  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
3008  __ jmp(&done);
3009
3010  NopRuntimeCallHelper call_helper;
3011  generator.GenerateSlow(masm_, call_helper);
3012
3013  __ bind(&done);
3014  context()->Plug(result);
3015}
3016
3017
3018void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
3019  ZoneList<Expression*>* args = expr->arguments();
3020  ASSERT(args->length() == 2);
3021
3022  VisitForStackValue(args->at(0));
3023  VisitForAccumulatorValue(args->at(1));
3024
3025  Register object = rbx;
3026  Register index = rax;
3027  Register scratch = rdx;
3028  Register result = rax;
3029
3030  __ pop(object);
3031
3032  Label need_conversion;
3033  Label index_out_of_range;
3034  Label done;
3035  StringCharAtGenerator generator(object,
3036                                  index,
3037                                  scratch,
3038                                  result,
3039                                  &need_conversion,
3040                                  &need_conversion,
3041                                  &index_out_of_range,
3042                                  STRING_INDEX_IS_NUMBER);
3043  generator.GenerateFast(masm_);
3044  __ jmp(&done);
3045
3046  __ bind(&index_out_of_range);
3047  // When the index is out of range, the spec requires us to return
3048  // the empty string.
3049  __ LoadRoot(result, Heap::kEmptyStringRootIndex);
3050  __ jmp(&done);
3051
3052  __ bind(&need_conversion);
3053  // Move smi zero into the result register, which will trigger
3054  // conversion.
3055  __ Move(result, Smi::FromInt(0));
3056  __ jmp(&done);
3057
3058  NopRuntimeCallHelper call_helper;
3059  generator.GenerateSlow(masm_, call_helper);
3060
3061  __ bind(&done);
3062  context()->Plug(result);
3063}
3064
3065
3066void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3067  ZoneList<Expression*>* args = expr->arguments();
3068  ASSERT_EQ(2, args->length());
3069
3070  VisitForStackValue(args->at(0));
3071  VisitForStackValue(args->at(1));
3072
3073  StringAddStub stub(NO_STRING_ADD_FLAGS);
3074  __ CallStub(&stub);
3075  context()->Plug(rax);
3076}
3077
3078
3079void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3080  ZoneList<Expression*>* args = expr->arguments();
3081  ASSERT_EQ(2, args->length());
3082
3083  VisitForStackValue(args->at(0));
3084  VisitForStackValue(args->at(1));
3085
3086  StringCompareStub stub;
3087  __ CallStub(&stub);
3088  context()->Plug(rax);
3089}
3090
3091
3092void FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
3093  // Load the argument on the stack and call the stub.
3094  TranscendentalCacheStub stub(TranscendentalCache::SIN,
3095                               TranscendentalCacheStub::TAGGED);
3096  ZoneList<Expression*>* args = expr->arguments();
3097  ASSERT(args->length() == 1);
3098  VisitForStackValue(args->at(0));
3099  __ CallStub(&stub);
3100  context()->Plug(rax);
3101}
3102
3103
3104void FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
3105  // Load the argument on the stack and call the stub.
3106  TranscendentalCacheStub stub(TranscendentalCache::COS,
3107                               TranscendentalCacheStub::TAGGED);
3108  ZoneList<Expression*>* args = expr->arguments();
3109  ASSERT(args->length() == 1);
3110  VisitForStackValue(args->at(0));
3111  __ CallStub(&stub);
3112  context()->Plug(rax);
3113}
3114
3115
3116void FullCodeGenerator::EmitMathTan(CallRuntime* expr) {
3117  // Load the argument on the stack and call the stub.
3118  TranscendentalCacheStub stub(TranscendentalCache::TAN,
3119                               TranscendentalCacheStub::TAGGED);
3120  ZoneList<Expression*>* args = expr->arguments();
3121  ASSERT(args->length() == 1);
3122  VisitForStackValue(args->at(0));
3123  __ CallStub(&stub);
3124  context()->Plug(rax);
3125}
3126
3127
3128void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
3129  // Load the argument on the stack and call the stub.
3130  TranscendentalCacheStub stub(TranscendentalCache::LOG,
3131                               TranscendentalCacheStub::TAGGED);
3132  ZoneList<Expression*>* args = expr->arguments();
3133  ASSERT(args->length() == 1);
3134  VisitForStackValue(args->at(0));
3135  __ CallStub(&stub);
3136  context()->Plug(rax);
3137}
3138
3139
3140void FullCodeGenerator::EmitMathSqrt(CallRuntime* expr) {
3141  // Load the argument on the stack and call the runtime function.
3142  ZoneList<Expression*>* args = expr->arguments();
3143  ASSERT(args->length() == 1);
3144  VisitForStackValue(args->at(0));
3145  __ CallRuntime(Runtime::kMath_sqrt, 1);
3146  context()->Plug(rax);
3147}
3148
3149
3150void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
3151  ZoneList<Expression*>* args = expr->arguments();
3152  ASSERT(args->length() >= 2);
3153
3154  int arg_count = args->length() - 2;  // 2 ~ receiver and function.
3155  for (int i = 0; i < arg_count + 1; i++) {
3156    VisitForStackValue(args->at(i));
3157  }
3158  VisitForAccumulatorValue(args->last());  // Function.
3159
3160  // Check for proxy.
3161  Label proxy, done;
3162  __ CmpObjectType(rax, JS_FUNCTION_PROXY_TYPE, rbx);
3163  __ j(equal, &proxy);
3164
3165  // InvokeFunction requires the function in rdi. Move it in there.
3166  __ movq(rdi, result_register());
3167  ParameterCount count(arg_count);
3168  __ InvokeFunction(rdi, count, CALL_FUNCTION,
3169                    NullCallWrapper(), CALL_AS_METHOD);
3170  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3171  __ jmp(&done);
3172
3173  __ bind(&proxy);
3174  __ push(rax);
3175  __ CallRuntime(Runtime::kCall, args->length());
3176  __ bind(&done);
3177
3178  context()->Plug(rax);
3179}
3180
3181
3182void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3183  RegExpConstructResultStub stub;
3184  ZoneList<Expression*>* args = expr->arguments();
3185  ASSERT(args->length() == 3);
3186  VisitForStackValue(args->at(0));
3187  VisitForStackValue(args->at(1));
3188  VisitForStackValue(args->at(2));
3189  __ CallStub(&stub);
3190  context()->Plug(rax);
3191}
3192
3193
3194void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3195  ZoneList<Expression*>* args = expr->arguments();
3196  ASSERT_EQ(2, args->length());
3197
3198  ASSERT_NE(NULL, args->at(0)->AsLiteral());
3199  int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
3200
3201  Handle<FixedArray> jsfunction_result_caches(
3202      isolate()->global_context()->jsfunction_result_caches());
3203  if (jsfunction_result_caches->length() <= cache_id) {
3204    __ Abort("Attempt to use undefined cache.");
3205    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
3206    context()->Plug(rax);
3207    return;
3208  }
3209
3210  VisitForAccumulatorValue(args->at(1));
3211
3212  Register key = rax;
3213  Register cache = rbx;
3214  Register tmp = rcx;
3215  __ movq(cache, ContextOperand(rsi, Context::GLOBAL_INDEX));
3216  __ movq(cache,
3217          FieldOperand(cache, GlobalObject::kGlobalContextOffset));
3218  __ movq(cache,
3219          ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
3220  __ movq(cache,
3221          FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
3222
3223  Label done, not_found;
3224  // tmp now holds finger offset as a smi.
3225  STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3226  __ movq(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
3227  SmiIndex index =
3228      __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2);
3229  __ cmpq(key, FieldOperand(cache,
3230                            index.reg,
3231                            index.scale,
3232                            FixedArray::kHeaderSize));
3233  __ j(not_equal, &not_found, Label::kNear);
3234  __ movq(rax, FieldOperand(cache,
3235                            index.reg,
3236                            index.scale,
3237                            FixedArray::kHeaderSize + kPointerSize));
3238  __ jmp(&done, Label::kNear);
3239
3240  __ bind(&not_found);
3241  // Call runtime to perform the lookup.
3242  __ push(cache);
3243  __ push(key);
3244  __ CallRuntime(Runtime::kGetFromCache, 2);
3245
3246  __ bind(&done);
3247  context()->Plug(rax);
3248}
3249
3250
3251void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
3252  ZoneList<Expression*>* args = expr->arguments();
3253  ASSERT_EQ(2, args->length());
3254
3255  Register right = rax;
3256  Register left = rbx;
3257  Register tmp = rcx;
3258
3259  VisitForStackValue(args->at(0));
3260  VisitForAccumulatorValue(args->at(1));
3261  __ pop(left);
3262
3263  Label done, fail, ok;
3264  __ cmpq(left, right);
3265  __ j(equal, &ok, Label::kNear);
3266  // Fail if either is a non-HeapObject.
3267  Condition either_smi = masm()->CheckEitherSmi(left, right, tmp);
3268  __ j(either_smi, &fail, Label::kNear);
3269  __ j(zero, &fail, Label::kNear);
3270  __ movq(tmp, FieldOperand(left, HeapObject::kMapOffset));
3271  __ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset),
3272          Immediate(JS_REGEXP_TYPE));
3273  __ j(not_equal, &fail, Label::kNear);
3274  __ cmpq(tmp, FieldOperand(right, HeapObject::kMapOffset));
3275  __ j(not_equal, &fail, Label::kNear);
3276  __ movq(tmp, FieldOperand(left, JSRegExp::kDataOffset));
3277  __ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset));
3278  __ j(equal, &ok, Label::kNear);
3279  __ bind(&fail);
3280  __ Move(rax, isolate()->factory()->false_value());
3281  __ jmp(&done, Label::kNear);
3282  __ bind(&ok);
3283  __ Move(rax, isolate()->factory()->true_value());
3284  __ bind(&done);
3285
3286  context()->Plug(rax);
3287}
3288
3289
3290void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3291  ZoneList<Expression*>* args = expr->arguments();
3292  ASSERT(args->length() == 1);
3293
3294  VisitForAccumulatorValue(args->at(0));
3295
3296  Label materialize_true, materialize_false;
3297  Label* if_true = NULL;
3298  Label* if_false = NULL;
3299  Label* fall_through = NULL;
3300  context()->PrepareTest(&materialize_true, &materialize_false,
3301                         &if_true, &if_false, &fall_through);
3302
3303  __ testl(FieldOperand(rax, String::kHashFieldOffset),
3304           Immediate(String::kContainsCachedArrayIndexMask));
3305  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3306  __ j(zero, if_true);
3307  __ jmp(if_false);
3308
3309  context()->Plug(if_true, if_false);
3310}
3311
3312
3313void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
3314  ZoneList<Expression*>* args = expr->arguments();
3315  ASSERT(args->length() == 1);
3316  VisitForAccumulatorValue(args->at(0));
3317
3318  if (FLAG_debug_code) {
3319    __ AbortIfNotString(rax);
3320  }
3321
3322  __ movl(rax, FieldOperand(rax, String::kHashFieldOffset));
3323  ASSERT(String::kHashShift >= kSmiTagSize);
3324  __ IndexFromHash(rax, rax);
3325
3326  context()->Plug(rax);
3327}
3328
3329
3330void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
3331  Label bailout, return_result, done, one_char_separator, long_separator,
3332      non_trivial_array, not_size_one_array, loop,
3333      loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
3334  ZoneList<Expression*>* args = expr->arguments();
3335  ASSERT(args->length() == 2);
3336  // We will leave the separator on the stack until the end of the function.
3337  VisitForStackValue(args->at(1));
3338  // Load this to rax (= array)
3339  VisitForAccumulatorValue(args->at(0));
3340  // All aliases of the same register have disjoint lifetimes.
3341  Register array = rax;
3342  Register elements = no_reg;  // Will be rax.
3343
3344  Register index = rdx;
3345
3346  Register string_length = rcx;
3347
3348  Register string = rsi;
3349
3350  Register scratch = rbx;
3351
3352  Register array_length = rdi;
3353  Register result_pos = no_reg;  // Will be rdi.
3354
3355  Operand separator_operand =    Operand(rsp, 2 * kPointerSize);
3356  Operand result_operand =       Operand(rsp, 1 * kPointerSize);
3357  Operand array_length_operand = Operand(rsp, 0 * kPointerSize);
3358  // Separator operand is already pushed. Make room for the two
3359  // other stack fields, and clear the direction flag in anticipation
3360  // of calling CopyBytes.
3361  __ subq(rsp, Immediate(2 * kPointerSize));
3362  __ cld();
3363  // Check that the array is a JSArray
3364  __ JumpIfSmi(array, &bailout);
3365  __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
3366  __ j(not_equal, &bailout);
3367
3368  // Check that the array has fast elements.
3369  __ CheckFastElements(scratch, &bailout);
3370
3371  // Array has fast elements, so its length must be a smi.
3372  // If the array has length zero, return the empty string.
3373  __ movq(array_length, FieldOperand(array, JSArray::kLengthOffset));
3374  __ SmiCompare(array_length, Smi::FromInt(0));
3375  __ j(not_zero, &non_trivial_array);
3376  __ LoadRoot(rax, Heap::kEmptyStringRootIndex);
3377  __ jmp(&return_result);
3378
3379  // Save the array length on the stack.
3380  __ bind(&non_trivial_array);
3381  __ SmiToInteger32(array_length, array_length);
3382  __ movl(array_length_operand, array_length);
3383
3384  // Save the FixedArray containing array's elements.
3385  // End of array's live range.
3386  elements = array;
3387  __ movq(elements, FieldOperand(array, JSArray::kElementsOffset));
3388  array = no_reg;
3389
3390
3391  // Check that all array elements are sequential ASCII strings, and
3392  // accumulate the sum of their lengths, as a smi-encoded value.
3393  __ Set(index, 0);
3394  __ Set(string_length, 0);
3395  // Loop condition: while (index < array_length).
3396  // Live loop registers: index(int32), array_length(int32), string(String*),
3397  //                      scratch, string_length(int32), elements(FixedArray*).
3398  if (FLAG_debug_code) {
3399    __ cmpq(index, array_length);
3400    __ Assert(below, "No empty arrays here in EmitFastAsciiArrayJoin");
3401  }
3402  __ bind(&loop);
3403  __ movq(string, FieldOperand(elements,
3404                               index,
3405                               times_pointer_size,
3406                               FixedArray::kHeaderSize));
3407  __ JumpIfSmi(string, &bailout);
3408  __ movq(scratch, FieldOperand(string, HeapObject::kMapOffset));
3409  __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3410  __ andb(scratch, Immediate(
3411      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3412  __ cmpb(scratch, Immediate(kStringTag | kAsciiStringTag | kSeqStringTag));
3413  __ j(not_equal, &bailout);
3414  __ AddSmiField(string_length,
3415                 FieldOperand(string, SeqAsciiString::kLengthOffset));
3416  __ j(overflow, &bailout);
3417  __ incl(index);
3418  __ cmpl(index, array_length);
3419  __ j(less, &loop);
3420
3421  // Live registers:
3422  // string_length: Sum of string lengths.
3423  // elements: FixedArray of strings.
3424  // index: Array length.
3425  // array_length: Array length.
3426
3427  // If array_length is 1, return elements[0], a string.
3428  __ cmpl(array_length, Immediate(1));
3429  __ j(not_equal, &not_size_one_array);
3430  __ movq(rax, FieldOperand(elements, FixedArray::kHeaderSize));
3431  __ jmp(&return_result);
3432
3433  __ bind(&not_size_one_array);
3434
3435  // End of array_length live range.
3436  result_pos = array_length;
3437  array_length = no_reg;
3438
3439  // Live registers:
3440  // string_length: Sum of string lengths.
3441  // elements: FixedArray of strings.
3442  // index: Array length.
3443
3444  // Check that the separator is a sequential ASCII string.
3445  __ movq(string, separator_operand);
3446  __ JumpIfSmi(string, &bailout);
3447  __ movq(scratch, FieldOperand(string, HeapObject::kMapOffset));
3448  __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3449  __ andb(scratch, Immediate(
3450      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3451  __ cmpb(scratch, Immediate(kStringTag | kAsciiStringTag | kSeqStringTag));
3452  __ j(not_equal, &bailout);
3453
3454  // Live registers:
3455  // string_length: Sum of string lengths.
3456  // elements: FixedArray of strings.
3457  // index: Array length.
3458  // string: Separator string.
3459
3460  // Add (separator length times (array_length - 1)) to string_length.
3461  __ SmiToInteger32(scratch,
3462                    FieldOperand(string, SeqAsciiString::kLengthOffset));
3463  __ decl(index);
3464  __ imull(scratch, index);
3465  __ j(overflow, &bailout);
3466  __ addl(string_length, scratch);
3467  __ j(overflow, &bailout);
3468
3469  // Live registers and stack values:
3470  //   string_length: Total length of result string.
3471  //   elements: FixedArray of strings.
3472  __ AllocateAsciiString(result_pos, string_length, scratch,
3473                         index, string, &bailout);
3474  __ movq(result_operand, result_pos);
3475  __ lea(result_pos, FieldOperand(result_pos, SeqAsciiString::kHeaderSize));
3476
3477  __ movq(string, separator_operand);
3478  __ SmiCompare(FieldOperand(string, SeqAsciiString::kLengthOffset),
3479                Smi::FromInt(1));
3480  __ j(equal, &one_char_separator);
3481  __ j(greater, &long_separator);
3482
3483
3484  // Empty separator case:
3485  __ Set(index, 0);
3486  __ movl(scratch, array_length_operand);
3487  __ jmp(&loop_1_condition);
3488  // Loop condition: while (index < array_length).
3489  __ bind(&loop_1);
3490  // Each iteration of the loop concatenates one string to the result.
3491  // Live values in registers:
3492  //   index: which element of the elements array we are adding to the result.
3493  //   result_pos: the position to which we are currently copying characters.
3494  //   elements: the FixedArray of strings we are joining.
3495  //   scratch: array length.
3496
3497  // Get string = array[index].
3498  __ movq(string, FieldOperand(elements, index,
3499                               times_pointer_size,
3500                               FixedArray::kHeaderSize));
3501  __ SmiToInteger32(string_length,
3502                    FieldOperand(string, String::kLengthOffset));
3503  __ lea(string,
3504         FieldOperand(string, SeqAsciiString::kHeaderSize));
3505  __ CopyBytes(result_pos, string, string_length);
3506  __ incl(index);
3507  __ bind(&loop_1_condition);
3508  __ cmpl(index, scratch);
3509  __ j(less, &loop_1);  // Loop while (index < array_length).
3510  __ jmp(&done);
3511
3512  // Generic bailout code used from several places.
3513  __ bind(&bailout);
3514  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
3515  __ jmp(&return_result);
3516
3517
3518  // One-character separator case
3519  __ bind(&one_char_separator);
3520  // Get the separator ASCII character value.
3521  // Register "string" holds the separator.
3522  __ movzxbl(scratch, FieldOperand(string, SeqAsciiString::kHeaderSize));
3523  __ Set(index, 0);
3524  // Jump into the loop after the code that copies the separator, so the first
3525  // element is not preceded by a separator
3526  __ jmp(&loop_2_entry);
3527  // Loop condition: while (index < length).
3528  __ bind(&loop_2);
3529  // Each iteration of the loop concatenates one string to the result.
3530  // Live values in registers:
3531  //   elements: The FixedArray of strings we are joining.
3532  //   index: which element of the elements array we are adding to the result.
3533  //   result_pos: the position to which we are currently copying characters.
3534  //   scratch: Separator character.
3535
3536  // Copy the separator character to the result.
3537  __ movb(Operand(result_pos, 0), scratch);
3538  __ incq(result_pos);
3539
3540  __ bind(&loop_2_entry);
3541  // Get string = array[index].
3542  __ movq(string, FieldOperand(elements, index,
3543                               times_pointer_size,
3544                               FixedArray::kHeaderSize));
3545  __ SmiToInteger32(string_length,
3546                    FieldOperand(string, String::kLengthOffset));
3547  __ lea(string,
3548         FieldOperand(string, SeqAsciiString::kHeaderSize));
3549  __ CopyBytes(result_pos, string, string_length);
3550  __ incl(index);
3551  __ cmpl(index, array_length_operand);
3552  __ j(less, &loop_2);  // End while (index < length).
3553  __ jmp(&done);
3554
3555
3556  // Long separator case (separator is more than one character).
3557  __ bind(&long_separator);
3558
3559  // Make elements point to end of elements array, and index
3560  // count from -array_length to zero, so we don't need to maintain
3561  // a loop limit.
3562  __ movl(index, array_length_operand);
3563  __ lea(elements, FieldOperand(elements, index, times_pointer_size,
3564                                FixedArray::kHeaderSize));
3565  __ neg(index);
3566
3567  // Replace separator string with pointer to its first character, and
3568  // make scratch be its length.
3569  __ movq(string, separator_operand);
3570  __ SmiToInteger32(scratch,
3571                    FieldOperand(string, String::kLengthOffset));
3572  __ lea(string,
3573         FieldOperand(string, SeqAsciiString::kHeaderSize));
3574  __ movq(separator_operand, string);
3575
3576  // Jump into the loop after the code that copies the separator, so the first
3577  // element is not preceded by a separator
3578  __ jmp(&loop_3_entry);
3579  // Loop condition: while (index < length).
3580  __ bind(&loop_3);
3581  // Each iteration of the loop concatenates one string to the result.
3582  // Live values in registers:
3583  //   index: which element of the elements array we are adding to the result.
3584  //   result_pos: the position to which we are currently copying characters.
3585  //   scratch: Separator length.
3586  //   separator_operand (rsp[0x10]): Address of first char of separator.
3587
3588  // Copy the separator to the result.
3589  __ movq(string, separator_operand);
3590  __ movl(string_length, scratch);
3591  __ CopyBytes(result_pos, string, string_length, 2);
3592
3593  __ bind(&loop_3_entry);
3594  // Get string = array[index].
3595  __ movq(string, Operand(elements, index, times_pointer_size, 0));
3596  __ SmiToInteger32(string_length,
3597                    FieldOperand(string, String::kLengthOffset));
3598  __ lea(string,
3599         FieldOperand(string, SeqAsciiString::kHeaderSize));
3600  __ CopyBytes(result_pos, string, string_length);
3601  __ incq(index);
3602  __ j(not_equal, &loop_3);  // Loop while (index < 0).
3603
3604  __ bind(&done);
3605  __ movq(rax, result_operand);
3606
3607  __ bind(&return_result);
3608  // Drop temp values from the stack, and restore context register.
3609  __ addq(rsp, Immediate(3 * kPointerSize));
3610  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3611  context()->Plug(rax);
3612}
3613
3614
3615void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
3616  Handle<String> name = expr->name();
3617  if (name->length() > 0 && name->Get(0) == '_') {
3618    Comment cmnt(masm_, "[ InlineRuntimeCall");
3619    EmitInlineRuntimeCall(expr);
3620    return;
3621  }
3622
3623  Comment cmnt(masm_, "[ CallRuntime");
3624  ZoneList<Expression*>* args = expr->arguments();
3625
3626  if (expr->is_jsruntime()) {
3627    // Prepare for calling JS runtime function.
3628    __ movq(rax, GlobalObjectOperand());
3629    __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
3630  }
3631
3632  // Push the arguments ("left-to-right").
3633  int arg_count = args->length();
3634  for (int i = 0; i < arg_count; i++) {
3635    VisitForStackValue(args->at(i));
3636  }
3637
3638  if (expr->is_jsruntime()) {
3639    // Call the JS runtime function using a call IC.
3640    __ Move(rcx, expr->name());
3641    RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
3642    Handle<Code> ic =
3643        isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
3644    __ call(ic, mode, expr->id());
3645    // Restore context register.
3646    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3647  } else {
3648    __ CallRuntime(expr->function(), arg_count);
3649  }
3650  context()->Plug(rax);
3651}
3652
3653
3654void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3655  switch (expr->op()) {
3656    case Token::DELETE: {
3657      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
3658      Property* property = expr->expression()->AsProperty();
3659      VariableProxy* proxy = expr->expression()->AsVariableProxy();
3660
3661      if (property != NULL) {
3662        VisitForStackValue(property->obj());
3663        VisitForStackValue(property->key());
3664        StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE)
3665            ? kNonStrictMode : kStrictMode;
3666        __ Push(Smi::FromInt(strict_mode_flag));
3667        __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3668        context()->Plug(rax);
3669      } else if (proxy != NULL) {
3670        Variable* var = proxy->var();
3671        // Delete of an unqualified identifier is disallowed in strict mode
3672        // but "delete this" is allowed.
3673        ASSERT(language_mode() == CLASSIC_MODE || var->is_this());
3674        if (var->IsUnallocated()) {
3675          __ push(GlobalObjectOperand());
3676          __ Push(var->name());
3677          __ Push(Smi::FromInt(kNonStrictMode));
3678          __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3679          context()->Plug(rax);
3680        } else if (var->IsStackAllocated() || var->IsContextSlot()) {
3681          // Result of deleting non-global variables is false.  'this' is
3682          // not really a variable, though we implement it as one.  The
3683          // subexpression does not have side effects.
3684          context()->Plug(var->is_this());
3685        } else {
3686          // Non-global variable.  Call the runtime to try to delete from the
3687          // context where the variable was introduced.
3688          __ push(context_register());
3689          __ Push(var->name());
3690          __ CallRuntime(Runtime::kDeleteContextSlot, 2);
3691          context()->Plug(rax);
3692        }
3693      } else {
3694        // Result of deleting non-property, non-variable reference is true.
3695        // The subexpression may have side effects.
3696        VisitForEffect(expr->expression());
3697        context()->Plug(true);
3698      }
3699      break;
3700    }
3701
3702    case Token::VOID: {
3703      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
3704      VisitForEffect(expr->expression());
3705      context()->Plug(Heap::kUndefinedValueRootIndex);
3706      break;
3707    }
3708
3709    case Token::NOT: {
3710      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
3711      if (context()->IsEffect()) {
3712        // Unary NOT has no side effects so it's only necessary to visit the
3713        // subexpression.  Match the optimizing compiler by not branching.
3714        VisitForEffect(expr->expression());
3715      } else if (context()->IsTest()) {
3716        const TestContext* test = TestContext::cast(context());
3717        // The labels are swapped for the recursive call.
3718        VisitForControl(expr->expression(),
3719                        test->false_label(),
3720                        test->true_label(),
3721                        test->fall_through());
3722        context()->Plug(test->true_label(), test->false_label());
3723      } else {
3724        // We handle value contexts explicitly rather than simply visiting
3725        // for control and plugging the control flow into the context,
3726        // because we need to prepare a pair of extra administrative AST ids
3727        // for the optimizing compiler.
3728        ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
3729        Label materialize_true, materialize_false, done;
3730        VisitForControl(expr->expression(),
3731                        &materialize_false,
3732                        &materialize_true,
3733                        &materialize_true);
3734        __ bind(&materialize_true);
3735        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
3736        if (context()->IsAccumulatorValue()) {
3737          __ LoadRoot(rax, Heap::kTrueValueRootIndex);
3738        } else {
3739          __ PushRoot(Heap::kTrueValueRootIndex);
3740        }
3741        __ jmp(&done, Label::kNear);
3742        __ bind(&materialize_false);
3743        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
3744        if (context()->IsAccumulatorValue()) {
3745          __ LoadRoot(rax, Heap::kFalseValueRootIndex);
3746        } else {
3747          __ PushRoot(Heap::kFalseValueRootIndex);
3748        }
3749        __ bind(&done);
3750      }
3751      break;
3752    }
3753
3754    case Token::TYPEOF: {
3755      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
3756      { StackValueContext context(this);
3757        VisitForTypeofValue(expr->expression());
3758      }
3759      __ CallRuntime(Runtime::kTypeof, 1);
3760      context()->Plug(rax);
3761      break;
3762    }
3763
3764    case Token::ADD: {
3765      Comment cmt(masm_, "[ UnaryOperation (ADD)");
3766      VisitForAccumulatorValue(expr->expression());
3767      Label no_conversion;
3768      __ JumpIfSmi(result_register(), &no_conversion);
3769      ToNumberStub convert_stub;
3770      __ CallStub(&convert_stub);
3771      __ bind(&no_conversion);
3772      context()->Plug(result_register());
3773      break;
3774    }
3775
3776    case Token::SUB:
3777      EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
3778      break;
3779
3780    case Token::BIT_NOT:
3781      EmitUnaryOperation(expr, "[ UnaryOperation (BIT_NOT)");
3782      break;
3783
3784    default:
3785      UNREACHABLE();
3786  }
3787}
3788
3789
3790void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
3791                                           const char* comment) {
3792  // TODO(svenpanne): Allowing format strings in Comment would be nice here...
3793  Comment cmt(masm_, comment);
3794  bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
3795  UnaryOverwriteMode overwrite =
3796      can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
3797  UnaryOpStub stub(expr->op(), overwrite);
3798  // UnaryOpStub expects the argument to be in the
3799  // accumulator register rax.
3800  VisitForAccumulatorValue(expr->expression());
3801  SetSourcePosition(expr->position());
3802  __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
3803  context()->Plug(rax);
3804}
3805
3806
3807void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3808  Comment cmnt(masm_, "[ CountOperation");
3809  SetSourcePosition(expr->position());
3810
3811  // Invalid left-hand-sides are rewritten to have a 'throw
3812  // ReferenceError' as the left-hand side.
3813  if (!expr->expression()->IsValidLeftHandSide()) {
3814    VisitForEffect(expr->expression());
3815    return;
3816  }
3817
3818  // Expression can only be a property, a global or a (parameter or local)
3819  // slot.
3820  enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
3821  LhsKind assign_type = VARIABLE;
3822  Property* prop = expr->expression()->AsProperty();
3823  // In case of a property we use the uninitialized expression context
3824  // of the key to detect a named property.
3825  if (prop != NULL) {
3826    assign_type =
3827        (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
3828  }
3829
3830  // Evaluate expression and get value.
3831  if (assign_type == VARIABLE) {
3832    ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
3833    AccumulatorValueContext context(this);
3834    EmitVariableLoad(expr->expression()->AsVariableProxy());
3835  } else {
3836    // Reserve space for result of postfix operation.
3837    if (expr->is_postfix() && !context()->IsEffect()) {
3838      __ Push(Smi::FromInt(0));
3839    }
3840    if (assign_type == NAMED_PROPERTY) {
3841      VisitForAccumulatorValue(prop->obj());
3842      __ push(rax);  // Copy of receiver, needed for later store.
3843      EmitNamedPropertyLoad(prop);
3844    } else {
3845      VisitForStackValue(prop->obj());
3846      VisitForAccumulatorValue(prop->key());
3847      __ movq(rdx, Operand(rsp, 0));  // Leave receiver on stack
3848      __ push(rax);  // Copy of key, needed for later store.
3849      EmitKeyedPropertyLoad(prop);
3850    }
3851  }
3852
3853  // We need a second deoptimization point after loading the value
3854  // in case evaluating the property load my have a side effect.
3855  if (assign_type == VARIABLE) {
3856    PrepareForBailout(expr->expression(), TOS_REG);
3857  } else {
3858    PrepareForBailoutForId(expr->CountId(), TOS_REG);
3859  }
3860
3861  // Call ToNumber only if operand is not a smi.
3862  Label no_conversion;
3863  __ JumpIfSmi(rax, &no_conversion, Label::kNear);
3864  ToNumberStub convert_stub;
3865  __ CallStub(&convert_stub);
3866  __ bind(&no_conversion);
3867
3868  // Save result for postfix expressions.
3869  if (expr->is_postfix()) {
3870    if (!context()->IsEffect()) {
3871      // Save the result on the stack. If we have a named or keyed property
3872      // we store the result under the receiver that is currently on top
3873      // of the stack.
3874      switch (assign_type) {
3875        case VARIABLE:
3876          __ push(rax);
3877          break;
3878        case NAMED_PROPERTY:
3879          __ movq(Operand(rsp, kPointerSize), rax);
3880          break;
3881        case KEYED_PROPERTY:
3882          __ movq(Operand(rsp, 2 * kPointerSize), rax);
3883          break;
3884      }
3885    }
3886  }
3887
3888  // Inline smi case if we are in a loop.
3889  Label done, stub_call;
3890  JumpPatchSite patch_site(masm_);
3891
3892  if (ShouldInlineSmiCase(expr->op())) {
3893    if (expr->op() == Token::INC) {
3894      __ SmiAddConstant(rax, rax, Smi::FromInt(1));
3895    } else {
3896      __ SmiSubConstant(rax, rax, Smi::FromInt(1));
3897    }
3898    __ j(overflow, &stub_call, Label::kNear);
3899    // We could eliminate this smi check if we split the code at
3900    // the first smi check before calling ToNumber.
3901    patch_site.EmitJumpIfSmi(rax, &done, Label::kNear);
3902
3903    __ bind(&stub_call);
3904    // Call stub. Undo operation first.
3905    if (expr->op() == Token::INC) {
3906      __ SmiSubConstant(rax, rax, Smi::FromInt(1));
3907    } else {
3908      __ SmiAddConstant(rax, rax, Smi::FromInt(1));
3909    }
3910  }
3911
3912  // Record position before stub call.
3913  SetSourcePosition(expr->position());
3914
3915  // Call stub for +1/-1.
3916  BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
3917  if (expr->op() == Token::INC) {
3918    __ Move(rdx, Smi::FromInt(1));
3919  } else {
3920    __ movq(rdx, rax);
3921    __ Move(rax, Smi::FromInt(1));
3922  }
3923  __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId());
3924  patch_site.EmitPatchInfo();
3925  __ bind(&done);
3926
3927  // Store the value returned in rax.
3928  switch (assign_type) {
3929    case VARIABLE:
3930      if (expr->is_postfix()) {
3931        // Perform the assignment as if via '='.
3932        { EffectContext context(this);
3933          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3934                                 Token::ASSIGN);
3935          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3936          context.Plug(rax);
3937        }
3938        // For all contexts except kEffect: We have the result on
3939        // top of the stack.
3940        if (!context()->IsEffect()) {
3941          context()->PlugTOS();
3942        }
3943      } else {
3944        // Perform the assignment as if via '='.
3945        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3946                               Token::ASSIGN);
3947        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3948        context()->Plug(rax);
3949      }
3950      break;
3951    case NAMED_PROPERTY: {
3952      __ Move(rcx, prop->key()->AsLiteral()->handle());
3953      __ pop(rdx);
3954      Handle<Code> ic = is_classic_mode()
3955          ? isolate()->builtins()->StoreIC_Initialize()
3956          : isolate()->builtins()->StoreIC_Initialize_Strict();
3957      __ call(ic, RelocInfo::CODE_TARGET, expr->id());
3958      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3959      if (expr->is_postfix()) {
3960        if (!context()->IsEffect()) {
3961          context()->PlugTOS();
3962        }
3963      } else {
3964        context()->Plug(rax);
3965      }
3966      break;
3967    }
3968    case KEYED_PROPERTY: {
3969      __ pop(rcx);
3970      __ pop(rdx);
3971      Handle<Code> ic = is_classic_mode()
3972          ? isolate()->builtins()->KeyedStoreIC_Initialize()
3973          : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
3974      __ call(ic, RelocInfo::CODE_TARGET, expr->id());
3975      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3976      if (expr->is_postfix()) {
3977        if (!context()->IsEffect()) {
3978          context()->PlugTOS();
3979        }
3980      } else {
3981        context()->Plug(rax);
3982      }
3983      break;
3984    }
3985  }
3986}
3987
3988
3989void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
3990  VariableProxy* proxy = expr->AsVariableProxy();
3991  ASSERT(!context()->IsEffect());
3992  ASSERT(!context()->IsTest());
3993
3994  if (proxy != NULL && proxy->var()->IsUnallocated()) {
3995    Comment cmnt(masm_, "Global variable");
3996    __ Move(rcx, proxy->name());
3997    __ movq(rax, GlobalObjectOperand());
3998    Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
3999    // Use a regular load, not a contextual load, to avoid a reference
4000    // error.
4001    __ call(ic);
4002    PrepareForBailout(expr, TOS_REG);
4003    context()->Plug(rax);
4004  } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4005    Label done, slow;
4006
4007    // Generate code for loading from variables potentially shadowed
4008    // by eval-introduced variables.
4009    EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
4010
4011    __ bind(&slow);
4012    __ push(rsi);
4013    __ Push(proxy->name());
4014    __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
4015    PrepareForBailout(expr, TOS_REG);
4016    __ bind(&done);
4017
4018    context()->Plug(rax);
4019  } else {
4020    // This expression cannot throw a reference error at the top level.
4021    VisitInDuplicateContext(expr);
4022  }
4023}
4024
4025
4026void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
4027                                                 Expression* sub_expr,
4028                                                 Handle<String> check) {
4029  Label materialize_true, materialize_false;
4030  Label* if_true = NULL;
4031  Label* if_false = NULL;
4032  Label* fall_through = NULL;
4033  context()->PrepareTest(&materialize_true, &materialize_false,
4034                         &if_true, &if_false, &fall_through);
4035
4036  { AccumulatorValueContext context(this);
4037    VisitForTypeofValue(sub_expr);
4038  }
4039  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4040
4041  if (check->Equals(isolate()->heap()->number_symbol())) {
4042    __ JumpIfSmi(rax, if_true);
4043    __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
4044    __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
4045    Split(equal, if_true, if_false, fall_through);
4046  } else if (check->Equals(isolate()->heap()->string_symbol())) {
4047    __ JumpIfSmi(rax, if_false);
4048    // Check for undetectable objects => false.
4049    __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
4050    __ j(above_equal, if_false);
4051    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
4052             Immediate(1 << Map::kIsUndetectable));
4053    Split(zero, if_true, if_false, fall_through);
4054  } else if (check->Equals(isolate()->heap()->boolean_symbol())) {
4055    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
4056    __ j(equal, if_true);
4057    __ CompareRoot(rax, Heap::kFalseValueRootIndex);
4058    Split(equal, if_true, if_false, fall_through);
4059  } else if (FLAG_harmony_typeof &&
4060             check->Equals(isolate()->heap()->null_symbol())) {
4061    __ CompareRoot(rax, Heap::kNullValueRootIndex);
4062    Split(equal, if_true, if_false, fall_through);
4063  } else if (check->Equals(isolate()->heap()->undefined_symbol())) {
4064    __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
4065    __ j(equal, if_true);
4066    __ JumpIfSmi(rax, if_false);
4067    // Check for undetectable objects => true.
4068    __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
4069    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
4070             Immediate(1 << Map::kIsUndetectable));
4071    Split(not_zero, if_true, if_false, fall_through);
4072  } else if (check->Equals(isolate()->heap()->function_symbol())) {
4073    __ JumpIfSmi(rax, if_false);
4074    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
4075    __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx);
4076    __ j(equal, if_true);
4077    __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE);
4078    Split(equal, if_true, if_false, fall_through);
4079  } else if (check->Equals(isolate()->heap()->object_symbol())) {
4080    __ JumpIfSmi(rax, if_false);
4081    if (!FLAG_harmony_typeof) {
4082      __ CompareRoot(rax, Heap::kNullValueRootIndex);
4083      __ j(equal, if_true);
4084    }
4085    __ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx);
4086    __ j(below, if_false);
4087    __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
4088    __ j(above, if_false);
4089    // Check for undetectable objects => false.
4090    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
4091             Immediate(1 << Map::kIsUndetectable));
4092    Split(zero, if_true, if_false, fall_through);
4093  } else {
4094    if (if_false != fall_through) __ jmp(if_false);
4095  }
4096  context()->Plug(if_true, if_false);
4097}
4098
4099
4100void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4101  Comment cmnt(masm_, "[ CompareOperation");
4102  SetSourcePosition(expr->position());
4103
4104  // First we try a fast inlined version of the compare when one of
4105  // the operands is a literal.
4106  if (TryLiteralCompare(expr)) return;
4107
4108  // Always perform the comparison for its control flow.  Pack the result
4109  // into the expression's context after the comparison is performed.
4110  Label materialize_true, materialize_false;
4111  Label* if_true = NULL;
4112  Label* if_false = NULL;
4113  Label* fall_through = NULL;
4114  context()->PrepareTest(&materialize_true, &materialize_false,
4115                         &if_true, &if_false, &fall_through);
4116
4117  Token::Value op = expr->op();
4118  VisitForStackValue(expr->left());
4119  switch (op) {
4120    case Token::IN:
4121      VisitForStackValue(expr->right());
4122      __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
4123      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
4124      __ CompareRoot(rax, Heap::kTrueValueRootIndex);
4125      Split(equal, if_true, if_false, fall_through);
4126      break;
4127
4128    case Token::INSTANCEOF: {
4129      VisitForStackValue(expr->right());
4130      InstanceofStub stub(InstanceofStub::kNoFlags);
4131      __ CallStub(&stub);
4132      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4133      __ testq(rax, rax);
4134       // The stub returns 0 for true.
4135      Split(zero, if_true, if_false, fall_through);
4136      break;
4137    }
4138
4139    default: {
4140      VisitForAccumulatorValue(expr->right());
4141      Condition cc = no_condition;
4142      switch (op) {
4143        case Token::EQ_STRICT:
4144        case Token::EQ:
4145          cc = equal;
4146          break;
4147        case Token::LT:
4148          cc = less;
4149          break;
4150        case Token::GT:
4151          cc = greater;
4152         break;
4153        case Token::LTE:
4154          cc = less_equal;
4155          break;
4156        case Token::GTE:
4157          cc = greater_equal;
4158          break;
4159        case Token::IN:
4160        case Token::INSTANCEOF:
4161        default:
4162          UNREACHABLE();
4163      }
4164      __ pop(rdx);
4165
4166      bool inline_smi_code = ShouldInlineSmiCase(op);
4167      JumpPatchSite patch_site(masm_);
4168      if (inline_smi_code) {
4169        Label slow_case;
4170        __ movq(rcx, rdx);
4171        __ or_(rcx, rax);
4172        patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
4173        __ cmpq(rdx, rax);
4174        Split(cc, if_true, if_false, NULL);
4175        __ bind(&slow_case);
4176      }
4177
4178      // Record position and call the compare IC.
4179      SetSourcePosition(expr->position());
4180      Handle<Code> ic = CompareIC::GetUninitialized(op);
4181      __ call(ic, RelocInfo::CODE_TARGET, expr->id());
4182      patch_site.EmitPatchInfo();
4183
4184      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4185      __ testq(rax, rax);
4186      Split(cc, if_true, if_false, fall_through);
4187    }
4188  }
4189
4190  // Convert the result of the comparison into one expected for this
4191  // expression's context.
4192  context()->Plug(if_true, if_false);
4193}
4194
4195
4196void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
4197                                              Expression* sub_expr,
4198                                              NilValue nil) {
4199  Label materialize_true, materialize_false;
4200  Label* if_true = NULL;
4201  Label* if_false = NULL;
4202  Label* fall_through = NULL;
4203  context()->PrepareTest(&materialize_true, &materialize_false,
4204                         &if_true, &if_false, &fall_through);
4205
4206  VisitForAccumulatorValue(sub_expr);
4207  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4208  Heap::RootListIndex nil_value = nil == kNullValue ?
4209      Heap::kNullValueRootIndex :
4210      Heap::kUndefinedValueRootIndex;
4211  __ CompareRoot(rax, nil_value);
4212  if (expr->op() == Token::EQ_STRICT) {
4213    Split(equal, if_true, if_false, fall_through);
4214  } else {
4215    Heap::RootListIndex other_nil_value = nil == kNullValue ?
4216        Heap::kUndefinedValueRootIndex :
4217        Heap::kNullValueRootIndex;
4218    __ j(equal, if_true);
4219    __ CompareRoot(rax, other_nil_value);
4220    __ j(equal, if_true);
4221    __ JumpIfSmi(rax, if_false);
4222    // It can be an undetectable object.
4223    __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
4224    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
4225             Immediate(1 << Map::kIsUndetectable));
4226    Split(not_zero, if_true, if_false, fall_through);
4227  }
4228  context()->Plug(if_true, if_false);
4229}
4230
4231
4232void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4233  __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
4234  context()->Plug(rax);
4235}
4236
4237
4238Register FullCodeGenerator::result_register() {
4239  return rax;
4240}
4241
4242
4243Register FullCodeGenerator::context_register() {
4244  return rsi;
4245}
4246
4247
4248void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4249  ASSERT(IsAligned(frame_offset, kPointerSize));
4250  __ movq(Operand(rbp, frame_offset), value);
4251}
4252
4253
4254void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
4255  __ movq(dst, ContextOperand(rsi, context_index));
4256}
4257
4258
4259void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
4260  Scope* declaration_scope = scope()->DeclarationScope();
4261  if (declaration_scope->is_global_scope()) {
4262    // Contexts nested in the global context have a canonical empty function
4263    // as their closure, not the anonymous closure containing the global
4264    // code.  Pass a smi sentinel and let the runtime look up the empty
4265    // function.
4266    __ Push(Smi::FromInt(0));
4267  } else if (declaration_scope->is_eval_scope()) {
4268    // Contexts created by a call to eval have the same closure as the
4269    // context calling eval, not the anonymous closure containing the eval
4270    // code.  Fetch it from the context.
4271    __ push(ContextOperand(rsi, Context::CLOSURE_INDEX));
4272  } else {
4273    ASSERT(declaration_scope->is_function_scope());
4274    __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
4275  }
4276}
4277
4278
4279// ----------------------------------------------------------------------------
4280// Non-local control flow support.
4281
4282
4283void FullCodeGenerator::EnterFinallyBlock() {
4284  ASSERT(!result_register().is(rdx));
4285  ASSERT(!result_register().is(rcx));
4286  // Cook return address on top of stack (smi encoded Code* delta)
4287  __ pop(rdx);
4288  __ Move(rcx, masm_->CodeObject());
4289  __ subq(rdx, rcx);
4290  __ Integer32ToSmi(rdx, rdx);
4291  __ push(rdx);
4292  // Store result register while executing finally block.
4293  __ push(result_register());
4294}
4295
4296
4297void FullCodeGenerator::ExitFinallyBlock() {
4298  ASSERT(!result_register().is(rdx));
4299  ASSERT(!result_register().is(rcx));
4300  __ pop(result_register());
4301  // Uncook return address.
4302  __ pop(rdx);
4303  __ SmiToInteger32(rdx, rdx);
4304  __ Move(rcx, masm_->CodeObject());
4305  __ addq(rdx, rcx);
4306  __ jmp(rdx);
4307}
4308
4309
4310#undef __
4311
4312#define __ ACCESS_MASM(masm())
4313
4314FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
4315    int* stack_depth,
4316    int* context_length) {
4317  // The macros used here must preserve the result register.
4318
4319  // Because the handler block contains the context of the finally
4320  // code, we can restore it directly from there for the finally code
4321  // rather than iteratively unwinding contexts via their previous
4322  // links.
4323  __ Drop(*stack_depth);  // Down to the handler block.
4324  if (*context_length > 0) {
4325    // Restore the context to its dedicated register and the stack.
4326    __ movq(rsi, Operand(rsp, StackHandlerConstants::kContextOffset));
4327    __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
4328  }
4329  __ PopTryHandler();
4330  __ call(finally_entry_);
4331
4332  *stack_depth = 0;
4333  *context_length = 0;
4334  return previous_;
4335}
4336
4337
4338#undef __
4339
4340} }  // namespace v8::internal
4341
4342#endif  // V8_TARGET_ARCH_X64
4343