1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#if V8_TARGET_ARCH_X64
6
7#include "src/ast/scopes.h"
8#include "src/code-factory.h"
9#include "src/code-stubs.h"
10#include "src/codegen.h"
11#include "src/debug/debug.h"
12#include "src/full-codegen/full-codegen.h"
13#include "src/ic/ic.h"
14#include "src/parsing/parser.h"
15
16namespace v8 {
17namespace internal {
18
19#define __ ACCESS_MASM(masm())
20
21class JumpPatchSite BASE_EMBEDDED {
22 public:
23  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
24#ifdef DEBUG
25    info_emitted_ = false;
26#endif
27  }
28
29  ~JumpPatchSite() {
30    DCHECK(patch_site_.is_bound() == info_emitted_);
31  }
32
33  void EmitJumpIfNotSmi(Register reg,
34                        Label* target,
35                        Label::Distance near_jump = Label::kFar) {
36    __ testb(reg, Immediate(kSmiTagMask));
37    EmitJump(not_carry, target, near_jump);   // Always taken before patched.
38  }
39
40  void EmitJumpIfSmi(Register reg,
41                     Label* target,
42                     Label::Distance near_jump = Label::kFar) {
43    __ testb(reg, Immediate(kSmiTagMask));
44    EmitJump(carry, target, near_jump);  // Never taken before patched.
45  }
46
47  void EmitPatchInfo() {
48    if (patch_site_.is_bound()) {
49      int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
50      DCHECK(is_uint8(delta_to_patch_site));
51      __ testl(rax, Immediate(delta_to_patch_site));
52#ifdef DEBUG
53      info_emitted_ = true;
54#endif
55    } else {
56      __ nop();  // Signals no inlined code.
57    }
58  }
59
60 private:
61  // jc will be patched with jz, jnc will become jnz.
62  void EmitJump(Condition cc, Label* target, Label::Distance near_jump) {
63    DCHECK(!patch_site_.is_bound() && !info_emitted_);
64    DCHECK(cc == carry || cc == not_carry);
65    __ bind(&patch_site_);
66    __ j(cc, target, near_jump);
67  }
68
69  MacroAssembler* masm() { return masm_; }
70  MacroAssembler* masm_;
71  Label patch_site_;
72#ifdef DEBUG
73  bool info_emitted_;
74#endif
75};
76
77
78// Generate code for a JS function.  On entry to the function the receiver
79// and arguments have been pushed on the stack left to right, with the
80// return address on top of them.  The actual argument count matches the
81// formal parameter count expected by the function.
82//
83// The live registers are:
84//   o rdi: the JS function object being called (i.e. ourselves)
85//   o rdx: the new target value
86//   o rsi: our context
87//   o rbp: our caller's frame pointer
88//   o rsp: stack pointer (pointing to return address)
89//
90// The function builds a JS frame.  Please see JavaScriptFrameConstants in
91// frames-x64.h for its layout.
92void FullCodeGenerator::Generate() {
93  CompilationInfo* info = info_;
94  profiling_counter_ = isolate()->factory()->NewCell(
95      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
96  SetFunctionPosition(literal());
97  Comment cmnt(masm_, "[ function compiled by full code generator");
98
99  ProfileEntryHookStub::MaybeCallEntryHook(masm_);
100
101  if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
102    StackArgumentsAccessor args(rsp, info->scope()->num_parameters());
103    __ movp(rcx, args.GetReceiverOperand());
104    __ AssertNotSmi(rcx);
105    __ CmpObjectType(rcx, FIRST_JS_RECEIVER_TYPE, rcx);
106    __ Assert(above_equal, kSloppyFunctionExpectsJSReceiverReceiver);
107  }
108
109  // Open a frame scope to indicate that there is a frame on the stack.  The
110  // MANUAL indicates that the scope shouldn't actually generate code to set up
111  // the frame (that is done below).
112  FrameScope frame_scope(masm_, StackFrame::MANUAL);
113
114  info->set_prologue_offset(masm_->pc_offset());
115  __ Prologue(info->GeneratePreagedPrologue());
116
117  { Comment cmnt(masm_, "[ Allocate locals");
118    int locals_count = info->scope()->num_stack_slots();
119    // Generators allocate locals, if any, in context slots.
120    DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0);
121    OperandStackDepthIncrement(locals_count);
122    if (locals_count == 1) {
123      __ PushRoot(Heap::kUndefinedValueRootIndex);
124    } else if (locals_count > 1) {
125      if (locals_count >= 128) {
126        Label ok;
127        __ movp(rcx, rsp);
128        __ subp(rcx, Immediate(locals_count * kPointerSize));
129        __ CompareRoot(rcx, Heap::kRealStackLimitRootIndex);
130        __ j(above_equal, &ok, Label::kNear);
131        __ CallRuntime(Runtime::kThrowStackOverflow);
132        __ bind(&ok);
133      }
134      __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
135      const int kMaxPushes = 32;
136      if (locals_count >= kMaxPushes) {
137        int loop_iterations = locals_count / kMaxPushes;
138        __ movp(rcx, Immediate(loop_iterations));
139        Label loop_header;
140        __ bind(&loop_header);
141        // Do pushes.
142        for (int i = 0; i < kMaxPushes; i++) {
143          __ Push(rax);
144        }
145        // Continue loop if not done.
146        __ decp(rcx);
147        __ j(not_zero, &loop_header, Label::kNear);
148      }
149      int remaining = locals_count % kMaxPushes;
150      // Emit the remaining pushes.
151      for (int i  = 0; i < remaining; i++) {
152        __ Push(rax);
153      }
154    }
155  }
156
157  bool function_in_register = true;
158
159  // Possibly allocate a local context.
160  if (info->scope()->num_heap_slots() > 0) {
161    Comment cmnt(masm_, "[ Allocate context");
162    bool need_write_barrier = true;
163    int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
164    // Argument to NewContext is the function, which is still in rdi.
165    if (info->scope()->is_script_scope()) {
166      __ Push(rdi);
167      __ Push(info->scope()->GetScopeInfo(info->isolate()));
168      __ CallRuntime(Runtime::kNewScriptContext);
169      PrepareForBailoutForId(BailoutId::ScriptContext(),
170                             BailoutState::TOS_REGISTER);
171      // The new target value is not used, clobbering is safe.
172      DCHECK_NULL(info->scope()->new_target_var());
173    } else {
174      if (info->scope()->new_target_var() != nullptr) {
175        __ Push(rdx);  // Preserve new target.
176      }
177      if (slots <= FastNewContextStub::kMaximumSlots) {
178        FastNewContextStub stub(isolate(), slots);
179        __ CallStub(&stub);
180        // Result of FastNewContextStub is always in new space.
181        need_write_barrier = false;
182      } else {
183        __ Push(rdi);
184        __ CallRuntime(Runtime::kNewFunctionContext);
185      }
186      if (info->scope()->new_target_var() != nullptr) {
187        __ Pop(rdx);  // Restore new target.
188      }
189    }
190    function_in_register = false;
191    // Context is returned in rax.  It replaces the context passed to us.
192    // It's saved in the stack and kept live in rsi.
193    __ movp(rsi, rax);
194    __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax);
195
196    // Copy any necessary parameters into the context.
197    int num_parameters = info->scope()->num_parameters();
198    int first_parameter = info->scope()->has_this_declaration() ? -1 : 0;
199    for (int i = first_parameter; i < num_parameters; i++) {
200      Variable* var = (i == -1) ? scope()->receiver() : scope()->parameter(i);
201      if (var->IsContextSlot()) {
202        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
203            (num_parameters - 1 - i) * kPointerSize;
204        // Load parameter from stack.
205        __ movp(rax, Operand(rbp, parameter_offset));
206        // Store it in the context.
207        int context_offset = Context::SlotOffset(var->index());
208        __ movp(Operand(rsi, context_offset), rax);
209        // Update the write barrier.  This clobbers rax and rbx.
210        if (need_write_barrier) {
211          __ RecordWriteContextSlot(
212              rsi, context_offset, rax, rbx, kDontSaveFPRegs);
213        } else if (FLAG_debug_code) {
214          Label done;
215          __ JumpIfInNewSpace(rsi, rax, &done, Label::kNear);
216          __ Abort(kExpectedNewSpaceObject);
217          __ bind(&done);
218        }
219      }
220    }
221  }
222
223  // Register holding this function and new target are both trashed in case we
224  // bailout here. But since that can happen only when new target is not used
225  // and we allocate a context, the value of |function_in_register| is correct.
226  PrepareForBailoutForId(BailoutId::FunctionContext(),
227                         BailoutState::NO_REGISTERS);
228
229  // Possibly set up a local binding to the this function which is used in
230  // derived constructors with super calls.
231  Variable* this_function_var = scope()->this_function_var();
232  if (this_function_var != nullptr) {
233    Comment cmnt(masm_, "[ This function");
234    if (!function_in_register) {
235      __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
236      // The write barrier clobbers register again, keep it marked as such.
237    }
238    SetVar(this_function_var, rdi, rbx, rcx);
239  }
240
241  // Possibly set up a local binding to the new target value.
242  Variable* new_target_var = scope()->new_target_var();
243  if (new_target_var != nullptr) {
244    Comment cmnt(masm_, "[ new.target");
245    SetVar(new_target_var, rdx, rbx, rcx);
246  }
247
248  // Possibly allocate RestParameters
249  int rest_index;
250  Variable* rest_param = scope()->rest_parameter(&rest_index);
251  if (rest_param) {
252    Comment cmnt(masm_, "[ Allocate rest parameter array");
253    if (!function_in_register) {
254      __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
255    }
256    FastNewRestParameterStub stub(isolate());
257    __ CallStub(&stub);
258    function_in_register = false;
259    SetVar(rest_param, rax, rbx, rdx);
260  }
261
262  // Possibly allocate an arguments object.
263  Variable* arguments = scope()->arguments();
264  if (arguments != NULL) {
265    // Arguments object must be allocated after the context object, in
266    // case the "arguments" or ".arguments" variables are in the context.
267    Comment cmnt(masm_, "[ Allocate arguments object");
268    if (!function_in_register) {
269      __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
270    }
271    if (is_strict(language_mode()) || !has_simple_parameters()) {
272      FastNewStrictArgumentsStub stub(isolate());
273      __ CallStub(&stub);
274    } else if (literal()->has_duplicate_parameters()) {
275      __ Push(rdi);
276      __ CallRuntime(Runtime::kNewSloppyArguments_Generic);
277    } else {
278      FastNewSloppyArgumentsStub stub(isolate());
279      __ CallStub(&stub);
280    }
281
282    SetVar(arguments, rax, rbx, rdx);
283  }
284
285  if (FLAG_trace) {
286    __ CallRuntime(Runtime::kTraceEnter);
287  }
288
289  // Visit the declarations and body unless there is an illegal
290  // redeclaration.
291  PrepareForBailoutForId(BailoutId::FunctionEntry(),
292                         BailoutState::NO_REGISTERS);
293  {
294    Comment cmnt(masm_, "[ Declarations");
295    VisitDeclarations(scope()->declarations());
296  }
297
298  // Assert that the declarations do not use ICs. Otherwise the debugger
299  // won't be able to redirect a PC at an IC to the correct IC in newly
300  // recompiled code.
301  DCHECK_EQ(0, ic_total_count_);
302
303  {
304    Comment cmnt(masm_, "[ Stack check");
305    PrepareForBailoutForId(BailoutId::Declarations(),
306                           BailoutState::NO_REGISTERS);
307    Label ok;
308    __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
309    __ j(above_equal, &ok, Label::kNear);
310    __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET);
311    __ bind(&ok);
312  }
313
314  {
315    Comment cmnt(masm_, "[ Body");
316    DCHECK(loop_depth() == 0);
317    VisitStatements(literal()->body());
318    DCHECK(loop_depth() == 0);
319  }
320
321  // Always emit a 'return undefined' in case control fell off the end of
322  // the body.
323  { Comment cmnt(masm_, "[ return <undefined>;");
324    __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
325    EmitReturnSequence();
326  }
327}
328
329
330void FullCodeGenerator::ClearAccumulator() {
331  __ Set(rax, 0);
332}
333
334
335void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
336  __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
337  __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset),
338                    Smi::FromInt(-delta));
339}
340
341
342void FullCodeGenerator::EmitProfilingCounterReset() {
343  int reset_value = FLAG_interrupt_budget;
344  __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
345  __ Move(kScratchRegister, Smi::FromInt(reset_value));
346  __ movp(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister);
347}
348
349
350static const byte kJnsOffset = kPointerSize == kInt64Size ? 0x1d : 0x14;
351
352
353void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
354                                                Label* back_edge_target) {
355  Comment cmnt(masm_, "[ Back edge bookkeeping");
356  Label ok;
357
358  DCHECK(back_edge_target->is_bound());
359  int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
360  int weight = Min(kMaxBackEdgeWeight,
361                   Max(1, distance / kCodeSizeMultiplier));
362  EmitProfilingCounterDecrement(weight);
363
364  __ j(positive, &ok, Label::kNear);
365  {
366    PredictableCodeSizeScope predictible_code_size_scope(masm_, kJnsOffset);
367    DontEmitDebugCodeScope dont_emit_debug_code_scope(masm_);
368    __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
369
370    // Record a mapping of this PC offset to the OSR id.  This is used to find
371    // the AST id from the unoptimized code in order to use it as a key into
372    // the deoptimization input data found in the optimized code.
373    RecordBackEdge(stmt->OsrEntryId());
374
375    EmitProfilingCounterReset();
376  }
377  __ bind(&ok);
378
379  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
380  // Record a mapping of the OSR id to this PC.  This is used if the OSR
381  // entry becomes the target of a bailout.  We don't expect it to be, but
382  // we want it to work if it is.
383  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
384}
385
386void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
387    bool is_tail_call) {
388  // Pretend that the exit is a backwards jump to the entry.
389  int weight = 1;
390  if (info_->ShouldSelfOptimize()) {
391    weight = FLAG_interrupt_budget / FLAG_self_opt_count;
392  } else {
393    int distance = masm_->pc_offset();
394    weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier));
395  }
396  EmitProfilingCounterDecrement(weight);
397  Label ok;
398  __ j(positive, &ok, Label::kNear);
399  // Don't need to save result register if we are going to do a tail call.
400  if (!is_tail_call) {
401    __ Push(rax);
402  }
403  __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
404  if (!is_tail_call) {
405    __ Pop(rax);
406  }
407  EmitProfilingCounterReset();
408  __ bind(&ok);
409}
410
411void FullCodeGenerator::EmitReturnSequence() {
412  Comment cmnt(masm_, "[ Return sequence");
413  if (return_label_.is_bound()) {
414    __ jmp(&return_label_);
415  } else {
416    __ bind(&return_label_);
417    if (FLAG_trace) {
418      __ Push(rax);
419      __ CallRuntime(Runtime::kTraceExit);
420    }
421    EmitProfilingCounterHandlingForReturnSequence(false);
422
423    SetReturnPosition(literal());
424    __ leave();
425
426    int arg_count = info_->scope()->num_parameters() + 1;
427    int arguments_bytes = arg_count * kPointerSize;
428    __ Ret(arguments_bytes, rcx);
429  }
430}
431
432void FullCodeGenerator::RestoreContext() {
433  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
434}
435
436void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
437  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
438  MemOperand operand = codegen()->VarOperand(var, result_register());
439  codegen()->PushOperand(operand);
440}
441
442
443void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
444}
445
446
447void FullCodeGenerator::AccumulatorValueContext::Plug(
448    Heap::RootListIndex index) const {
449  __ LoadRoot(result_register(), index);
450}
451
452
453void FullCodeGenerator::StackValueContext::Plug(
454    Heap::RootListIndex index) const {
455  codegen()->OperandStackDepthIncrement(1);
456  __ PushRoot(index);
457}
458
459
460void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
461  codegen()->PrepareForBailoutBeforeSplit(condition(),
462                                          true,
463                                          true_label_,
464                                          false_label_);
465  if (index == Heap::kUndefinedValueRootIndex ||
466      index == Heap::kNullValueRootIndex ||
467      index == Heap::kFalseValueRootIndex) {
468    if (false_label_ != fall_through_) __ jmp(false_label_);
469  } else if (index == Heap::kTrueValueRootIndex) {
470    if (true_label_ != fall_through_) __ jmp(true_label_);
471  } else {
472    __ LoadRoot(result_register(), index);
473    codegen()->DoTest(this);
474  }
475}
476
477
478void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
479}
480
481
482void FullCodeGenerator::AccumulatorValueContext::Plug(
483    Handle<Object> lit) const {
484  if (lit->IsSmi()) {
485    __ SafeMove(result_register(), Smi::cast(*lit));
486  } else {
487    __ Move(result_register(), lit);
488  }
489}
490
491
492void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
493  codegen()->OperandStackDepthIncrement(1);
494  if (lit->IsSmi()) {
495    __ SafePush(Smi::cast(*lit));
496  } else {
497    __ Push(lit);
498  }
499}
500
501
502void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
503  codegen()->PrepareForBailoutBeforeSplit(condition(),
504                                          true,
505                                          true_label_,
506                                          false_label_);
507  DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
508         !lit->IsUndetectable());
509  if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
510      lit->IsFalse(isolate())) {
511    if (false_label_ != fall_through_) __ jmp(false_label_);
512  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
513    if (true_label_ != fall_through_) __ jmp(true_label_);
514  } else if (lit->IsString()) {
515    if (String::cast(*lit)->length() == 0) {
516      if (false_label_ != fall_through_) __ jmp(false_label_);
517    } else {
518      if (true_label_ != fall_through_) __ jmp(true_label_);
519    }
520  } else if (lit->IsSmi()) {
521    if (Smi::cast(*lit)->value() == 0) {
522      if (false_label_ != fall_through_) __ jmp(false_label_);
523    } else {
524      if (true_label_ != fall_through_) __ jmp(true_label_);
525    }
526  } else {
527    // For simplicity we always test the accumulator register.
528    __ Move(result_register(), lit);
529    codegen()->DoTest(this);
530  }
531}
532
533
534void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
535                                                       Register reg) const {
536  DCHECK(count > 0);
537  if (count > 1) codegen()->DropOperands(count - 1);
538  __ movp(Operand(rsp, 0), reg);
539}
540
541
542void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
543                                            Label* materialize_false) const {
544  DCHECK(materialize_true == materialize_false);
545  __ bind(materialize_true);
546}
547
548
549void FullCodeGenerator::AccumulatorValueContext::Plug(
550    Label* materialize_true,
551    Label* materialize_false) const {
552  Label done;
553  __ bind(materialize_true);
554  __ Move(result_register(), isolate()->factory()->true_value());
555  __ jmp(&done, Label::kNear);
556  __ bind(materialize_false);
557  __ Move(result_register(), isolate()->factory()->false_value());
558  __ bind(&done);
559}
560
561
562void FullCodeGenerator::StackValueContext::Plug(
563    Label* materialize_true,
564    Label* materialize_false) const {
565  codegen()->OperandStackDepthIncrement(1);
566  Label done;
567  __ bind(materialize_true);
568  __ Push(isolate()->factory()->true_value());
569  __ jmp(&done, Label::kNear);
570  __ bind(materialize_false);
571  __ Push(isolate()->factory()->false_value());
572  __ bind(&done);
573}
574
575
576void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
577                                          Label* materialize_false) const {
578  DCHECK(materialize_true == true_label_);
579  DCHECK(materialize_false == false_label_);
580}
581
582
583void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
584  Heap::RootListIndex value_root_index =
585      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
586  __ LoadRoot(result_register(), value_root_index);
587}
588
589
590void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
591  codegen()->OperandStackDepthIncrement(1);
592  Heap::RootListIndex value_root_index =
593      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
594  __ PushRoot(value_root_index);
595}
596
597
598void FullCodeGenerator::TestContext::Plug(bool flag) const {
599  codegen()->PrepareForBailoutBeforeSplit(condition(),
600                                          true,
601                                          true_label_,
602                                          false_label_);
603  if (flag) {
604    if (true_label_ != fall_through_) __ jmp(true_label_);
605  } else {
606    if (false_label_ != fall_through_) __ jmp(false_label_);
607  }
608}
609
610
611void FullCodeGenerator::DoTest(Expression* condition,
612                               Label* if_true,
613                               Label* if_false,
614                               Label* fall_through) {
615  Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
616  CallIC(ic, condition->test_id());
617  __ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
618  Split(equal, if_true, if_false, fall_through);
619}
620
621
622void FullCodeGenerator::Split(Condition cc,
623                              Label* if_true,
624                              Label* if_false,
625                              Label* fall_through) {
626  if (if_false == fall_through) {
627    __ j(cc, if_true);
628  } else if (if_true == fall_through) {
629    __ j(NegateCondition(cc), if_false);
630  } else {
631    __ j(cc, if_true);
632    __ jmp(if_false);
633  }
634}
635
636
637MemOperand FullCodeGenerator::StackOperand(Variable* var) {
638  DCHECK(var->IsStackAllocated());
639  // Offset is negative because higher indexes are at lower addresses.
640  int offset = -var->index() * kPointerSize;
641  // Adjust by a (parameter or local) base offset.
642  if (var->IsParameter()) {
643    offset += kFPOnStackSize + kPCOnStackSize +
644              (info_->scope()->num_parameters() - 1) * kPointerSize;
645  } else {
646    offset += JavaScriptFrameConstants::kLocal0Offset;
647  }
648  return Operand(rbp, offset);
649}
650
651
652MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
653  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
654  if (var->IsContextSlot()) {
655    int context_chain_length = scope()->ContextChainLength(var->scope());
656    __ LoadContext(scratch, context_chain_length);
657    return ContextOperand(scratch, var->index());
658  } else {
659    return StackOperand(var);
660  }
661}
662
663
664void FullCodeGenerator::GetVar(Register dest, Variable* var) {
665  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
666  MemOperand location = VarOperand(var, dest);
667  __ movp(dest, location);
668}
669
670
671void FullCodeGenerator::SetVar(Variable* var,
672                               Register src,
673                               Register scratch0,
674                               Register scratch1) {
675  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
676  DCHECK(!scratch0.is(src));
677  DCHECK(!scratch0.is(scratch1));
678  DCHECK(!scratch1.is(src));
679  MemOperand location = VarOperand(var, scratch0);
680  __ movp(location, src);
681
682  // Emit the write barrier code if the location is in the heap.
683  if (var->IsContextSlot()) {
684    int offset = Context::SlotOffset(var->index());
685    __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
686  }
687}
688
689
690void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
691                                                     bool should_normalize,
692                                                     Label* if_true,
693                                                     Label* if_false) {
694  // Only prepare for bailouts before splits if we're in a test
695  // context. Otherwise, we let the Visit function deal with the
696  // preparation to avoid preparing with the same AST id twice.
697  if (!context()->IsTest()) return;
698
699  Label skip;
700  if (should_normalize) __ jmp(&skip, Label::kNear);
701  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
702  if (should_normalize) {
703    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
704    Split(equal, if_true, if_false, NULL);
705    __ bind(&skip);
706  }
707}
708
709
710void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
711  // The variable in the declaration always resides in the current context.
712  DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
713  if (FLAG_debug_code) {
714    // Check that we're not inside a with or catch context.
715    __ movp(rbx, FieldOperand(rsi, HeapObject::kMapOffset));
716    __ CompareRoot(rbx, Heap::kWithContextMapRootIndex);
717    __ Check(not_equal, kDeclarationInWithContext);
718    __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
719    __ Check(not_equal, kDeclarationInCatchContext);
720  }
721}
722
723
724void FullCodeGenerator::VisitVariableDeclaration(
725    VariableDeclaration* declaration) {
726  // If it was not possible to allocate the variable at compile time, we
727  // need to "declare" it at runtime to make sure it actually exists in the
728  // local context.
729  VariableProxy* proxy = declaration->proxy();
730  VariableMode mode = declaration->mode();
731  Variable* variable = proxy->var();
732  bool hole_init = mode == LET || mode == CONST;
733  switch (variable->location()) {
734    case VariableLocation::GLOBAL:
735    case VariableLocation::UNALLOCATED:
736      DCHECK(!variable->binding_needs_init());
737      globals_->Add(variable->name(), zone());
738      globals_->Add(isolate()->factory()->undefined_value(), zone());
739      break;
740
741    case VariableLocation::PARAMETER:
742    case VariableLocation::LOCAL:
743      if (hole_init) {
744        Comment cmnt(masm_, "[ VariableDeclaration");
745        __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
746        __ movp(StackOperand(variable), kScratchRegister);
747      }
748      break;
749
750    case VariableLocation::CONTEXT:
751      if (hole_init) {
752        Comment cmnt(masm_, "[ VariableDeclaration");
753        EmitDebugCheckDeclarationContext(variable);
754        __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
755        __ movp(ContextOperand(rsi, variable->index()), kScratchRegister);
756        // No write barrier since the hole value is in old space.
757        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
758      }
759      break;
760
761    case VariableLocation::LOOKUP: {
762      Comment cmnt(masm_, "[ VariableDeclaration");
763      DCHECK_EQ(VAR, mode);
764      DCHECK(!hole_init);
765      __ Push(variable->name());
766      __ CallRuntime(Runtime::kDeclareEvalVar);
767      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
768      break;
769    }
770  }
771}
772
773
774void FullCodeGenerator::VisitFunctionDeclaration(
775    FunctionDeclaration* declaration) {
776  VariableProxy* proxy = declaration->proxy();
777  Variable* variable = proxy->var();
778  switch (variable->location()) {
779    case VariableLocation::GLOBAL:
780    case VariableLocation::UNALLOCATED: {
781      globals_->Add(variable->name(), zone());
782      Handle<SharedFunctionInfo> function =
783          Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
784      // Check for stack-overflow exception.
785      if (function.is_null()) return SetStackOverflow();
786      globals_->Add(function, zone());
787      break;
788    }
789
790    case VariableLocation::PARAMETER:
791    case VariableLocation::LOCAL: {
792      Comment cmnt(masm_, "[ FunctionDeclaration");
793      VisitForAccumulatorValue(declaration->fun());
794      __ movp(StackOperand(variable), result_register());
795      break;
796    }
797
798    case VariableLocation::CONTEXT: {
799      Comment cmnt(masm_, "[ FunctionDeclaration");
800      EmitDebugCheckDeclarationContext(variable);
801      VisitForAccumulatorValue(declaration->fun());
802      __ movp(ContextOperand(rsi, variable->index()), result_register());
803      int offset = Context::SlotOffset(variable->index());
804      // We know that we have written a function, which is not a smi.
805      __ RecordWriteContextSlot(rsi,
806                                offset,
807                                result_register(),
808                                rcx,
809                                kDontSaveFPRegs,
810                                EMIT_REMEMBERED_SET,
811                                OMIT_SMI_CHECK);
812      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
813      break;
814    }
815
816    case VariableLocation::LOOKUP: {
817      Comment cmnt(masm_, "[ FunctionDeclaration");
818      PushOperand(variable->name());
819      VisitForStackValue(declaration->fun());
820      CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
821      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
822      break;
823    }
824  }
825}
826
827
828void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
829  // Call the runtime to declare the globals.
830  __ Push(pairs);
831  __ Push(Smi::FromInt(DeclareGlobalsFlags()));
832  __ CallRuntime(Runtime::kDeclareGlobals);
833  // Return value is ignored.
834}
835
836
837void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) {
838  // Call the runtime to declare the modules.
839  __ Push(descriptions);
840  __ CallRuntime(Runtime::kDeclareModules);
841  // Return value is ignored.
842}
843
844
845void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
846  Comment cmnt(masm_, "[ SwitchStatement");
847  Breakable nested_statement(this, stmt);
848  SetStatementPosition(stmt);
849
850  // Keep the switch value on the stack until a case matches.
851  VisitForStackValue(stmt->tag());
852  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
853
854  ZoneList<CaseClause*>* clauses = stmt->cases();
855  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
856
857  Label next_test;  // Recycled for each test.
858  // Compile all the tests with branches to their bodies.
859  for (int i = 0; i < clauses->length(); i++) {
860    CaseClause* clause = clauses->at(i);
861    clause->body_target()->Unuse();
862
863    // The default is not a test, but remember it as final fall through.
864    if (clause->is_default()) {
865      default_clause = clause;
866      continue;
867    }
868
869    Comment cmnt(masm_, "[ Case comparison");
870    __ bind(&next_test);
871    next_test.Unuse();
872
873    // Compile the label expression.
874    VisitForAccumulatorValue(clause->label());
875
876    // Perform the comparison as if via '==='.
877    __ movp(rdx, Operand(rsp, 0));  // Switch value.
878    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
879    JumpPatchSite patch_site(masm_);
880    if (inline_smi_code) {
881      Label slow_case;
882      __ movp(rcx, rdx);
883      __ orp(rcx, rax);
884      patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
885
886      __ cmpp(rdx, rax);
887      __ j(not_equal, &next_test);
888      __ Drop(1);  // Switch value is no longer needed.
889      __ jmp(clause->body_target());
890      __ bind(&slow_case);
891    }
892
893    // Record position before stub call for type feedback.
894    SetExpressionPosition(clause);
895    Handle<Code> ic =
896        CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
897    CallIC(ic, clause->CompareId());
898    patch_site.EmitPatchInfo();
899
900    Label skip;
901    __ jmp(&skip, Label::kNear);
902    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
903    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
904    __ j(not_equal, &next_test);
905    __ Drop(1);
906    __ jmp(clause->body_target());
907    __ bind(&skip);
908
909    __ testp(rax, rax);
910    __ j(not_equal, &next_test);
911    __ Drop(1);  // Switch value is no longer needed.
912    __ jmp(clause->body_target());
913  }
914
915  // Discard the test value and jump to the default if present, otherwise to
916  // the end of the statement.
917  __ bind(&next_test);
918  DropOperands(1);  // Switch value is no longer needed.
919  if (default_clause == NULL) {
920    __ jmp(nested_statement.break_label());
921  } else {
922    __ jmp(default_clause->body_target());
923  }
924
925  // Compile all the case bodies.
926  for (int i = 0; i < clauses->length(); i++) {
927    Comment cmnt(masm_, "[ Case body");
928    CaseClause* clause = clauses->at(i);
929    __ bind(clause->body_target());
930    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
931    VisitStatements(clause->statements());
932  }
933
934  __ bind(nested_statement.break_label());
935  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
936}
937
938
939void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
940  Comment cmnt(masm_, "[ ForInStatement");
941  SetStatementPosition(stmt, SKIP_BREAK);
942
943  FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
944
945  // Get the object to enumerate over.
946  SetExpressionAsStatementPosition(stmt->enumerable());
947  VisitForAccumulatorValue(stmt->enumerable());
948  OperandStackDepthIncrement(5);
949
950  Label loop, exit;
951  Iteration loop_statement(this, stmt);
952  increment_loop_depth();
953
954  // If the object is null or undefined, skip over the loop, otherwise convert
955  // it to a JS receiver.  See ECMA-262 version 5, section 12.6.4.
956  Label convert, done_convert;
957  __ JumpIfSmi(rax, &convert, Label::kNear);
958  __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rcx);
959  __ j(above_equal, &done_convert, Label::kNear);
960  __ CompareRoot(rax, Heap::kNullValueRootIndex);
961  __ j(equal, &exit);
962  __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
963  __ j(equal, &exit);
964  __ bind(&convert);
965  ToObjectStub stub(isolate());
966  __ CallStub(&stub);
967  __ bind(&done_convert);
968  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
969  __ Push(rax);
970
971  // Check cache validity in generated code. If we cannot guarantee cache
972  // validity, call the runtime system to check cache validity or get the
973  // property names in a fixed array. Note: Proxies never have an enum cache,
974  // so will always take the slow path.
975  Label call_runtime;
976  __ CheckEnumCache(&call_runtime);
977
978  // The enum cache is valid.  Load the map of the object being
979  // iterated over and use the cache for the iteration.
980  Label use_cache;
981  __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
982  __ jmp(&use_cache, Label::kNear);
983
984  // Get the set of properties to enumerate.
985  __ bind(&call_runtime);
986  __ Push(rax);  // Duplicate the enumerable object on the stack.
987  __ CallRuntime(Runtime::kForInEnumerate);
988  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
989
990  // If we got a map from the runtime call, we can do a fast
991  // modification check. Otherwise, we got a fixed array, and we have
992  // to do a slow check.
993  Label fixed_array;
994  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
995                 Heap::kMetaMapRootIndex);
996  __ j(not_equal, &fixed_array);
997
998  // We got a map in register rax. Get the enumeration cache from it.
999  __ bind(&use_cache);
1000
1001  Label no_descriptors;
1002
1003  __ EnumLength(rdx, rax);
1004  __ Cmp(rdx, Smi::FromInt(0));
1005  __ j(equal, &no_descriptors);
1006
1007  __ LoadInstanceDescriptors(rax, rcx);
1008  __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheOffset));
1009  __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1010
1011  // Set up the four remaining stack slots.
1012  __ Push(rax);  // Map.
1013  __ Push(rcx);  // Enumeration cache.
1014  __ Push(rdx);  // Number of valid entries for the map in the enum cache.
1015  __ Push(Smi::FromInt(0));  // Initial index.
1016  __ jmp(&loop);
1017
1018  __ bind(&no_descriptors);
1019  __ addp(rsp, Immediate(kPointerSize));
1020  __ jmp(&exit);
1021
1022  // We got a fixed array in register rax. Iterate through that.
1023  __ bind(&fixed_array);
1024
1025  __ movp(rcx, Operand(rsp, 0 * kPointerSize));  // Get enumerated object
1026  __ Push(Smi::FromInt(1));                      // Smi(1) indicates slow check
1027  __ Push(rax);  // Array
1028  __ movp(rax, FieldOperand(rax, FixedArray::kLengthOffset));
1029  __ Push(rax);  // Fixed array length (as smi).
1030  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
1031  __ Push(Smi::FromInt(0));  // Initial index.
1032
1033  // Generate code for doing the condition check.
1034  __ bind(&loop);
1035  SetExpressionAsStatementPosition(stmt->each());
1036
1037  __ movp(rax, Operand(rsp, 0 * kPointerSize));  // Get the current index.
1038  __ cmpp(rax, Operand(rsp, 1 * kPointerSize));  // Compare to the array length.
1039  __ j(above_equal, loop_statement.break_label());
1040
1041  // Get the current entry of the array into register rbx.
1042  __ movp(rbx, Operand(rsp, 2 * kPointerSize));
1043  SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2);
1044  __ movp(rbx, FieldOperand(rbx,
1045                            index.reg,
1046                            index.scale,
1047                            FixedArray::kHeaderSize));
1048
1049  // Get the expected map from the stack or a smi in the
1050  // permanent slow case into register rdx.
1051  __ movp(rdx, Operand(rsp, 3 * kPointerSize));
1052
1053  // Check if the expected map still matches that of the enumerable.
1054  // If not, we may have to filter the key.
1055  Label update_each;
1056  __ movp(rcx, Operand(rsp, 4 * kPointerSize));
1057  __ cmpp(rdx, FieldOperand(rcx, HeapObject::kMapOffset));
1058  __ j(equal, &update_each, Label::kNear);
1059
1060  // We need to filter the key, record slow-path here.
1061  int const vector_index = SmiFromSlot(slot)->value();
1062  __ EmitLoadTypeFeedbackVector(rdx);
1063  __ Move(FieldOperand(rdx, FixedArray::OffsetOfElementAt(vector_index)),
1064          TypeFeedbackVector::MegamorphicSentinel(isolate()));
1065
1066  // Convert the entry to a string or null if it isn't a property
1067  // anymore. If the property has been removed while iterating, we
1068  // just skip it.
1069  __ Push(rcx);  // Enumerable.
1070  __ Push(rbx);  // Current entry.
1071  __ CallRuntime(Runtime::kForInFilter);
1072  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
1073  __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
1074  __ j(equal, loop_statement.continue_label());
1075  __ movp(rbx, rax);
1076
1077  // Update the 'each' property or variable from the possibly filtered
1078  // entry in register rbx.
1079  __ bind(&update_each);
1080  __ movp(result_register(), rbx);
1081  // Perform the assignment as if via '='.
1082  { EffectContext context(this);
1083    EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
1084    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
1085  }
1086
1087  // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
1088  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
1089  // Generate code for the body of the loop.
1090  Visit(stmt->body());
1091
1092  // Generate code for going to the next element by incrementing the
1093  // index (smi) stored on top of the stack.
1094  __ bind(loop_statement.continue_label());
1095  __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1));
1096
1097  EmitBackEdgeBookkeeping(stmt, &loop);
1098  __ jmp(&loop);
1099
1100  // Remove the pointers stored on the stack.
1101  __ bind(loop_statement.break_label());
1102  DropOperands(5);
1103
1104  // Exit and decrement the loop depth.
1105  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
1106  __ bind(&exit);
1107  decrement_loop_depth();
1108}
1109
1110
1111void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
1112                                          FeedbackVectorSlot slot) {
1113  DCHECK(NeedsHomeObject(initializer));
1114  __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
1115  __ Move(StoreDescriptor::NameRegister(),
1116          isolate()->factory()->home_object_symbol());
1117  __ movp(StoreDescriptor::ValueRegister(),
1118          Operand(rsp, offset * kPointerSize));
1119  EmitLoadStoreICSlot(slot);
1120  CallStoreIC();
1121}
1122
1123
1124void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer,
1125                                                     int offset,
1126                                                     FeedbackVectorSlot slot) {
1127  DCHECK(NeedsHomeObject(initializer));
1128  __ movp(StoreDescriptor::ReceiverRegister(), rax);
1129  __ Move(StoreDescriptor::NameRegister(),
1130          isolate()->factory()->home_object_symbol());
1131  __ movp(StoreDescriptor::ValueRegister(),
1132          Operand(rsp, offset * kPointerSize));
1133  EmitLoadStoreICSlot(slot);
1134  CallStoreIC();
1135}
1136
1137
1138void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
1139                                                      TypeofMode typeof_mode,
1140                                                      Label* slow) {
1141  Register context = rsi;
1142  Register temp = rdx;
1143
1144  Scope* s = scope();
1145  while (s != NULL) {
1146    if (s->num_heap_slots() > 0) {
1147      if (s->calls_sloppy_eval()) {
1148        // Check that extension is "the hole".
1149        __ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
1150                         Heap::kTheHoleValueRootIndex, slow);
1151      }
1152      // Load next context in chain.
1153      __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1154      // Walk the rest of the chain without clobbering rsi.
1155      context = temp;
1156    }
1157    // If no outer scope calls eval, we do not need to check more
1158    // context extensions.  If we have reached an eval scope, we check
1159    // all extensions from this point.
1160    if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
1161    s = s->outer_scope();
1162  }
1163
1164  if (s != NULL && s->is_eval_scope()) {
1165    // Loop up the context chain.  There is no frame effect so it is
1166    // safe to use raw labels here.
1167    Label next, fast;
1168    if (!context.is(temp)) {
1169      __ movp(temp, context);
1170    }
1171    // Load map for comparison into register, outside loop.
1172    __ LoadRoot(kScratchRegister, Heap::kNativeContextMapRootIndex);
1173    __ bind(&next);
1174    // Terminate at native context.
1175    __ cmpp(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset));
1176    __ j(equal, &fast, Label::kNear);
1177    // Check that extension is "the hole".
1178    __ JumpIfNotRoot(ContextOperand(temp, Context::EXTENSION_INDEX),
1179                     Heap::kTheHoleValueRootIndex, slow);
1180    // Load next context in chain.
1181    __ movp(temp, ContextOperand(temp, Context::PREVIOUS_INDEX));
1182    __ jmp(&next);
1183    __ bind(&fast);
1184  }
1185
1186  // All extension objects were empty and it is safe to use a normal global
1187  // load machinery.
1188  EmitGlobalVariableLoad(proxy, typeof_mode);
1189}
1190
1191
1192MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1193                                                                Label* slow) {
1194  DCHECK(var->IsContextSlot());
1195  Register context = rsi;
1196  Register temp = rbx;
1197
1198  for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
1199    if (s->num_heap_slots() > 0) {
1200      if (s->calls_sloppy_eval()) {
1201        // Check that extension is "the hole".
1202        __ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
1203                         Heap::kTheHoleValueRootIndex, slow);
1204      }
1205      __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1206      // Walk the rest of the chain without clobbering rsi.
1207      context = temp;
1208    }
1209  }
1210  // Check that last extension is "the hole".
1211  __ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
1212                   Heap::kTheHoleValueRootIndex, slow);
1213
1214  // This function is used only for loads, not stores, so it's safe to
1215  // return an rsi-based operand (the write barrier cannot be allowed to
1216  // destroy the rsi register).
1217  return ContextOperand(context, var->index());
1218}
1219
1220
1221void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
1222                                                  TypeofMode typeof_mode,
1223                                                  Label* slow, Label* done) {
1224  // Generate fast-case code for variables that might be shadowed by
1225  // eval-introduced variables.  Eval is used a lot without
1226  // introducing variables.  In those cases, we do not want to
1227  // perform a runtime call for all variables in the scope
1228  // containing the eval.
1229  Variable* var = proxy->var();
1230  if (var->mode() == DYNAMIC_GLOBAL) {
1231    EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow);
1232    __ jmp(done);
1233  } else if (var->mode() == DYNAMIC_LOCAL) {
1234    Variable* local = var->local_if_not_shadowed();
1235    __ movp(rax, ContextSlotOperandCheckExtensions(local, slow));
1236    if (local->mode() == LET || local->mode() == CONST) {
1237      __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1238      __ j(not_equal, done);
1239      __ Push(var->name());
1240      __ CallRuntime(Runtime::kThrowReferenceError);
1241    }
1242    __ jmp(done);
1243  }
1244}
1245
1246
1247void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
1248                                               TypeofMode typeof_mode) {
1249#ifdef DEBUG
1250  Variable* var = proxy->var();
1251  DCHECK(var->IsUnallocatedOrGlobalSlot() ||
1252         (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
1253#endif
1254  __ Move(LoadGlobalDescriptor::SlotRegister(),
1255          SmiFromSlot(proxy->VariableFeedbackSlot()));
1256  CallLoadGlobalIC(typeof_mode);
1257}
1258
1259
1260void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
1261                                         TypeofMode typeof_mode) {
1262  // Record position before possible IC call.
1263  SetExpressionPosition(proxy);
1264  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
1265  Variable* var = proxy->var();
1266
1267  // Three cases: global variables, lookup variables, and all other types of
1268  // variables.
1269  switch (var->location()) {
1270    case VariableLocation::GLOBAL:
1271    case VariableLocation::UNALLOCATED: {
1272      Comment cmnt(masm_, "[ Global variable");
1273      EmitGlobalVariableLoad(proxy, typeof_mode);
1274      context()->Plug(rax);
1275      break;
1276    }
1277
1278    case VariableLocation::PARAMETER:
1279    case VariableLocation::LOCAL:
1280    case VariableLocation::CONTEXT: {
1281      DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode);
1282      Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot"
1283                                               : "[ Stack slot");
1284      if (NeedsHoleCheckForLoad(proxy)) {
1285        // Let and const need a read barrier.
1286        Label done;
1287        GetVar(rax, var);
1288        __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1289        __ j(not_equal, &done, Label::kNear);
1290        if (var->mode() == LET || var->mode() == CONST) {
1291          // Throw a reference error when using an uninitialized let/const
1292          // binding in harmony mode.
1293          __ Push(var->name());
1294          __ CallRuntime(Runtime::kThrowReferenceError);
1295        }
1296        __ bind(&done);
1297        context()->Plug(rax);
1298        break;
1299      }
1300      context()->Plug(var);
1301      break;
1302    }
1303
1304    case VariableLocation::LOOKUP: {
1305      Comment cmnt(masm_, "[ Lookup slot");
1306      Label done, slow;
1307      // Generate code for loading from variables potentially shadowed
1308      // by eval-introduced variables.
1309      EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done);
1310      __ bind(&slow);
1311      __ Push(var->name());
1312      Runtime::FunctionId function_id =
1313          typeof_mode == NOT_INSIDE_TYPEOF
1314              ? Runtime::kLoadLookupSlot
1315              : Runtime::kLoadLookupSlotInsideTypeof;
1316      __ CallRuntime(function_id);
1317      __ bind(&done);
1318      context()->Plug(rax);
1319      break;
1320    }
1321  }
1322}
1323
1324
1325void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
1326  Expression* expression = (property == NULL) ? NULL : property->value();
1327  if (expression == NULL) {
1328    OperandStackDepthIncrement(1);
1329    __ PushRoot(Heap::kNullValueRootIndex);
1330  } else {
1331    VisitForStackValue(expression);
1332    if (NeedsHomeObject(expression)) {
1333      DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
1334             property->kind() == ObjectLiteral::Property::SETTER);
1335      int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
1336      EmitSetHomeObject(expression, offset, property->GetSlot());
1337    }
1338  }
1339}
1340
1341
1342void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1343  Comment cmnt(masm_, "[ ObjectLiteral");
1344
1345  Handle<FixedArray> constant_properties = expr->constant_properties();
1346  int flags = expr->ComputeFlags();
1347  if (MustCreateObjectLiteralWithRuntime(expr)) {
1348    __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1349    __ Push(Smi::FromInt(expr->literal_index()));
1350    __ Push(constant_properties);
1351    __ Push(Smi::FromInt(flags));
1352    __ CallRuntime(Runtime::kCreateObjectLiteral);
1353  } else {
1354    __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1355    __ Move(rbx, Smi::FromInt(expr->literal_index()));
1356    __ Move(rcx, constant_properties);
1357    __ Move(rdx, Smi::FromInt(flags));
1358    FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
1359    __ CallStub(&stub);
1360    RestoreContext();
1361  }
1362  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
1363
1364  // If result_saved is true the result is on top of the stack.  If
1365  // result_saved is false the result is in rax.
1366  bool result_saved = false;
1367
1368  AccessorTable accessor_table(zone());
1369  int property_index = 0;
1370  for (; property_index < expr->properties()->length(); property_index++) {
1371    ObjectLiteral::Property* property = expr->properties()->at(property_index);
1372    if (property->is_computed_name()) break;
1373    if (property->IsCompileTimeValue()) continue;
1374
1375    Literal* key = property->key()->AsLiteral();
1376    Expression* value = property->value();
1377    if (!result_saved) {
1378      PushOperand(rax);  // Save result on the stack
1379      result_saved = true;
1380    }
1381    switch (property->kind()) {
1382      case ObjectLiteral::Property::CONSTANT:
1383        UNREACHABLE();
1384      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1385        DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
1386        // Fall through.
1387      case ObjectLiteral::Property::COMPUTED:
1388        // It is safe to use [[Put]] here because the boilerplate already
1389        // contains computed properties with an uninitialized value.
1390        if (key->value()->IsInternalizedString()) {
1391          if (property->emit_store()) {
1392            VisitForAccumulatorValue(value);
1393            DCHECK(StoreDescriptor::ValueRegister().is(rax));
1394            __ Move(StoreDescriptor::NameRegister(), key->value());
1395            __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
1396            EmitLoadStoreICSlot(property->GetSlot(0));
1397            CallStoreIC();
1398            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
1399
1400            if (NeedsHomeObject(value)) {
1401              EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
1402            }
1403          } else {
1404            VisitForEffect(value);
1405          }
1406          break;
1407        }
1408        PushOperand(Operand(rsp, 0));  // Duplicate receiver.
1409        VisitForStackValue(key);
1410        VisitForStackValue(value);
1411        if (property->emit_store()) {
1412          if (NeedsHomeObject(value)) {
1413            EmitSetHomeObject(value, 2, property->GetSlot());
1414          }
1415          PushOperand(Smi::FromInt(SLOPPY));  // Language mode
1416          CallRuntimeWithOperands(Runtime::kSetProperty);
1417        } else {
1418          DropOperands(3);
1419        }
1420        break;
1421      case ObjectLiteral::Property::PROTOTYPE:
1422        PushOperand(Operand(rsp, 0));  // Duplicate receiver.
1423        VisitForStackValue(value);
1424        DCHECK(property->emit_store());
1425        CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
1426        PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
1427                               BailoutState::NO_REGISTERS);
1428        break;
1429      case ObjectLiteral::Property::GETTER:
1430        if (property->emit_store()) {
1431          AccessorTable::Iterator it = accessor_table.lookup(key);
1432          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
1433          it->second->getter = property;
1434        }
1435        break;
1436      case ObjectLiteral::Property::SETTER:
1437        if (property->emit_store()) {
1438          AccessorTable::Iterator it = accessor_table.lookup(key);
1439          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
1440          it->second->setter = property;
1441        }
1442        break;
1443    }
1444  }
1445
1446  // Emit code to define accessors, using only a single call to the runtime for
1447  // each pair of corresponding getters and setters.
1448  for (AccessorTable::Iterator it = accessor_table.begin();
1449       it != accessor_table.end();
1450       ++it) {
1451    PushOperand(Operand(rsp, 0));  // Duplicate receiver.
1452    VisitForStackValue(it->first);
1453    EmitAccessor(it->second->getter);
1454    EmitAccessor(it->second->setter);
1455    PushOperand(Smi::FromInt(NONE));
1456    CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
1457    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
1458  }
1459
1460  // Object literals have two parts. The "static" part on the left contains no
1461  // computed property names, and so we can compute its map ahead of time; see
1462  // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part
1463  // starts with the first computed property name, and continues with all
1464  // properties to its right.  All the code from above initializes the static
1465  // component of the object literal, and arranges for the map of the result to
1466  // reflect the static order in which the keys appear. For the dynamic
1467  // properties, we compile them into a series of "SetOwnProperty" runtime
1468  // calls. This will preserve insertion order.
1469  for (; property_index < expr->properties()->length(); property_index++) {
1470    ObjectLiteral::Property* property = expr->properties()->at(property_index);
1471
1472    Expression* value = property->value();
1473    if (!result_saved) {
1474      PushOperand(rax);  // Save result on the stack
1475      result_saved = true;
1476    }
1477
1478    PushOperand(Operand(rsp, 0));  // Duplicate receiver.
1479
1480    if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1481      DCHECK(!property->is_computed_name());
1482      VisitForStackValue(value);
1483      DCHECK(property->emit_store());
1484      CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
1485      PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
1486                             BailoutState::NO_REGISTERS);
1487    } else {
1488      EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
1489      VisitForStackValue(value);
1490      if (NeedsHomeObject(value)) {
1491        EmitSetHomeObject(value, 2, property->GetSlot());
1492      }
1493
1494      switch (property->kind()) {
1495        case ObjectLiteral::Property::CONSTANT:
1496        case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1497        case ObjectLiteral::Property::COMPUTED:
1498          if (property->emit_store()) {
1499            PushOperand(Smi::FromInt(NONE));
1500            PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
1501            CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
1502            PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
1503                                   BailoutState::NO_REGISTERS);
1504          } else {
1505            DropOperands(3);
1506          }
1507          break;
1508
1509        case ObjectLiteral::Property::PROTOTYPE:
1510          UNREACHABLE();
1511          break;
1512
1513        case ObjectLiteral::Property::GETTER:
1514          PushOperand(Smi::FromInt(NONE));
1515          CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked);
1516          break;
1517
1518        case ObjectLiteral::Property::SETTER:
1519          PushOperand(Smi::FromInt(NONE));
1520          CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked);
1521          break;
1522      }
1523    }
1524  }
1525
1526  if (result_saved) {
1527    context()->PlugTOS();
1528  } else {
1529    context()->Plug(rax);
1530  }
1531}
1532
1533
1534void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1535  Comment cmnt(masm_, "[ ArrayLiteral");
1536
1537  Handle<FixedArray> constant_elements = expr->constant_elements();
1538  bool has_constant_fast_elements =
1539      IsFastObjectElementsKind(expr->constant_elements_kind());
1540
1541  AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1542  if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
1543    // If the only customer of allocation sites is transitioning, then
1544    // we can turn it off if we don't have anywhere else to transition to.
1545    allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1546  }
1547
1548  if (MustCreateArrayLiteralWithRuntime(expr)) {
1549    __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1550    __ Push(Smi::FromInt(expr->literal_index()));
1551    __ Push(constant_elements);
1552    __ Push(Smi::FromInt(expr->ComputeFlags()));
1553    __ CallRuntime(Runtime::kCreateArrayLiteral);
1554  } else {
1555    __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1556    __ Move(rbx, Smi::FromInt(expr->literal_index()));
1557    __ Move(rcx, constant_elements);
1558    FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
1559    __ CallStub(&stub);
1560  }
1561  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
1562
1563  bool result_saved = false;  // Is the result saved to the stack?
1564  ZoneList<Expression*>* subexprs = expr->values();
1565  int length = subexprs->length();
1566
1567  // Emit code to evaluate all the non-constant subexpressions and to store
1568  // them into the newly cloned array.
1569  int array_index = 0;
1570  for (; array_index < length; array_index++) {
1571    Expression* subexpr = subexprs->at(array_index);
1572    DCHECK(!subexpr->IsSpread());
1573
1574    // If the subexpression is a literal or a simple materialized literal it
1575    // is already set in the cloned array.
1576    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1577
1578    if (!result_saved) {
1579      PushOperand(rax);  // array literal
1580      result_saved = true;
1581    }
1582    VisitForAccumulatorValue(subexpr);
1583
1584    __ Move(StoreDescriptor::NameRegister(), Smi::FromInt(array_index));
1585    __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
1586    EmitLoadStoreICSlot(expr->LiteralFeedbackSlot());
1587    Handle<Code> ic =
1588        CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
1589    CallIC(ic);
1590
1591    PrepareForBailoutForId(expr->GetIdForElement(array_index),
1592                           BailoutState::NO_REGISTERS);
1593  }
1594
1595  // In case the array literal contains spread expressions it has two parts. The
1596  // first part is  the "static" array which has a literal index is  handled
1597  // above. The second part is the part after the first spread expression
1598  // (inclusive) and these elements gets appended to the array. Note that the
1599  // number elements an iterable produces is unknown ahead of time.
1600  if (array_index < length && result_saved) {
1601    PopOperand(rax);
1602    result_saved = false;
1603  }
1604  for (; array_index < length; array_index++) {
1605    Expression* subexpr = subexprs->at(array_index);
1606
1607    PushOperand(rax);
1608    DCHECK(!subexpr->IsSpread());
1609    VisitForStackValue(subexpr);
1610    CallRuntimeWithOperands(Runtime::kAppendElement);
1611
1612    PrepareForBailoutForId(expr->GetIdForElement(array_index),
1613                           BailoutState::NO_REGISTERS);
1614  }
1615
1616  if (result_saved) {
1617    context()->PlugTOS();
1618  } else {
1619    context()->Plug(rax);
1620  }
1621}
1622
1623
1624void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1625  DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
1626
1627  Comment cmnt(masm_, "[ Assignment");
1628
1629  Property* property = expr->target()->AsProperty();
1630  LhsKind assign_type = Property::GetAssignType(property);
1631
1632  // Evaluate LHS expression.
1633  switch (assign_type) {
1634    case VARIABLE:
1635      // Nothing to do here.
1636      break;
1637    case NAMED_PROPERTY:
1638      if (expr->is_compound()) {
1639        // We need the receiver both on the stack and in the register.
1640        VisitForStackValue(property->obj());
1641        __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
1642      } else {
1643        VisitForStackValue(property->obj());
1644      }
1645      break;
1646    case NAMED_SUPER_PROPERTY:
1647      VisitForStackValue(
1648          property->obj()->AsSuperPropertyReference()->this_var());
1649      VisitForAccumulatorValue(
1650          property->obj()->AsSuperPropertyReference()->home_object());
1651      PushOperand(result_register());
1652      if (expr->is_compound()) {
1653        PushOperand(MemOperand(rsp, kPointerSize));
1654        PushOperand(result_register());
1655      }
1656      break;
1657    case KEYED_SUPER_PROPERTY:
1658      VisitForStackValue(
1659          property->obj()->AsSuperPropertyReference()->this_var());
1660      VisitForStackValue(
1661          property->obj()->AsSuperPropertyReference()->home_object());
1662      VisitForAccumulatorValue(property->key());
1663      PushOperand(result_register());
1664      if (expr->is_compound()) {
1665        PushOperand(MemOperand(rsp, 2 * kPointerSize));
1666        PushOperand(MemOperand(rsp, 2 * kPointerSize));
1667        PushOperand(result_register());
1668      }
1669      break;
1670    case KEYED_PROPERTY: {
1671      if (expr->is_compound()) {
1672        VisitForStackValue(property->obj());
1673        VisitForStackValue(property->key());
1674        __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize));
1675        __ movp(LoadDescriptor::NameRegister(), Operand(rsp, 0));
1676      } else {
1677        VisitForStackValue(property->obj());
1678        VisitForStackValue(property->key());
1679      }
1680      break;
1681    }
1682  }
1683
1684  // For compound assignments we need another deoptimization point after the
1685  // variable/property load.
1686  if (expr->is_compound()) {
1687    { AccumulatorValueContext context(this);
1688      switch (assign_type) {
1689        case VARIABLE:
1690          EmitVariableLoad(expr->target()->AsVariableProxy());
1691          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
1692          break;
1693        case NAMED_PROPERTY:
1694          EmitNamedPropertyLoad(property);
1695          PrepareForBailoutForId(property->LoadId(),
1696                                 BailoutState::TOS_REGISTER);
1697          break;
1698        case NAMED_SUPER_PROPERTY:
1699          EmitNamedSuperPropertyLoad(property);
1700          PrepareForBailoutForId(property->LoadId(),
1701                                 BailoutState::TOS_REGISTER);
1702          break;
1703        case KEYED_SUPER_PROPERTY:
1704          EmitKeyedSuperPropertyLoad(property);
1705          PrepareForBailoutForId(property->LoadId(),
1706                                 BailoutState::TOS_REGISTER);
1707          break;
1708        case KEYED_PROPERTY:
1709          EmitKeyedPropertyLoad(property);
1710          PrepareForBailoutForId(property->LoadId(),
1711                                 BailoutState::TOS_REGISTER);
1712          break;
1713      }
1714    }
1715
1716    Token::Value op = expr->binary_op();
1717    PushOperand(rax);  // Left operand goes on the stack.
1718    VisitForAccumulatorValue(expr->value());
1719
1720    AccumulatorValueContext context(this);
1721    if (ShouldInlineSmiCase(op)) {
1722      EmitInlineSmiBinaryOp(expr->binary_operation(),
1723                            op,
1724                            expr->target(),
1725                            expr->value());
1726    } else {
1727      EmitBinaryOp(expr->binary_operation(), op);
1728    }
1729    // Deoptimization point in case the binary operation may have side effects.
1730    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
1731  } else {
1732    VisitForAccumulatorValue(expr->value());
1733  }
1734
1735  SetExpressionPosition(expr);
1736
1737  // Store the value.
1738  switch (assign_type) {
1739    case VARIABLE:
1740      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1741                             expr->op(), expr->AssignmentSlot());
1742      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
1743      context()->Plug(rax);
1744      break;
1745    case NAMED_PROPERTY:
1746      EmitNamedPropertyAssignment(expr);
1747      break;
1748    case NAMED_SUPER_PROPERTY:
1749      EmitNamedSuperPropertyStore(property);
1750      context()->Plug(rax);
1751      break;
1752    case KEYED_SUPER_PROPERTY:
1753      EmitKeyedSuperPropertyStore(property);
1754      context()->Plug(rax);
1755      break;
1756    case KEYED_PROPERTY:
1757      EmitKeyedPropertyAssignment(expr);
1758      break;
1759  }
1760}
1761
1762
1763void FullCodeGenerator::VisitYield(Yield* expr) {
1764  Comment cmnt(masm_, "[ Yield");
1765  SetExpressionPosition(expr);
1766
1767  // Evaluate yielded value first; the initial iterator definition depends on
1768  // this.  It stays on the stack while we update the iterator.
1769  VisitForStackValue(expr->expression());
1770
1771  Label suspend, continuation, post_runtime, resume, exception;
1772
1773  __ jmp(&suspend);
1774  __ bind(&continuation);
1775  // When we arrive here, rax holds the generator object.
1776  __ RecordGeneratorContinuation();
1777  __ movp(rbx, FieldOperand(rax, JSGeneratorObject::kResumeModeOffset));
1778  __ movp(rax, FieldOperand(rax, JSGeneratorObject::kInputOrDebugPosOffset));
1779  STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
1780  STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
1781  __ SmiCompare(rbx, Smi::FromInt(JSGeneratorObject::kReturn));
1782  __ j(less, &resume);
1783  __ Push(result_register());
1784  __ j(greater, &exception);
1785  EmitCreateIteratorResult(true);
1786  EmitUnwindAndReturn();
1787
1788  __ bind(&exception);
1789  __ CallRuntime(Runtime::kThrow);
1790
1791  __ bind(&suspend);
1792  OperandStackDepthIncrement(1);  // Not popped on this path.
1793  VisitForAccumulatorValue(expr->generator_object());
1794  DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
1795  __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset),
1796          Smi::FromInt(continuation.pos()));
1797  __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi);
1798  __ movp(rcx, rsi);
1799  __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx,
1800                      kDontSaveFPRegs);
1801  __ leap(rbx, Operand(rbp, StandardFrameConstants::kExpressionsOffset));
1802  __ cmpp(rsp, rbx);
1803  __ j(equal, &post_runtime);
1804  __ Push(rax);  // generator object
1805  __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
1806  RestoreContext();
1807  __ bind(&post_runtime);
1808
1809  PopOperand(result_register());
1810  EmitReturnSequence();
1811
1812  __ bind(&resume);
1813  context()->Plug(result_register());
1814}
1815
1816void FullCodeGenerator::PushOperand(MemOperand operand) {
1817  OperandStackDepthIncrement(1);
1818  __ Push(operand);
1819}
1820
1821void FullCodeGenerator::EmitOperandStackDepthCheck() {
1822  if (FLAG_debug_code) {
1823    int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp +
1824                        operand_stack_depth_ * kPointerSize;
1825    __ movp(rax, rbp);
1826    __ subp(rax, rsp);
1827    __ cmpp(rax, Immediate(expected_diff));
1828    __ Assert(equal, kUnexpectedStackDepth);
1829  }
1830}
1831
1832void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
1833  Label allocate, done_allocate;
1834
1835  __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &allocate,
1836              NO_ALLOCATION_FLAGS);
1837  __ jmp(&done_allocate, Label::kNear);
1838
1839  __ bind(&allocate);
1840  __ Push(Smi::FromInt(JSIteratorResult::kSize));
1841  __ CallRuntime(Runtime::kAllocateInNewSpace);
1842
1843  __ bind(&done_allocate);
1844  __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, rbx);
1845  __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx);
1846  __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex);
1847  __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx);
1848  __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx);
1849  __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset));
1850  __ LoadRoot(FieldOperand(rax, JSIteratorResult::kDoneOffset),
1851              done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex);
1852  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
1853  OperandStackDepthDecrement(1);
1854}
1855
1856
1857void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
1858                                              Token::Value op,
1859                                              Expression* left,
1860                                              Expression* right) {
1861  // Do combined smi check of the operands. Left operand is on the
1862  // stack (popped into rdx). Right operand is in rax but moved into
1863  // rcx to make the shifts easier.
1864  Label done, stub_call, smi_case;
1865  PopOperand(rdx);
1866  __ movp(rcx, rax);
1867  __ orp(rax, rdx);
1868  JumpPatchSite patch_site(masm_);
1869  patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear);
1870
1871  __ bind(&stub_call);
1872  __ movp(rax, rcx);
1873  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
1874  CallIC(code, expr->BinaryOperationFeedbackId());
1875  patch_site.EmitPatchInfo();
1876  __ jmp(&done, Label::kNear);
1877
1878  __ bind(&smi_case);
1879  switch (op) {
1880    case Token::SAR:
1881      __ SmiShiftArithmeticRight(rax, rdx, rcx);
1882      break;
1883    case Token::SHL:
1884      __ SmiShiftLeft(rax, rdx, rcx, &stub_call);
1885      break;
1886    case Token::SHR:
1887      __ SmiShiftLogicalRight(rax, rdx, rcx, &stub_call);
1888      break;
1889    case Token::ADD:
1890      __ SmiAdd(rax, rdx, rcx, &stub_call);
1891      break;
1892    case Token::SUB:
1893      __ SmiSub(rax, rdx, rcx, &stub_call);
1894      break;
1895    case Token::MUL:
1896      __ SmiMul(rax, rdx, rcx, &stub_call);
1897      break;
1898    case Token::BIT_OR:
1899      __ SmiOr(rax, rdx, rcx);
1900      break;
1901    case Token::BIT_AND:
1902      __ SmiAnd(rax, rdx, rcx);
1903      break;
1904    case Token::BIT_XOR:
1905      __ SmiXor(rax, rdx, rcx);
1906      break;
1907    default:
1908      UNREACHABLE();
1909      break;
1910  }
1911
1912  __ bind(&done);
1913  context()->Plug(rax);
1914}
1915
1916
1917void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
1918  for (int i = 0; i < lit->properties()->length(); i++) {
1919    ObjectLiteral::Property* property = lit->properties()->at(i);
1920    Expression* value = property->value();
1921
1922    if (property->is_static()) {
1923      PushOperand(Operand(rsp, kPointerSize));  // constructor
1924    } else {
1925      PushOperand(Operand(rsp, 0));  // prototype
1926    }
1927    EmitPropertyKey(property, lit->GetIdForProperty(i));
1928
1929    // The static prototype property is read only. We handle the non computed
1930    // property name case in the parser. Since this is the only case where we
1931    // need to check for an own read only property we special case this so we do
1932    // not need to do this for every property.
1933    if (property->is_static() && property->is_computed_name()) {
1934      __ CallRuntime(Runtime::kThrowIfStaticPrototype);
1935      __ Push(rax);
1936    }
1937
1938    VisitForStackValue(value);
1939    if (NeedsHomeObject(value)) {
1940      EmitSetHomeObject(value, 2, property->GetSlot());
1941    }
1942
1943    switch (property->kind()) {
1944      case ObjectLiteral::Property::CONSTANT:
1945      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1946      case ObjectLiteral::Property::PROTOTYPE:
1947        UNREACHABLE();
1948      case ObjectLiteral::Property::COMPUTED:
1949        PushOperand(Smi::FromInt(DONT_ENUM));
1950        PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
1951        CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
1952        break;
1953
1954      case ObjectLiteral::Property::GETTER:
1955        PushOperand(Smi::FromInt(DONT_ENUM));
1956        CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked);
1957        break;
1958
1959      case ObjectLiteral::Property::SETTER:
1960        PushOperand(Smi::FromInt(DONT_ENUM));
1961        CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked);
1962        break;
1963
1964      default:
1965        UNREACHABLE();
1966    }
1967  }
1968}
1969
1970
1971void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
1972  PopOperand(rdx);
1973  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
1974  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
1975  CallIC(code, expr->BinaryOperationFeedbackId());
1976  patch_site.EmitPatchInfo();
1977  context()->Plug(rax);
1978}
1979
1980
1981void FullCodeGenerator::EmitAssignment(Expression* expr,
1982                                       FeedbackVectorSlot slot) {
1983  DCHECK(expr->IsValidReferenceExpressionOrThis());
1984
1985  Property* prop = expr->AsProperty();
1986  LhsKind assign_type = Property::GetAssignType(prop);
1987
1988  switch (assign_type) {
1989    case VARIABLE: {
1990      Variable* var = expr->AsVariableProxy()->var();
1991      EffectContext context(this);
1992      EmitVariableAssignment(var, Token::ASSIGN, slot);
1993      break;
1994    }
1995    case NAMED_PROPERTY: {
1996      PushOperand(rax);  // Preserve value.
1997      VisitForAccumulatorValue(prop->obj());
1998      __ Move(StoreDescriptor::ReceiverRegister(), rax);
1999      PopOperand(StoreDescriptor::ValueRegister());  // Restore value.
2000      __ Move(StoreDescriptor::NameRegister(),
2001              prop->key()->AsLiteral()->value());
2002      EmitLoadStoreICSlot(slot);
2003      CallStoreIC();
2004      break;
2005    }
2006    case NAMED_SUPER_PROPERTY: {
2007      PushOperand(rax);
2008      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
2009      VisitForAccumulatorValue(
2010          prop->obj()->AsSuperPropertyReference()->home_object());
2011      // stack: value, this; rax: home_object
2012      Register scratch = rcx;
2013      Register scratch2 = rdx;
2014      __ Move(scratch, result_register());               // home_object
2015      __ movp(rax, MemOperand(rsp, kPointerSize));       // value
2016      __ movp(scratch2, MemOperand(rsp, 0));             // this
2017      __ movp(MemOperand(rsp, kPointerSize), scratch2);  // this
2018      __ movp(MemOperand(rsp, 0), scratch);              // home_object
2019      // stack: this, home_object; rax: value
2020      EmitNamedSuperPropertyStore(prop);
2021      break;
2022    }
2023    case KEYED_SUPER_PROPERTY: {
2024      PushOperand(rax);
2025      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
2026      VisitForStackValue(
2027          prop->obj()->AsSuperPropertyReference()->home_object());
2028      VisitForAccumulatorValue(prop->key());
2029      Register scratch = rcx;
2030      Register scratch2 = rdx;
2031      __ movp(scratch2, MemOperand(rsp, 2 * kPointerSize));  // value
2032      // stack: value, this, home_object; rax: key, rdx: value
2033      __ movp(scratch, MemOperand(rsp, kPointerSize));  // this
2034      __ movp(MemOperand(rsp, 2 * kPointerSize), scratch);
2035      __ movp(scratch, MemOperand(rsp, 0));  // home_object
2036      __ movp(MemOperand(rsp, kPointerSize), scratch);
2037      __ movp(MemOperand(rsp, 0), rax);
2038      __ Move(rax, scratch2);
2039      // stack: this, home_object, key; rax: value.
2040      EmitKeyedSuperPropertyStore(prop);
2041      break;
2042    }
2043    case KEYED_PROPERTY: {
2044      PushOperand(rax);  // Preserve value.
2045      VisitForStackValue(prop->obj());
2046      VisitForAccumulatorValue(prop->key());
2047      __ Move(StoreDescriptor::NameRegister(), rax);
2048      PopOperand(StoreDescriptor::ReceiverRegister());
2049      PopOperand(StoreDescriptor::ValueRegister());  // Restore value.
2050      EmitLoadStoreICSlot(slot);
2051      Handle<Code> ic =
2052          CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
2053      CallIC(ic);
2054      break;
2055    }
2056  }
2057  context()->Plug(rax);
2058}
2059
2060
2061void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2062    Variable* var, MemOperand location) {
2063  __ movp(location, rax);
2064  if (var->IsContextSlot()) {
2065    __ movp(rdx, rax);
2066    __ RecordWriteContextSlot(
2067        rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
2068  }
2069}
2070
2071
2072void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
2073                                               FeedbackVectorSlot slot) {
2074  if (var->IsUnallocated()) {
2075    // Global var, const, or let.
2076    __ Move(StoreDescriptor::NameRegister(), var->name());
2077    __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
2078    EmitLoadStoreICSlot(slot);
2079    CallStoreIC();
2080
2081  } else if (var->mode() == LET && op != Token::INIT) {
2082    // Non-initializing assignment to let variable needs a write barrier.
2083    DCHECK(!var->IsLookupSlot());
2084    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2085    Label assign;
2086    MemOperand location = VarOperand(var, rcx);
2087    __ movp(rdx, location);
2088    __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2089    __ j(not_equal, &assign, Label::kNear);
2090    __ Push(var->name());
2091    __ CallRuntime(Runtime::kThrowReferenceError);
2092    __ bind(&assign);
2093    EmitStoreToStackLocalOrContextSlot(var, location);
2094
2095  } else if (var->mode() == CONST && op != Token::INIT) {
2096    // Assignment to const variable needs a write barrier.
2097    DCHECK(!var->IsLookupSlot());
2098    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2099    Label const_error;
2100    MemOperand location = VarOperand(var, rcx);
2101    __ movp(rdx, location);
2102    __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2103    __ j(not_equal, &const_error, Label::kNear);
2104    __ Push(var->name());
2105    __ CallRuntime(Runtime::kThrowReferenceError);
2106    __ bind(&const_error);
2107    __ CallRuntime(Runtime::kThrowConstAssignError);
2108
2109  } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) {
2110    // Initializing assignment to const {this} needs a write barrier.
2111    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2112    Label uninitialized_this;
2113    MemOperand location = VarOperand(var, rcx);
2114    __ movp(rdx, location);
2115    __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2116    __ j(equal, &uninitialized_this);
2117    __ Push(var->name());
2118    __ CallRuntime(Runtime::kThrowReferenceError);
2119    __ bind(&uninitialized_this);
2120    EmitStoreToStackLocalOrContextSlot(var, location);
2121
2122  } else if (!var->is_const_mode() || op == Token::INIT) {
2123    if (var->IsLookupSlot()) {
2124      // Assignment to var.
2125      __ Push(var->name());
2126      __ Push(rax);
2127      __ CallRuntime(is_strict(language_mode())
2128                         ? Runtime::kStoreLookupSlot_Strict
2129                         : Runtime::kStoreLookupSlot_Sloppy);
2130    } else {
2131      // Assignment to var or initializing assignment to let/const in harmony
2132      // mode.
2133      DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2134      MemOperand location = VarOperand(var, rcx);
2135      if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) {
2136        // Check for an uninitialized let binding.
2137        __ movp(rdx, location);
2138        __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2139        __ Check(equal, kLetBindingReInitialization);
2140      }
2141      EmitStoreToStackLocalOrContextSlot(var, location);
2142    }
2143
2144  } else {
2145    DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT);
2146    if (is_strict(language_mode())) {
2147      __ CallRuntime(Runtime::kThrowConstAssignError);
2148    }
2149    // Silently ignore store in sloppy mode.
2150  }
2151}
2152
2153
2154void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2155  // Assignment to a property, using a named store IC.
2156  Property* prop = expr->target()->AsProperty();
2157  DCHECK(prop != NULL);
2158  DCHECK(prop->key()->IsLiteral());
2159
2160  __ Move(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value());
2161  PopOperand(StoreDescriptor::ReceiverRegister());
2162  EmitLoadStoreICSlot(expr->AssignmentSlot());
2163  CallStoreIC();
2164
2165  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2166  context()->Plug(rax);
2167}
2168
2169
2170void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
2171  // Assignment to named property of super.
2172  // rax : value
2173  // stack : receiver ('this'), home_object
2174  DCHECK(prop != NULL);
2175  Literal* key = prop->key()->AsLiteral();
2176  DCHECK(key != NULL);
2177
2178  PushOperand(key->value());
2179  PushOperand(rax);
2180  CallRuntimeWithOperands(is_strict(language_mode())
2181                              ? Runtime::kStoreToSuper_Strict
2182                              : Runtime::kStoreToSuper_Sloppy);
2183}
2184
2185
2186void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
2187  // Assignment to named property of super.
2188  // rax : value
2189  // stack : receiver ('this'), home_object, key
2190  DCHECK(prop != NULL);
2191
2192  PushOperand(rax);
2193  CallRuntimeWithOperands(is_strict(language_mode())
2194                              ? Runtime::kStoreKeyedToSuper_Strict
2195                              : Runtime::kStoreKeyedToSuper_Sloppy);
2196}
2197
2198
2199void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2200  // Assignment to a property, using a keyed store IC.
2201  PopOperand(StoreDescriptor::NameRegister());  // Key.
2202  PopOperand(StoreDescriptor::ReceiverRegister());
2203  DCHECK(StoreDescriptor::ValueRegister().is(rax));
2204  Handle<Code> ic =
2205      CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
2206  EmitLoadStoreICSlot(expr->AssignmentSlot());
2207  CallIC(ic);
2208
2209  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2210  context()->Plug(rax);
2211}
2212
2213
2214void FullCodeGenerator::CallIC(Handle<Code> code,
2215                               TypeFeedbackId ast_id) {
2216  ic_total_count_++;
2217  __ call(code, RelocInfo::CODE_TARGET, ast_id);
2218}
2219
2220
2221// Code common for calls using the IC.
2222void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
2223  Expression* callee = expr->expression();
2224
2225  // Get the target function.
2226  ConvertReceiverMode convert_mode;
2227  if (callee->IsVariableProxy()) {
2228    { StackValueContext context(this);
2229      EmitVariableLoad(callee->AsVariableProxy());
2230      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
2231    }
2232    // Push undefined as receiver. This is patched in the Call builtin if it
2233    // is a sloppy mode method.
2234    PushOperand(isolate()->factory()->undefined_value());
2235    convert_mode = ConvertReceiverMode::kNullOrUndefined;
2236  } else {
2237    // Load the function from the receiver.
2238    DCHECK(callee->IsProperty());
2239    DCHECK(!callee->AsProperty()->IsSuperAccess());
2240    __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
2241    EmitNamedPropertyLoad(callee->AsProperty());
2242    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
2243                           BailoutState::TOS_REGISTER);
2244    // Push the target function under the receiver.
2245    PushOperand(Operand(rsp, 0));
2246    __ movp(Operand(rsp, kPointerSize), rax);
2247    convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
2248  }
2249
2250  EmitCall(expr, convert_mode);
2251}
2252
2253
2254void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
2255  Expression* callee = expr->expression();
2256  DCHECK(callee->IsProperty());
2257  Property* prop = callee->AsProperty();
2258  DCHECK(prop->IsSuperAccess());
2259  SetExpressionPosition(prop);
2260
2261  Literal* key = prop->key()->AsLiteral();
2262  DCHECK(!key->value()->IsSmi());
2263  // Load the function from the receiver.
2264  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
2265  VisitForStackValue(super_ref->home_object());
2266  VisitForAccumulatorValue(super_ref->this_var());
2267  PushOperand(rax);
2268  PushOperand(rax);
2269  PushOperand(Operand(rsp, kPointerSize * 2));
2270  PushOperand(key->value());
2271
2272  // Stack here:
2273  //  - home_object
2274  //  - this (receiver)
2275  //  - this (receiver) <-- LoadFromSuper will pop here and below.
2276  //  - home_object
2277  //  - key
2278  CallRuntimeWithOperands(Runtime::kLoadFromSuper);
2279  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
2280
2281  // Replace home_object with target function.
2282  __ movp(Operand(rsp, kPointerSize), rax);
2283
2284  // Stack here:
2285  // - target function
2286  // - this (receiver)
2287  EmitCall(expr);
2288}
2289
2290
2291// Common code for calls using the IC.
2292void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2293                                                Expression* key) {
2294  // Load the key.
2295  VisitForAccumulatorValue(key);
2296
2297  Expression* callee = expr->expression();
2298
2299  // Load the function from the receiver.
2300  DCHECK(callee->IsProperty());
2301  __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
2302  __ Move(LoadDescriptor::NameRegister(), rax);
2303  EmitKeyedPropertyLoad(callee->AsProperty());
2304  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
2305                         BailoutState::TOS_REGISTER);
2306
2307  // Push the target function under the receiver.
2308  PushOperand(Operand(rsp, 0));
2309  __ movp(Operand(rsp, kPointerSize), rax);
2310
2311  EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined);
2312}
2313
2314
2315void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
2316  Expression* callee = expr->expression();
2317  DCHECK(callee->IsProperty());
2318  Property* prop = callee->AsProperty();
2319  DCHECK(prop->IsSuperAccess());
2320
2321  SetExpressionPosition(prop);
2322  // Load the function from the receiver.
2323  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
2324  VisitForStackValue(super_ref->home_object());
2325  VisitForAccumulatorValue(super_ref->this_var());
2326  PushOperand(rax);
2327  PushOperand(rax);
2328  PushOperand(Operand(rsp, kPointerSize * 2));
2329  VisitForStackValue(prop->key());
2330
2331  // Stack here:
2332  //  - home_object
2333  //  - this (receiver)
2334  //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
2335  //  - home_object
2336  //  - key
2337  CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
2338  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
2339
2340  // Replace home_object with target function.
2341  __ movp(Operand(rsp, kPointerSize), rax);
2342
2343  // Stack here:
2344  // - target function
2345  // - this (receiver)
2346  EmitCall(expr);
2347}
2348
2349
2350void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
2351  // Load the arguments.
2352  ZoneList<Expression*>* args = expr->arguments();
2353  int arg_count = args->length();
2354  for (int i = 0; i < arg_count; i++) {
2355    VisitForStackValue(args->at(i));
2356  }
2357
2358  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
2359  SetCallPosition(expr, expr->tail_call_mode());
2360  if (expr->tail_call_mode() == TailCallMode::kAllow) {
2361    if (FLAG_trace) {
2362      __ CallRuntime(Runtime::kTraceTailCall);
2363    }
2364    // Update profiling counters before the tail call since we will
2365    // not return to this function.
2366    EmitProfilingCounterHandlingForReturnSequence(true);
2367  }
2368  Handle<Code> ic =
2369      CodeFactory::CallIC(isolate(), arg_count, mode, expr->tail_call_mode())
2370          .code();
2371  __ Move(rdx, SmiFromSlot(expr->CallFeedbackICSlot()));
2372  __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2373  // Don't assign a type feedback id to the IC, since type feedback is provided
2374  // by the vector above.
2375  CallIC(ic);
2376  OperandStackDepthDecrement(arg_count + 1);
2377
2378  RecordJSReturnSite(expr);
2379  RestoreContext();
2380  // Discard the function left on TOS.
2381  context()->DropAndPlug(1, rax);
2382}
2383
2384void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
2385  int arg_count = expr->arguments()->length();
2386  // Push copy of the first argument or undefined if it doesn't exist.
2387  if (arg_count > 0) {
2388    __ Push(Operand(rsp, arg_count * kPointerSize));
2389  } else {
2390    __ PushRoot(Heap::kUndefinedValueRootIndex);
2391  }
2392
2393  // Push the enclosing function.
2394  __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
2395
2396  // Push the language mode.
2397  __ Push(Smi::FromInt(language_mode()));
2398
2399  // Push the start position of the scope the calls resides in.
2400  __ Push(Smi::FromInt(scope()->start_position()));
2401
2402  // Push the source position of the eval call.
2403  __ Push(Smi::FromInt(expr->position()));
2404
2405  // Do the runtime call.
2406  __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
2407}
2408
2409
2410// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
2411void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
2412  VariableProxy* callee = expr->expression()->AsVariableProxy();
2413  if (callee->var()->IsLookupSlot()) {
2414    Label slow, done;
2415    SetExpressionPosition(callee);
2416    // Generate code for loading from variables potentially shadowed by
2417    // eval-introduced variables.
2418    EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
2419    __ bind(&slow);
2420    // Call the runtime to find the function to call (returned in rax) and
2421    // the object holding it (returned in rdx).
2422    __ Push(callee->name());
2423    __ CallRuntime(Runtime::kLoadLookupSlotForCall);
2424    PushOperand(rax);  // Function.
2425    PushOperand(rdx);  // Receiver.
2426    PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
2427
2428    // If fast case code has been generated, emit code to push the function
2429    // and receiver and have the slow path jump around this code.
2430    if (done.is_linked()) {
2431      Label call;
2432      __ jmp(&call, Label::kNear);
2433      __ bind(&done);
2434      // Push function.
2435      __ Push(rax);
2436      // Pass undefined as the receiver, which is the WithBaseObject of a
2437      // non-object environment record.  If the callee is sloppy, it will patch
2438      // it up to be the global receiver.
2439      __ PushRoot(Heap::kUndefinedValueRootIndex);
2440      __ bind(&call);
2441    }
2442  } else {
2443    VisitForStackValue(callee);
2444    // refEnv.WithBaseObject()
2445    OperandStackDepthIncrement(1);
2446    __ PushRoot(Heap::kUndefinedValueRootIndex);
2447  }
2448}
2449
2450
2451void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
2452  // In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
2453  // to resolve the function we need to call.  Then we call the resolved
2454  // function using the given arguments.
2455  ZoneList<Expression*>* args = expr->arguments();
2456  int arg_count = args->length();
2457  PushCalleeAndWithBaseObject(expr);
2458
2459  // Push the arguments.
2460  for (int i = 0; i < arg_count; i++) {
2461    VisitForStackValue(args->at(i));
2462  }
2463
2464  // Push a copy of the function (found below the arguments) and resolve
2465  // eval.
2466  __ Push(Operand(rsp, (arg_count + 1) * kPointerSize));
2467  EmitResolvePossiblyDirectEval(expr);
2468
2469  // Touch up the callee.
2470  __ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
2471
2472  PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
2473
2474  SetCallPosition(expr);
2475  __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2476  __ Set(rax, arg_count);
2477  __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kAny,
2478                                      expr->tail_call_mode()),
2479          RelocInfo::CODE_TARGET);
2480  OperandStackDepthDecrement(arg_count + 1);
2481  RecordJSReturnSite(expr);
2482  RestoreContext();
2483  context()->DropAndPlug(1, rax);
2484}
2485
2486
2487void FullCodeGenerator::VisitCallNew(CallNew* expr) {
2488  Comment cmnt(masm_, "[ CallNew");
2489  // According to ECMA-262, section 11.2.2, page 44, the function
2490  // expression in new calls must be evaluated before the
2491  // arguments.
2492
2493  // Push constructor on the stack.  If it's not a function it's used as
2494  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
2495  // ignored.
2496  DCHECK(!expr->expression()->IsSuperPropertyReference());
2497  VisitForStackValue(expr->expression());
2498
2499  // Push the arguments ("left-to-right") on the stack.
2500  ZoneList<Expression*>* args = expr->arguments();
2501  int arg_count = args->length();
2502  for (int i = 0; i < arg_count; i++) {
2503    VisitForStackValue(args->at(i));
2504  }
2505
2506  // Call the construct call builtin that handles allocation and
2507  // constructor invocation.
2508  SetConstructCallPosition(expr);
2509
2510  // Load function and argument count into rdi and rax.
2511  __ Set(rax, arg_count);
2512  __ movp(rdi, Operand(rsp, arg_count * kPointerSize));
2513
2514  // Record call targets in unoptimized code, but not in the snapshot.
2515  __ EmitLoadTypeFeedbackVector(rbx);
2516  __ Move(rdx, SmiFromSlot(expr->CallNewFeedbackSlot()));
2517
2518  CallConstructStub stub(isolate());
2519  __ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
2520  OperandStackDepthDecrement(arg_count + 1);
2521  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
2522  RestoreContext();
2523  context()->Plug(rax);
2524}
2525
2526
2527void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
2528  SuperCallReference* super_call_ref =
2529      expr->expression()->AsSuperCallReference();
2530  DCHECK_NOT_NULL(super_call_ref);
2531
2532  // Push the super constructor target on the stack (may be null,
2533  // but the Construct builtin can deal with that properly).
2534  VisitForAccumulatorValue(super_call_ref->this_function_var());
2535  __ AssertFunction(result_register());
2536  __ movp(result_register(),
2537          FieldOperand(result_register(), HeapObject::kMapOffset));
2538  PushOperand(FieldOperand(result_register(), Map::kPrototypeOffset));
2539
2540  // Push the arguments ("left-to-right") on the stack.
2541  ZoneList<Expression*>* args = expr->arguments();
2542  int arg_count = args->length();
2543  for (int i = 0; i < arg_count; i++) {
2544    VisitForStackValue(args->at(i));
2545  }
2546
2547  // Call the construct call builtin that handles allocation and
2548  // constructor invocation.
2549  SetConstructCallPosition(expr);
2550
2551  // Load new target into rdx.
2552  VisitForAccumulatorValue(super_call_ref->new_target_var());
2553  __ movp(rdx, result_register());
2554
2555  // Load function and argument count into rdi and rax.
2556  __ Set(rax, arg_count);
2557  __ movp(rdi, Operand(rsp, arg_count * kPointerSize));
2558
2559  __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
2560  OperandStackDepthDecrement(arg_count + 1);
2561
2562  RecordJSReturnSite(expr);
2563  RestoreContext();
2564  context()->Plug(rax);
2565}
2566
2567
2568void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2569  ZoneList<Expression*>* args = expr->arguments();
2570  DCHECK(args->length() == 1);
2571
2572  VisitForAccumulatorValue(args->at(0));
2573
2574  Label materialize_true, materialize_false;
2575  Label* if_true = NULL;
2576  Label* if_false = NULL;
2577  Label* fall_through = NULL;
2578  context()->PrepareTest(&materialize_true, &materialize_false,
2579                         &if_true, &if_false, &fall_through);
2580
2581  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2582  __ JumpIfSmi(rax, if_true);
2583  __ jmp(if_false);
2584
2585  context()->Plug(if_true, if_false);
2586}
2587
2588
2589void FullCodeGenerator::EmitIsJSReceiver(CallRuntime* expr) {
2590  ZoneList<Expression*>* args = expr->arguments();
2591  DCHECK(args->length() == 1);
2592
2593  VisitForAccumulatorValue(args->at(0));
2594
2595  Label materialize_true, materialize_false;
2596  Label* if_true = NULL;
2597  Label* if_false = NULL;
2598  Label* fall_through = NULL;
2599  context()->PrepareTest(&materialize_true, &materialize_false,
2600                         &if_true, &if_false, &fall_through);
2601
2602  __ JumpIfSmi(rax, if_false);
2603  __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rbx);
2604  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2605  Split(above_equal, if_true, if_false, fall_through);
2606
2607  context()->Plug(if_true, if_false);
2608}
2609
2610
2611void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
2612  ZoneList<Expression*>* args = expr->arguments();
2613  DCHECK(args->length() == 1);
2614
2615  VisitForAccumulatorValue(args->at(0));
2616
2617  Label materialize_true, materialize_false;
2618  Label* if_true = NULL;
2619  Label* if_false = NULL;
2620  Label* fall_through = NULL;
2621  context()->PrepareTest(&materialize_true, &materialize_false,
2622                         &if_true, &if_false, &fall_through);
2623
2624  __ JumpIfSmi(rax, if_false);
2625  __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
2626  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2627  Split(equal, if_true, if_false, fall_through);
2628
2629  context()->Plug(if_true, if_false);
2630}
2631
2632
2633void FullCodeGenerator::EmitIsTypedArray(CallRuntime* expr) {
2634  ZoneList<Expression*>* args = expr->arguments();
2635  DCHECK(args->length() == 1);
2636
2637  VisitForAccumulatorValue(args->at(0));
2638
2639  Label materialize_true, materialize_false;
2640  Label* if_true = NULL;
2641  Label* if_false = NULL;
2642  Label* fall_through = NULL;
2643  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
2644                         &if_false, &fall_through);
2645
2646  __ JumpIfSmi(rax, if_false);
2647  __ CmpObjectType(rax, JS_TYPED_ARRAY_TYPE, rbx);
2648  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2649  Split(equal, if_true, if_false, fall_through);
2650
2651  context()->Plug(if_true, if_false);
2652}
2653
2654
2655void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
2656  ZoneList<Expression*>* args = expr->arguments();
2657  DCHECK(args->length() == 1);
2658
2659  VisitForAccumulatorValue(args->at(0));
2660
2661  Label materialize_true, materialize_false;
2662  Label* if_true = NULL;
2663  Label* if_false = NULL;
2664  Label* fall_through = NULL;
2665  context()->PrepareTest(&materialize_true, &materialize_false,
2666                         &if_true, &if_false, &fall_through);
2667
2668  __ JumpIfSmi(rax, if_false);
2669  __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
2670  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2671  Split(equal, if_true, if_false, fall_through);
2672
2673  context()->Plug(if_true, if_false);
2674}
2675
2676
2677void FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) {
2678  ZoneList<Expression*>* args = expr->arguments();
2679  DCHECK(args->length() == 1);
2680
2681  VisitForAccumulatorValue(args->at(0));
2682
2683  Label materialize_true, materialize_false;
2684  Label* if_true = NULL;
2685  Label* if_false = NULL;
2686  Label* fall_through = NULL;
2687  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
2688                         &if_false, &fall_through);
2689
2690
2691  __ JumpIfSmi(rax, if_false);
2692  __ CmpObjectType(rax, JS_PROXY_TYPE, rbx);
2693  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2694  Split(equal, if_true, if_false, fall_through);
2695
2696  context()->Plug(if_true, if_false);
2697}
2698
2699
2700void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
2701  ZoneList<Expression*>* args = expr->arguments();
2702  DCHECK(args->length() == 1);
2703  Label done, null, function, non_function_constructor;
2704
2705  VisitForAccumulatorValue(args->at(0));
2706
2707  // If the object is not a JSReceiver, we return null.
2708  __ JumpIfSmi(rax, &null, Label::kNear);
2709  STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
2710  __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rax);
2711  __ j(below, &null, Label::kNear);
2712
2713  // Return 'Function' for JSFunction and JSBoundFunction objects.
2714  __ CmpInstanceType(rax, FIRST_FUNCTION_TYPE);
2715  STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
2716  __ j(above_equal, &function, Label::kNear);
2717
2718  // Check if the constructor in the map is a JS function.
2719  __ GetMapConstructor(rax, rax, rbx);
2720  __ CmpInstanceType(rbx, JS_FUNCTION_TYPE);
2721  __ j(not_equal, &non_function_constructor, Label::kNear);
2722
2723  // rax now contains the constructor function. Grab the
2724  // instance class name from there.
2725  __ movp(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
2726  __ movp(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset));
2727  __ jmp(&done, Label::kNear);
2728
2729  // Non-JS objects have class null.
2730  __ bind(&null);
2731  __ LoadRoot(rax, Heap::kNullValueRootIndex);
2732  __ jmp(&done, Label::kNear);
2733
2734  // Functions have class 'Function'.
2735  __ bind(&function);
2736  __ LoadRoot(rax, Heap::kFunction_stringRootIndex);
2737  __ jmp(&done, Label::kNear);
2738
2739  // Objects with a non-function constructor have class 'Object'.
2740  __ bind(&non_function_constructor);
2741  __ LoadRoot(rax, Heap::kObject_stringRootIndex);
2742
2743  // All done.
2744  __ bind(&done);
2745
2746  context()->Plug(rax);
2747}
2748
2749
2750void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
2751  ZoneList<Expression*>* args = expr->arguments();
2752  DCHECK(args->length() == 1);
2753
2754  VisitForAccumulatorValue(args->at(0));  // Load the object.
2755
2756  Label done;
2757  // If the object is a smi return the object.
2758  __ JumpIfSmi(rax, &done);
2759  // If the object is not a value type, return the object.
2760  __ CmpObjectType(rax, JS_VALUE_TYPE, rbx);
2761  __ j(not_equal, &done);
2762  __ movp(rax, FieldOperand(rax, JSValue::kValueOffset));
2763
2764  __ bind(&done);
2765  context()->Plug(rax);
2766}
2767
2768
2769void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
2770  ZoneList<Expression*>* args = expr->arguments();
2771  DCHECK(args->length() == 1);
2772
2773  VisitForAccumulatorValue(args->at(0));
2774
2775  Label done;
2776  StringCharFromCodeGenerator generator(rax, rbx);
2777  generator.GenerateFast(masm_);
2778  __ jmp(&done);
2779
2780  NopRuntimeCallHelper call_helper;
2781  generator.GenerateSlow(masm_, call_helper);
2782
2783  __ bind(&done);
2784  context()->Plug(rbx);
2785}
2786
2787
2788void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
2789  ZoneList<Expression*>* args = expr->arguments();
2790  DCHECK(args->length() == 2);
2791
2792  VisitForStackValue(args->at(0));
2793  VisitForAccumulatorValue(args->at(1));
2794
2795  Register object = rbx;
2796  Register index = rax;
2797  Register result = rdx;
2798
2799  PopOperand(object);
2800
2801  Label need_conversion;
2802  Label index_out_of_range;
2803  Label done;
2804  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
2805                                      &need_conversion, &index_out_of_range);
2806  generator.GenerateFast(masm_);
2807  __ jmp(&done);
2808
2809  __ bind(&index_out_of_range);
2810  // When the index is out of range, the spec requires us to return
2811  // NaN.
2812  __ LoadRoot(result, Heap::kNanValueRootIndex);
2813  __ jmp(&done);
2814
2815  __ bind(&need_conversion);
2816  // Move the undefined value into the result register, which will
2817  // trigger conversion.
2818  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
2819  __ jmp(&done);
2820
2821  NopRuntimeCallHelper call_helper;
2822  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
2823
2824  __ bind(&done);
2825  context()->Plug(result);
2826}
2827
2828
2829void FullCodeGenerator::EmitCall(CallRuntime* expr) {
2830  ZoneList<Expression*>* args = expr->arguments();
2831  DCHECK_LE(2, args->length());
2832  // Push target, receiver and arguments onto the stack.
2833  for (Expression* const arg : *args) {
2834    VisitForStackValue(arg);
2835  }
2836  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
2837  // Move target to rdi.
2838  int const argc = args->length() - 2;
2839  __ movp(rdi, Operand(rsp, (argc + 1) * kPointerSize));
2840  // Call the target.
2841  __ Set(rax, argc);
2842  __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
2843  OperandStackDepthDecrement(argc + 1);
2844  RestoreContext();
2845  // Discard the function left on TOS.
2846  context()->DropAndPlug(1, rax);
2847}
2848
2849
2850void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
2851  ZoneList<Expression*>* args = expr->arguments();
2852  DCHECK(args->length() == 1);
2853
2854  VisitForAccumulatorValue(args->at(0));
2855
2856  Label materialize_true, materialize_false;
2857  Label* if_true = NULL;
2858  Label* if_false = NULL;
2859  Label* fall_through = NULL;
2860  context()->PrepareTest(&materialize_true, &materialize_false,
2861                         &if_true, &if_false, &fall_through);
2862
2863  __ testl(FieldOperand(rax, String::kHashFieldOffset),
2864           Immediate(String::kContainsCachedArrayIndexMask));
2865  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2866  __ j(zero, if_true);
2867  __ jmp(if_false);
2868
2869  context()->Plug(if_true, if_false);
2870}
2871
2872
2873void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
2874  ZoneList<Expression*>* args = expr->arguments();
2875  DCHECK(args->length() == 1);
2876  VisitForAccumulatorValue(args->at(0));
2877
2878  __ AssertString(rax);
2879
2880  __ movl(rax, FieldOperand(rax, String::kHashFieldOffset));
2881  DCHECK(String::kHashShift >= kSmiTagSize);
2882  __ IndexFromHash(rax, rax);
2883
2884  context()->Plug(rax);
2885}
2886
2887
2888void FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) {
2889  ZoneList<Expression*>* args = expr->arguments();
2890  DCHECK_EQ(1, args->length());
2891  VisitForAccumulatorValue(args->at(0));
2892  __ AssertFunction(rax);
2893  __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
2894  __ movp(rax, FieldOperand(rax, Map::kPrototypeOffset));
2895  context()->Plug(rax);
2896}
2897
2898void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
2899  DCHECK(expr->arguments()->length() == 0);
2900  ExternalReference debug_is_active =
2901      ExternalReference::debug_is_active_address(isolate());
2902  __ Move(kScratchRegister, debug_is_active);
2903  __ movzxbp(rax, Operand(kScratchRegister, 0));
2904  __ Integer32ToSmi(rax, rax);
2905  context()->Plug(rax);
2906}
2907
2908
2909void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
2910  ZoneList<Expression*>* args = expr->arguments();
2911  DCHECK_EQ(2, args->length());
2912  VisitForStackValue(args->at(0));
2913  VisitForStackValue(args->at(1));
2914
2915  Label runtime, done;
2916
2917  __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &runtime,
2918              NO_ALLOCATION_FLAGS);
2919  __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, rbx);
2920  __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx);
2921  __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex);
2922  __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx);
2923  __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx);
2924  __ Pop(FieldOperand(rax, JSIteratorResult::kDoneOffset));
2925  __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset));
2926  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
2927  __ jmp(&done, Label::kNear);
2928
2929  __ bind(&runtime);
2930  CallRuntimeWithOperands(Runtime::kCreateIterResultObject);
2931
2932  __ bind(&done);
2933  context()->Plug(rax);
2934}
2935
2936
2937void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
2938  // Push function.
2939  __ LoadNativeContextSlot(expr->context_index(), rax);
2940  PushOperand(rax);
2941
2942  // Push undefined as receiver.
2943  OperandStackDepthIncrement(1);
2944  __ PushRoot(Heap::kUndefinedValueRootIndex);
2945}
2946
2947
2948void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
2949  ZoneList<Expression*>* args = expr->arguments();
2950  int arg_count = args->length();
2951
2952  SetCallPosition(expr);
2953  __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2954  __ Set(rax, arg_count);
2955  __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
2956          RelocInfo::CODE_TARGET);
2957  OperandStackDepthDecrement(arg_count + 1);
2958  RestoreContext();
2959}
2960
2961
2962void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2963  switch (expr->op()) {
2964    case Token::DELETE: {
2965      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2966      Property* property = expr->expression()->AsProperty();
2967      VariableProxy* proxy = expr->expression()->AsVariableProxy();
2968
2969      if (property != NULL) {
2970        VisitForStackValue(property->obj());
2971        VisitForStackValue(property->key());
2972        CallRuntimeWithOperands(is_strict(language_mode())
2973                                    ? Runtime::kDeleteProperty_Strict
2974                                    : Runtime::kDeleteProperty_Sloppy);
2975        context()->Plug(rax);
2976      } else if (proxy != NULL) {
2977        Variable* var = proxy->var();
2978        // Delete of an unqualified identifier is disallowed in strict mode but
2979        // "delete this" is allowed.
2980        bool is_this = var->HasThisName(isolate());
2981        DCHECK(is_sloppy(language_mode()) || is_this);
2982        if (var->IsUnallocatedOrGlobalSlot()) {
2983          __ movp(rax, NativeContextOperand());
2984          __ Push(ContextOperand(rax, Context::EXTENSION_INDEX));
2985          __ Push(var->name());
2986          __ CallRuntime(Runtime::kDeleteProperty_Sloppy);
2987          context()->Plug(rax);
2988        } else if (var->IsStackAllocated() || var->IsContextSlot()) {
2989          // Result of deleting non-global variables is false.  'this' is
2990          // not really a variable, though we implement it as one.  The
2991          // subexpression does not have side effects.
2992          context()->Plug(is_this);
2993        } else {
2994          // Non-global variable.  Call the runtime to try to delete from the
2995          // context where the variable was introduced.
2996          __ Push(var->name());
2997          __ CallRuntime(Runtime::kDeleteLookupSlot);
2998          context()->Plug(rax);
2999        }
3000      } else {
3001        // Result of deleting non-property, non-variable reference is true.
3002        // The subexpression may have side effects.
3003        VisitForEffect(expr->expression());
3004        context()->Plug(true);
3005      }
3006      break;
3007    }
3008
3009    case Token::VOID: {
3010      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
3011      VisitForEffect(expr->expression());
3012      context()->Plug(Heap::kUndefinedValueRootIndex);
3013      break;
3014    }
3015
3016    case Token::NOT: {
3017      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
3018      if (context()->IsEffect()) {
3019        // Unary NOT has no side effects so it's only necessary to visit the
3020        // subexpression.  Match the optimizing compiler by not branching.
3021        VisitForEffect(expr->expression());
3022      } else if (context()->IsTest()) {
3023        const TestContext* test = TestContext::cast(context());
3024        // The labels are swapped for the recursive call.
3025        VisitForControl(expr->expression(),
3026                        test->false_label(),
3027                        test->true_label(),
3028                        test->fall_through());
3029        context()->Plug(test->true_label(), test->false_label());
3030      } else {
3031        // We handle value contexts explicitly rather than simply visiting
3032        // for control and plugging the control flow into the context,
3033        // because we need to prepare a pair of extra administrative AST ids
3034        // for the optimizing compiler.
3035        DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
3036        Label materialize_true, materialize_false, done;
3037        VisitForControl(expr->expression(),
3038                        &materialize_false,
3039                        &materialize_true,
3040                        &materialize_true);
3041        if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
3042        __ bind(&materialize_true);
3043        PrepareForBailoutForId(expr->MaterializeTrueId(),
3044                               BailoutState::NO_REGISTERS);
3045        if (context()->IsAccumulatorValue()) {
3046          __ LoadRoot(rax, Heap::kTrueValueRootIndex);
3047        } else {
3048          __ PushRoot(Heap::kTrueValueRootIndex);
3049        }
3050        __ jmp(&done, Label::kNear);
3051        __ bind(&materialize_false);
3052        PrepareForBailoutForId(expr->MaterializeFalseId(),
3053                               BailoutState::NO_REGISTERS);
3054        if (context()->IsAccumulatorValue()) {
3055          __ LoadRoot(rax, Heap::kFalseValueRootIndex);
3056        } else {
3057          __ PushRoot(Heap::kFalseValueRootIndex);
3058        }
3059        __ bind(&done);
3060      }
3061      break;
3062    }
3063
3064    case Token::TYPEOF: {
3065      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
3066      {
3067        AccumulatorValueContext context(this);
3068        VisitForTypeofValue(expr->expression());
3069      }
3070      __ movp(rbx, rax);
3071      TypeofStub typeof_stub(isolate());
3072      __ CallStub(&typeof_stub);
3073      context()->Plug(rax);
3074      break;
3075    }
3076
3077    default:
3078      UNREACHABLE();
3079  }
3080}
3081
3082
3083void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3084  DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
3085
3086  Comment cmnt(masm_, "[ CountOperation");
3087
3088  Property* prop = expr->expression()->AsProperty();
3089  LhsKind assign_type = Property::GetAssignType(prop);
3090
3091  // Evaluate expression and get value.
3092  if (assign_type == VARIABLE) {
3093    DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
3094    AccumulatorValueContext context(this);
3095    EmitVariableLoad(expr->expression()->AsVariableProxy());
3096  } else {
3097    // Reserve space for result of postfix operation.
3098    if (expr->is_postfix() && !context()->IsEffect()) {
3099      PushOperand(Smi::FromInt(0));
3100    }
3101    switch (assign_type) {
3102      case NAMED_PROPERTY: {
3103        VisitForStackValue(prop->obj());
3104        __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
3105        EmitNamedPropertyLoad(prop);
3106        break;
3107      }
3108
3109      case NAMED_SUPER_PROPERTY: {
3110        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
3111        VisitForAccumulatorValue(
3112            prop->obj()->AsSuperPropertyReference()->home_object());
3113        PushOperand(result_register());
3114        PushOperand(MemOperand(rsp, kPointerSize));
3115        PushOperand(result_register());
3116        EmitNamedSuperPropertyLoad(prop);
3117        break;
3118      }
3119
3120      case KEYED_SUPER_PROPERTY: {
3121        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
3122        VisitForStackValue(
3123            prop->obj()->AsSuperPropertyReference()->home_object());
3124        VisitForAccumulatorValue(prop->key());
3125        PushOperand(result_register());
3126        PushOperand(MemOperand(rsp, 2 * kPointerSize));
3127        PushOperand(MemOperand(rsp, 2 * kPointerSize));
3128        PushOperand(result_register());
3129        EmitKeyedSuperPropertyLoad(prop);
3130        break;
3131      }
3132
3133      case KEYED_PROPERTY: {
3134        VisitForStackValue(prop->obj());
3135        VisitForStackValue(prop->key());
3136        // Leave receiver on stack
3137        __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize));
3138        // Copy of key, needed for later store.
3139        __ movp(LoadDescriptor::NameRegister(), Operand(rsp, 0));
3140        EmitKeyedPropertyLoad(prop);
3141        break;
3142      }
3143
3144      case VARIABLE:
3145        UNREACHABLE();
3146    }
3147  }
3148
3149  // We need a second deoptimization point after loading the value
3150  // in case evaluating the property load my have a side effect.
3151  if (assign_type == VARIABLE) {
3152    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
3153  } else {
3154    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
3155  }
3156
3157  // Inline smi case if we are in a loop.
3158  Label done, stub_call;
3159  JumpPatchSite patch_site(masm_);
3160  if (ShouldInlineSmiCase(expr->op())) {
3161    Label slow;
3162    patch_site.EmitJumpIfNotSmi(rax, &slow, Label::kNear);
3163
3164    // Save result for postfix expressions.
3165    if (expr->is_postfix()) {
3166      if (!context()->IsEffect()) {
3167        // Save the result on the stack. If we have a named or keyed property
3168        // we store the result under the receiver that is currently on top
3169        // of the stack.
3170        switch (assign_type) {
3171          case VARIABLE:
3172            __ Push(rax);
3173            break;
3174          case NAMED_PROPERTY:
3175            __ movp(Operand(rsp, kPointerSize), rax);
3176            break;
3177          case NAMED_SUPER_PROPERTY:
3178            __ movp(Operand(rsp, 2 * kPointerSize), rax);
3179            break;
3180          case KEYED_PROPERTY:
3181            __ movp(Operand(rsp, 2 * kPointerSize), rax);
3182            break;
3183          case KEYED_SUPER_PROPERTY:
3184            __ movp(Operand(rsp, 3 * kPointerSize), rax);
3185            break;
3186        }
3187      }
3188    }
3189
3190    SmiOperationConstraints constraints =
3191        SmiOperationConstraint::kPreserveSourceRegister |
3192        SmiOperationConstraint::kBailoutOnNoOverflow;
3193    if (expr->op() == Token::INC) {
3194      __ SmiAddConstant(rax, rax, Smi::FromInt(1), constraints, &done,
3195                        Label::kNear);
3196    } else {
3197      __ SmiSubConstant(rax, rax, Smi::FromInt(1), constraints, &done,
3198                        Label::kNear);
3199    }
3200    __ jmp(&stub_call, Label::kNear);
3201    __ bind(&slow);
3202  }
3203
3204  // Convert old value into a number.
3205  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
3206  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
3207
3208  // Save result for postfix expressions.
3209  if (expr->is_postfix()) {
3210    if (!context()->IsEffect()) {
3211      // Save the result on the stack. If we have a named or keyed property
3212      // we store the result under the receiver that is currently on top
3213      // of the stack.
3214      switch (assign_type) {
3215        case VARIABLE:
3216          PushOperand(rax);
3217          break;
3218        case NAMED_PROPERTY:
3219          __ movp(Operand(rsp, kPointerSize), rax);
3220          break;
3221        case NAMED_SUPER_PROPERTY:
3222          __ movp(Operand(rsp, 2 * kPointerSize), rax);
3223          break;
3224        case KEYED_PROPERTY:
3225          __ movp(Operand(rsp, 2 * kPointerSize), rax);
3226          break;
3227        case KEYED_SUPER_PROPERTY:
3228          __ movp(Operand(rsp, 3 * kPointerSize), rax);
3229          break;
3230      }
3231    }
3232  }
3233
3234  SetExpressionPosition(expr);
3235
3236  // Call stub for +1/-1.
3237  __ bind(&stub_call);
3238  __ movp(rdx, rax);
3239  __ Move(rax, Smi::FromInt(1));
3240  Handle<Code> code =
3241      CodeFactory::BinaryOpIC(isolate(), expr->binary_op()).code();
3242  CallIC(code, expr->CountBinOpFeedbackId());
3243  patch_site.EmitPatchInfo();
3244  __ bind(&done);
3245
3246  // Store the value returned in rax.
3247  switch (assign_type) {
3248    case VARIABLE:
3249      if (expr->is_postfix()) {
3250        // Perform the assignment as if via '='.
3251        { EffectContext context(this);
3252          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3253                                 Token::ASSIGN, expr->CountSlot());
3254          PrepareForBailoutForId(expr->AssignmentId(),
3255                                 BailoutState::TOS_REGISTER);
3256          context.Plug(rax);
3257        }
3258        // For all contexts except kEffect: We have the result on
3259        // top of the stack.
3260        if (!context()->IsEffect()) {
3261          context()->PlugTOS();
3262        }
3263      } else {
3264        // Perform the assignment as if via '='.
3265        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3266                               Token::ASSIGN, expr->CountSlot());
3267        PrepareForBailoutForId(expr->AssignmentId(),
3268                               BailoutState::TOS_REGISTER);
3269        context()->Plug(rax);
3270      }
3271      break;
3272    case NAMED_PROPERTY: {
3273      __ Move(StoreDescriptor::NameRegister(),
3274              prop->key()->AsLiteral()->value());
3275      PopOperand(StoreDescriptor::ReceiverRegister());
3276      EmitLoadStoreICSlot(expr->CountSlot());
3277      CallStoreIC();
3278      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3279      if (expr->is_postfix()) {
3280        if (!context()->IsEffect()) {
3281          context()->PlugTOS();
3282        }
3283      } else {
3284        context()->Plug(rax);
3285      }
3286      break;
3287    }
3288    case NAMED_SUPER_PROPERTY: {
3289      EmitNamedSuperPropertyStore(prop);
3290      if (expr->is_postfix()) {
3291        if (!context()->IsEffect()) {
3292          context()->PlugTOS();
3293        }
3294      } else {
3295        context()->Plug(rax);
3296      }
3297      break;
3298    }
3299    case KEYED_SUPER_PROPERTY: {
3300      EmitKeyedSuperPropertyStore(prop);
3301      if (expr->is_postfix()) {
3302        if (!context()->IsEffect()) {
3303          context()->PlugTOS();
3304        }
3305      } else {
3306        context()->Plug(rax);
3307      }
3308      break;
3309    }
3310    case KEYED_PROPERTY: {
3311      PopOperand(StoreDescriptor::NameRegister());
3312      PopOperand(StoreDescriptor::ReceiverRegister());
3313      Handle<Code> ic =
3314          CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
3315      EmitLoadStoreICSlot(expr->CountSlot());
3316      CallIC(ic);
3317      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3318      if (expr->is_postfix()) {
3319        if (!context()->IsEffect()) {
3320          context()->PlugTOS();
3321        }
3322      } else {
3323        context()->Plug(rax);
3324      }
3325      break;
3326    }
3327  }
3328}
3329
3330
3331void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
3332                                                 Expression* sub_expr,
3333                                                 Handle<String> check) {
3334  Label materialize_true, materialize_false;
3335  Label* if_true = NULL;
3336  Label* if_false = NULL;
3337  Label* fall_through = NULL;
3338  context()->PrepareTest(&materialize_true, &materialize_false,
3339                         &if_true, &if_false, &fall_through);
3340
3341  { AccumulatorValueContext context(this);
3342    VisitForTypeofValue(sub_expr);
3343  }
3344  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3345
3346  Factory* factory = isolate()->factory();
3347  if (String::Equals(check, factory->number_string())) {
3348    __ JumpIfSmi(rax, if_true);
3349    __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
3350    __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
3351    Split(equal, if_true, if_false, fall_through);
3352  } else if (String::Equals(check, factory->string_string())) {
3353    __ JumpIfSmi(rax, if_false);
3354    __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
3355    Split(below, if_true, if_false, fall_through);
3356  } else if (String::Equals(check, factory->symbol_string())) {
3357    __ JumpIfSmi(rax, if_false);
3358    __ CmpObjectType(rax, SYMBOL_TYPE, rdx);
3359    Split(equal, if_true, if_false, fall_through);
3360  } else if (String::Equals(check, factory->boolean_string())) {
3361    __ CompareRoot(rax, Heap::kTrueValueRootIndex);
3362    __ j(equal, if_true);
3363    __ CompareRoot(rax, Heap::kFalseValueRootIndex);
3364    Split(equal, if_true, if_false, fall_through);
3365  } else if (String::Equals(check, factory->undefined_string())) {
3366    __ CompareRoot(rax, Heap::kNullValueRootIndex);
3367    __ j(equal, if_false);
3368    __ JumpIfSmi(rax, if_false);
3369    // Check for undetectable objects => true.
3370    __ movp(rdx, FieldOperand(rax, HeapObject::kMapOffset));
3371    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
3372             Immediate(1 << Map::kIsUndetectable));
3373    Split(not_zero, if_true, if_false, fall_through);
3374  } else if (String::Equals(check, factory->function_string())) {
3375    __ JumpIfSmi(rax, if_false);
3376    // Check for callable and not undetectable objects => true.
3377    __ movp(rdx, FieldOperand(rax, HeapObject::kMapOffset));
3378    __ movzxbl(rdx, FieldOperand(rdx, Map::kBitFieldOffset));
3379    __ andb(rdx,
3380            Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
3381    __ cmpb(rdx, Immediate(1 << Map::kIsCallable));
3382    Split(equal, if_true, if_false, fall_through);
3383  } else if (String::Equals(check, factory->object_string())) {
3384    __ JumpIfSmi(rax, if_false);
3385    __ CompareRoot(rax, Heap::kNullValueRootIndex);
3386    __ j(equal, if_true);
3387    STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
3388    __ CmpObjectType(rax, FIRST_JS_RECEIVER_TYPE, rdx);
3389    __ j(below, if_false);
3390    // Check for callable or undetectable objects => false.
3391    __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
3392             Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
3393    Split(zero, if_true, if_false, fall_through);
3394// clang-format off
3395#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type)   \
3396  } else if (String::Equals(check, factory->type##_string())) { \
3397    __ JumpIfSmi(rax, if_false);                                \
3398    __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));    \
3399    __ CompareRoot(rax, Heap::k##Type##MapRootIndex);           \
3400    Split(equal, if_true, if_false, fall_through);
3401  SIMD128_TYPES(SIMD128_TYPE)
3402#undef SIMD128_TYPE
3403    // clang-format on
3404  } else {
3405    if (if_false != fall_through) __ jmp(if_false);
3406  }
3407  context()->Plug(if_true, if_false);
3408}
3409
3410
3411void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
3412  Comment cmnt(masm_, "[ CompareOperation");
3413
3414  // First we try a fast inlined version of the compare when one of
3415  // the operands is a literal.
3416  if (TryLiteralCompare(expr)) return;
3417
3418  // Always perform the comparison for its control flow.  Pack the result
3419  // into the expression's context after the comparison is performed.
3420  Label materialize_true, materialize_false;
3421  Label* if_true = NULL;
3422  Label* if_false = NULL;
3423  Label* fall_through = NULL;
3424  context()->PrepareTest(&materialize_true, &materialize_false,
3425                         &if_true, &if_false, &fall_through);
3426
3427  Token::Value op = expr->op();
3428  VisitForStackValue(expr->left());
3429  switch (op) {
3430    case Token::IN:
3431      VisitForStackValue(expr->right());
3432      SetExpressionPosition(expr);
3433      EmitHasProperty();
3434      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
3435      __ CompareRoot(rax, Heap::kTrueValueRootIndex);
3436      Split(equal, if_true, if_false, fall_through);
3437      break;
3438
3439    case Token::INSTANCEOF: {
3440      VisitForAccumulatorValue(expr->right());
3441      SetExpressionPosition(expr);
3442      PopOperand(rdx);
3443      InstanceOfStub stub(isolate());
3444      __ CallStub(&stub);
3445      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
3446      __ CompareRoot(rax, Heap::kTrueValueRootIndex);
3447      Split(equal, if_true, if_false, fall_through);
3448      break;
3449    }
3450
3451    default: {
3452      VisitForAccumulatorValue(expr->right());
3453      SetExpressionPosition(expr);
3454      Condition cc = CompareIC::ComputeCondition(op);
3455      PopOperand(rdx);
3456
3457      bool inline_smi_code = ShouldInlineSmiCase(op);
3458      JumpPatchSite patch_site(masm_);
3459      if (inline_smi_code) {
3460        Label slow_case;
3461        __ movp(rcx, rdx);
3462        __ orp(rcx, rax);
3463        patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
3464        __ cmpp(rdx, rax);
3465        Split(cc, if_true, if_false, NULL);
3466        __ bind(&slow_case);
3467      }
3468
3469      Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
3470      CallIC(ic, expr->CompareOperationFeedbackId());
3471      patch_site.EmitPatchInfo();
3472
3473      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3474      __ testp(rax, rax);
3475      Split(cc, if_true, if_false, fall_through);
3476    }
3477  }
3478
3479  // Convert the result of the comparison into one expected for this
3480  // expression's context.
3481  context()->Plug(if_true, if_false);
3482}
3483
3484
3485void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
3486                                              Expression* sub_expr,
3487                                              NilValue nil) {
3488  Label materialize_true, materialize_false;
3489  Label* if_true = NULL;
3490  Label* if_false = NULL;
3491  Label* fall_through = NULL;
3492  context()->PrepareTest(&materialize_true, &materialize_false,
3493                         &if_true, &if_false, &fall_through);
3494
3495  VisitForAccumulatorValue(sub_expr);
3496  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3497  if (expr->op() == Token::EQ_STRICT) {
3498    Heap::RootListIndex nil_value = nil == kNullValue ?
3499        Heap::kNullValueRootIndex :
3500        Heap::kUndefinedValueRootIndex;
3501    __ CompareRoot(rax, nil_value);
3502    Split(equal, if_true, if_false, fall_through);
3503  } else {
3504    __ JumpIfSmi(rax, if_false);
3505    __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
3506    __ testb(FieldOperand(rax, Map::kBitFieldOffset),
3507             Immediate(1 << Map::kIsUndetectable));
3508    Split(not_zero, if_true, if_false, fall_through);
3509  }
3510  context()->Plug(if_true, if_false);
3511}
3512
3513
3514Register FullCodeGenerator::result_register() {
3515  return rax;
3516}
3517
3518
3519Register FullCodeGenerator::context_register() {
3520  return rsi;
3521}
3522
3523void FullCodeGenerator::LoadFromFrameField(int frame_offset, Register value) {
3524  DCHECK(IsAligned(frame_offset, kPointerSize));
3525  __ movp(value, Operand(rbp, frame_offset));
3526}
3527
3528void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3529  DCHECK(IsAligned(frame_offset, kPointerSize));
3530  __ movp(Operand(rbp, frame_offset), value);
3531}
3532
3533
3534void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
3535  __ movp(dst, ContextOperand(rsi, context_index));
3536}
3537
3538
3539void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
3540  Scope* closure_scope = scope()->ClosureScope();
3541  if (closure_scope->is_script_scope() ||
3542      closure_scope->is_module_scope()) {
3543    // Contexts nested in the native context have a canonical empty function
3544    // as their closure, not the anonymous closure containing the global
3545    // code.
3546    __ movp(rax, NativeContextOperand());
3547    PushOperand(ContextOperand(rax, Context::CLOSURE_INDEX));
3548  } else if (closure_scope->is_eval_scope()) {
3549    // Contexts created by a call to eval have the same closure as the
3550    // context calling eval, not the anonymous closure containing the eval
3551    // code.  Fetch it from the context.
3552    PushOperand(ContextOperand(rsi, Context::CLOSURE_INDEX));
3553  } else {
3554    DCHECK(closure_scope->is_function_scope());
3555    PushOperand(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
3556  }
3557}
3558
3559
3560// ----------------------------------------------------------------------------
3561// Non-local control flow support.
3562
3563
3564void FullCodeGenerator::EnterFinallyBlock() {
3565  DCHECK(!result_register().is(rdx));
3566
3567  // Store pending message while executing finally block.
3568  ExternalReference pending_message_obj =
3569      ExternalReference::address_of_pending_message_obj(isolate());
3570  __ Load(rdx, pending_message_obj);
3571  PushOperand(rdx);
3572
3573  ClearPendingMessage();
3574}
3575
3576
3577void FullCodeGenerator::ExitFinallyBlock() {
3578  DCHECK(!result_register().is(rdx));
3579  // Restore pending message from stack.
3580  PopOperand(rdx);
3581  ExternalReference pending_message_obj =
3582      ExternalReference::address_of_pending_message_obj(isolate());
3583  __ Store(pending_message_obj, rdx);
3584}
3585
3586
3587void FullCodeGenerator::ClearPendingMessage() {
3588  DCHECK(!result_register().is(rdx));
3589  ExternalReference pending_message_obj =
3590      ExternalReference::address_of_pending_message_obj(isolate());
3591  __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
3592  __ Store(pending_message_obj, rdx);
3593}
3594
3595
3596void FullCodeGenerator::DeferredCommands::EmitCommands() {
3597  __ Pop(result_register());  // Restore the accumulator.
3598  __ Pop(rdx);                // Get the token.
3599  for (DeferredCommand cmd : commands_) {
3600    Label skip;
3601    __ SmiCompare(rdx, Smi::FromInt(cmd.token));
3602    __ j(not_equal, &skip);
3603    switch (cmd.command) {
3604      case kReturn:
3605        codegen_->EmitUnwindAndReturn();
3606        break;
3607      case kThrow:
3608        __ Push(result_register());
3609        __ CallRuntime(Runtime::kReThrow);
3610        break;
3611      case kContinue:
3612        codegen_->EmitContinue(cmd.target);
3613        break;
3614      case kBreak:
3615        codegen_->EmitBreak(cmd.target);
3616        break;
3617    }
3618    __ bind(&skip);
3619  }
3620}
3621
3622#undef __
3623
3624
3625static const byte kJnsInstruction = 0x79;
3626static const byte kNopByteOne = 0x66;
3627static const byte kNopByteTwo = 0x90;
3628#ifdef DEBUG
3629static const byte kCallInstruction = 0xe8;
3630#endif
3631
3632
3633void BackEdgeTable::PatchAt(Code* unoptimized_code,
3634                            Address pc,
3635                            BackEdgeState target_state,
3636                            Code* replacement_code) {
3637  Address call_target_address = pc - kIntSize;
3638  Address jns_instr_address = call_target_address - 3;
3639  Address jns_offset_address = call_target_address - 2;
3640
3641  switch (target_state) {
3642    case INTERRUPT:
3643      //     sub <profiling_counter>, <delta>  ;; Not changed
3644      //     jns ok
3645      //     call <interrupt stub>
3646      //   ok:
3647      *jns_instr_address = kJnsInstruction;
3648      *jns_offset_address = kJnsOffset;
3649      break;
3650    case ON_STACK_REPLACEMENT:
3651      //     sub <profiling_counter>, <delta>  ;; Not changed
3652      //     nop
3653      //     nop
3654      //     call <on-stack replacment>
3655      //   ok:
3656      *jns_instr_address = kNopByteOne;
3657      *jns_offset_address = kNopByteTwo;
3658      break;
3659  }
3660
3661  Assembler::set_target_address_at(unoptimized_code->GetIsolate(),
3662                                   call_target_address, unoptimized_code,
3663                                   replacement_code->entry());
3664  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
3665      unoptimized_code, call_target_address, replacement_code);
3666}
3667
3668
3669BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
3670    Isolate* isolate,
3671    Code* unoptimized_code,
3672    Address pc) {
3673  Address call_target_address = pc - kIntSize;
3674  Address jns_instr_address = call_target_address - 3;
3675  DCHECK_EQ(kCallInstruction, *(call_target_address - 1));
3676
3677  if (*jns_instr_address == kJnsInstruction) {
3678    DCHECK_EQ(kJnsOffset, *(call_target_address - 2));
3679    DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(),
3680              Assembler::target_address_at(call_target_address,
3681                                           unoptimized_code));
3682    return INTERRUPT;
3683  }
3684
3685  DCHECK_EQ(kNopByteOne, *jns_instr_address);
3686  DCHECK_EQ(kNopByteTwo, *(call_target_address - 2));
3687
3688  DCHECK_EQ(
3689      isolate->builtins()->OnStackReplacement()->entry(),
3690      Assembler::target_address_at(call_target_address, unoptimized_code));
3691  return ON_STACK_REPLACEMENT;
3692}
3693
3694}  // namespace internal
3695}  // namespace v8
3696
3697#endif  // V8_TARGET_ARCH_X64
3698