d8c60ad445fb89c6698e9ab0f9886fdaf8002a82
[platform/upstream/v8.git] / src / full-codegen / x64 / full-codegen-x64.cc
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 #include "src/v8.h"
6
7 #if V8_TARGET_ARCH_X64
8
9 #include "src/code-factory.h"
10 #include "src/code-stubs.h"
11 #include "src/codegen.h"
12 #include "src/compiler.h"
13 #include "src/debug/debug.h"
14 #include "src/full-codegen/full-codegen.h"
15 #include "src/ic/ic.h"
16 #include "src/parser.h"
17 #include "src/scopes.h"
18
19 namespace v8 {
20 namespace internal {
21
22 #define __ ACCESS_MASM(masm_)
23
24
25 class JumpPatchSite BASE_EMBEDDED {
26  public:
27   explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
28 #ifdef DEBUG
29     info_emitted_ = false;
30 #endif
31   }
32
33   ~JumpPatchSite() {
34     DCHECK(patch_site_.is_bound() == info_emitted_);
35   }
36
37   void EmitJumpIfNotSmi(Register reg,
38                         Label* target,
39                         Label::Distance near_jump = Label::kFar) {
40     __ testb(reg, Immediate(kSmiTagMask));
41     EmitJump(not_carry, target, near_jump);   // Always taken before patched.
42   }
43
44   void EmitJumpIfSmi(Register reg,
45                      Label* target,
46                      Label::Distance near_jump = Label::kFar) {
47     __ testb(reg, Immediate(kSmiTagMask));
48     EmitJump(carry, target, near_jump);  // Never taken before patched.
49   }
50
51   void EmitPatchInfo() {
52     if (patch_site_.is_bound()) {
53       int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
54       DCHECK(is_uint8(delta_to_patch_site));
55       __ testl(rax, Immediate(delta_to_patch_site));
56 #ifdef DEBUG
57       info_emitted_ = true;
58 #endif
59     } else {
60       __ nop();  // Signals no inlined code.
61     }
62   }
63
64  private:
65   // jc will be patched with jz, jnc will become jnz.
66   void EmitJump(Condition cc, Label* target, Label::Distance near_jump) {
67     DCHECK(!patch_site_.is_bound() && !info_emitted_);
68     DCHECK(cc == carry || cc == not_carry);
69     __ bind(&patch_site_);
70     __ j(cc, target, near_jump);
71   }
72
73   MacroAssembler* masm_;
74   Label patch_site_;
75 #ifdef DEBUG
76   bool info_emitted_;
77 #endif
78 };
79
80
81 // Generate code for a JS function.  On entry to the function the receiver
82 // and arguments have been pushed on the stack left to right, with the
83 // return address on top of them.  The actual argument count matches the
84 // formal parameter count expected by the function.
85 //
86 // The live registers are:
87 //   o rdi: the JS function object being called (i.e. ourselves)
88 //   o rsi: our context
89 //   o rbp: our caller's frame pointer
90 //   o rsp: stack pointer (pointing to return address)
91 //
92 // The function builds a JS frame.  Please see JavaScriptFrameConstants in
93 // frames-x64.h for its layout.
94 void FullCodeGenerator::Generate() {
95   CompilationInfo* info = info_;
96   profiling_counter_ = isolate()->factory()->NewCell(
97       Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
98   SetFunctionPosition(function());
99   Comment cmnt(masm_, "[ function compiled by full code generator");
100
101   ProfileEntryHookStub::MaybeCallEntryHook(masm_);
102
103 #ifdef DEBUG
104   if (strlen(FLAG_stop_at) > 0 &&
105       info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
106     __ int3();
107   }
108 #endif
109
110   // Sloppy mode functions and builtins need to replace the receiver with the
111   // global proxy when called as functions (without an explicit receiver
112   // object).
113   if (is_sloppy(info->language_mode()) && !info->is_native() &&
114       info->MayUseThis() && info->scope()->has_this_declaration()) {
115     Label ok;
116     // +1 for return address.
117     StackArgumentsAccessor args(rsp, info->scope()->num_parameters());
118     __ movp(rcx, args.GetReceiverOperand());
119
120     __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
121     __ j(not_equal, &ok, Label::kNear);
122
123     __ movp(rcx, GlobalObjectOperand());
124     __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalProxyOffset));
125
126     __ movp(args.GetReceiverOperand(), rcx);
127
128     __ bind(&ok);
129   }
130
131   // Open a frame scope to indicate that there is a frame on the stack.  The
132   // MANUAL indicates that the scope shouldn't actually generate code to set up
133   // the frame (that is done below).
134   FrameScope frame_scope(masm_, StackFrame::MANUAL);
135
136   info->set_prologue_offset(masm_->pc_offset());
137   __ Prologue(info->IsCodePreAgingActive());
138   info->AddNoFrameRange(0, masm_->pc_offset());
139
140   { Comment cmnt(masm_, "[ Allocate locals");
141     int locals_count = info->scope()->num_stack_slots();
142     // Generators allocate locals, if any, in context slots.
143     DCHECK(!IsGeneratorFunction(info->function()->kind()) || locals_count == 0);
144     if (locals_count == 1) {
145       __ PushRoot(Heap::kUndefinedValueRootIndex);
146     } else if (locals_count > 1) {
147       if (locals_count >= 128) {
148         Label ok;
149         __ movp(rcx, rsp);
150         __ subp(rcx, Immediate(locals_count * kPointerSize));
151         __ CompareRoot(rcx, Heap::kRealStackLimitRootIndex);
152         __ j(above_equal, &ok, Label::kNear);
153         __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
154         __ bind(&ok);
155       }
156       __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
157       const int kMaxPushes = 32;
158       if (locals_count >= kMaxPushes) {
159         int loop_iterations = locals_count / kMaxPushes;
160         __ movp(rcx, Immediate(loop_iterations));
161         Label loop_header;
162         __ bind(&loop_header);
163         // Do pushes.
164         for (int i = 0; i < kMaxPushes; i++) {
165           __ Push(rdx);
166         }
167         // Continue loop if not done.
168         __ decp(rcx);
169         __ j(not_zero, &loop_header, Label::kNear);
170       }
171       int remaining = locals_count % kMaxPushes;
172       // Emit the remaining pushes.
173       for (int i  = 0; i < remaining; i++) {
174         __ Push(rdx);
175       }
176     }
177   }
178
179   bool function_in_register = true;
180
181   // Possibly allocate a local context.
182   if (info->scope()->num_heap_slots() > 0) {
183     Comment cmnt(masm_, "[ Allocate context");
184     bool need_write_barrier = true;
185     int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
186     // Argument to NewContext is the function, which is still in rdi.
187     if (info->scope()->is_script_scope()) {
188       __ Push(rdi);
189       __ Push(info->scope()->GetScopeInfo(info->isolate()));
190       __ CallRuntime(Runtime::kNewScriptContext, 2);
191     } else if (slots <= FastNewContextStub::kMaximumSlots) {
192       FastNewContextStub stub(isolate(), slots);
193       __ CallStub(&stub);
194       // Result of FastNewContextStub is always in new space.
195       need_write_barrier = false;
196     } else {
197       __ Push(rdi);
198       __ CallRuntime(Runtime::kNewFunctionContext, 1);
199     }
200     function_in_register = false;
201     // Context is returned in rax.  It replaces the context passed to us.
202     // It's saved in the stack and kept live in rsi.
203     __ movp(rsi, rax);
204     __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax);
205
206     // Copy any necessary parameters into the context.
207     int num_parameters = info->scope()->num_parameters();
208     int first_parameter = info->scope()->has_this_declaration() ? -1 : 0;
209     for (int i = first_parameter; i < num_parameters; i++) {
210       Variable* var = (i == -1) ? scope()->receiver() : scope()->parameter(i);
211       if (var->IsContextSlot()) {
212         int parameter_offset = StandardFrameConstants::kCallerSPOffset +
213             (num_parameters - 1 - i) * kPointerSize;
214         // Load parameter from stack.
215         __ movp(rax, Operand(rbp, parameter_offset));
216         // Store it in the context.
217         int context_offset = Context::SlotOffset(var->index());
218         __ movp(Operand(rsi, context_offset), rax);
219         // Update the write barrier.  This clobbers rax and rbx.
220         if (need_write_barrier) {
221           __ RecordWriteContextSlot(
222               rsi, context_offset, rax, rbx, kDontSaveFPRegs);
223         } else if (FLAG_debug_code) {
224           Label done;
225           __ JumpIfInNewSpace(rsi, rax, &done, Label::kNear);
226           __ Abort(kExpectedNewSpaceObject);
227           __ bind(&done);
228         }
229       }
230     }
231   }
232
233   // Possibly set up a local binding to the this function which is used in
234   // derived constructors with super calls.
235   Variable* this_function_var = scope()->this_function_var();
236   if (this_function_var != nullptr) {
237     Comment cmnt(masm_, "[ This function");
238     if (!function_in_register) {
239       __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
240       // The write barrier clobbers register again, keep is marked as such.
241     }
242     SetVar(this_function_var, rdi, rbx, rdx);
243   }
244
245   Variable* new_target_var = scope()->new_target_var();
246   if (new_target_var != nullptr) {
247     Comment cmnt(masm_, "[ new.target");
248
249     __ movp(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
250     Label non_adaptor_frame;
251     __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset),
252            Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
253     __ j(not_equal, &non_adaptor_frame);
254     __ movp(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
255
256     __ bind(&non_adaptor_frame);
257     __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset),
258            Smi::FromInt(StackFrame::CONSTRUCT));
259
260     Label non_construct_frame, done;
261     __ j(not_equal, &non_construct_frame);
262
263     // Construct frame
264     __ movp(rax,
265             Operand(rax, ConstructFrameConstants::kOriginalConstructorOffset));
266     __ jmp(&done);
267
268     // Non-construct frame
269     __ bind(&non_construct_frame);
270     __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
271
272     __ bind(&done);
273     SetVar(new_target_var, rax, rbx, rdx);
274   }
275
276   // Possibly allocate RestParameters
277   int rest_index;
278   Variable* rest_param = scope()->rest_parameter(&rest_index);
279   if (rest_param) {
280     Comment cmnt(masm_, "[ Allocate rest parameter array");
281
282     int num_parameters = info->scope()->num_parameters();
283     int offset = num_parameters * kPointerSize;
284
285     __ leap(rdx,
286             Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
287     __ Push(rdx);
288     __ Push(Smi::FromInt(num_parameters));
289     __ Push(Smi::FromInt(rest_index));
290     __ Push(Smi::FromInt(language_mode()));
291
292     RestParamAccessStub stub(isolate());
293     __ CallStub(&stub);
294
295     SetVar(rest_param, rax, rbx, rdx);
296   }
297
298   // Possibly allocate an arguments object.
299   Variable* arguments = scope()->arguments();
300   if (arguments != NULL) {
301     // Arguments object must be allocated after the context object, in
302     // case the "arguments" or ".arguments" variables are in the context.
303     Comment cmnt(masm_, "[ Allocate arguments object");
304     if (function_in_register) {
305       __ Push(rdi);
306     } else {
307       __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
308     }
309     // The receiver is just before the parameters on the caller's stack.
310     int num_parameters = info->scope()->num_parameters();
311     int offset = num_parameters * kPointerSize;
312     __ leap(rdx,
313            Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
314     __ Push(rdx);
315     __ Push(Smi::FromInt(num_parameters));
316     // Arguments to ArgumentsAccessStub:
317     //   function, receiver address, parameter count.
318     // The stub will rewrite receiver and parameter count if the previous
319     // stack frame was an arguments adapter frame.
320
321     ArgumentsAccessStub::Type type;
322     if (is_strict(language_mode()) || !is_simple_parameter_list()) {
323       type = ArgumentsAccessStub::NEW_STRICT;
324     } else if (function()->has_duplicate_parameters()) {
325       type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
326     } else {
327       type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
328     }
329     ArgumentsAccessStub stub(isolate(), type);
330     __ CallStub(&stub);
331
332     SetVar(arguments, rax, rbx, rdx);
333   }
334
335   if (FLAG_trace) {
336     __ CallRuntime(Runtime::kTraceEnter, 0);
337   }
338
339   // Visit the declarations and body unless there is an illegal
340   // redeclaration.
341   if (scope()->HasIllegalRedeclaration()) {
342     Comment cmnt(masm_, "[ Declarations");
343     scope()->VisitIllegalRedeclaration(this);
344
345   } else {
346     PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
347     { Comment cmnt(masm_, "[ Declarations");
348       VisitDeclarations(scope()->declarations());
349     }
350
351     // Assert that the declarations do not use ICs. Otherwise the debugger
352     // won't be able to redirect a PC at an IC to the correct IC in newly
353     // recompiled code.
354     DCHECK_EQ(0, ic_total_count_);
355
356     { Comment cmnt(masm_, "[ Stack check");
357       PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
358        Label ok;
359        __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
360        __ j(above_equal, &ok, Label::kNear);
361        __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET);
362        __ bind(&ok);
363     }
364
365     { Comment cmnt(masm_, "[ Body");
366       DCHECK(loop_depth() == 0);
367       VisitStatements(function()->body());
368       DCHECK(loop_depth() == 0);
369     }
370   }
371
372   // Always emit a 'return undefined' in case control fell off the end of
373   // the body.
374   { Comment cmnt(masm_, "[ return <undefined>;");
375     __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
376     EmitReturnSequence();
377   }
378 }
379
380
381 void FullCodeGenerator::ClearAccumulator() {
382   __ Set(rax, 0);
383 }
384
385
386 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
387   __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
388   __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset),
389                     Smi::FromInt(-delta));
390 }
391
392
393 void FullCodeGenerator::EmitProfilingCounterReset() {
394   int reset_value = FLAG_interrupt_budget;
395   __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
396   __ Move(kScratchRegister, Smi::FromInt(reset_value));
397   __ movp(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister);
398 }
399
400
401 static const byte kJnsOffset = kPointerSize == kInt64Size ? 0x1d : 0x14;
402
403
404 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
405                                                 Label* back_edge_target) {
406   Comment cmnt(masm_, "[ Back edge bookkeeping");
407   Label ok;
408
409   DCHECK(back_edge_target->is_bound());
410   int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
411   int weight = Min(kMaxBackEdgeWeight,
412                    Max(1, distance / kCodeSizeMultiplier));
413   EmitProfilingCounterDecrement(weight);
414
415   __ j(positive, &ok, Label::kNear);
416   {
417     PredictableCodeSizeScope predictible_code_size_scope(masm_, kJnsOffset);
418     DontEmitDebugCodeScope dont_emit_debug_code_scope(masm_);
419     __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
420
421     // Record a mapping of this PC offset to the OSR id.  This is used to find
422     // the AST id from the unoptimized code in order to use it as a key into
423     // the deoptimization input data found in the optimized code.
424     RecordBackEdge(stmt->OsrEntryId());
425
426     EmitProfilingCounterReset();
427   }
428   __ bind(&ok);
429
430   PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
431   // Record a mapping of the OSR id to this PC.  This is used if the OSR
432   // entry becomes the target of a bailout.  We don't expect it to be, but
433   // we want it to work if it is.
434   PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
435 }
436
437
438 void FullCodeGenerator::EmitReturnSequence() {
439   Comment cmnt(masm_, "[ Return sequence");
440   if (return_label_.is_bound()) {
441     __ jmp(&return_label_);
442   } else {
443     __ bind(&return_label_);
444     if (FLAG_trace) {
445       __ Push(rax);
446       __ CallRuntime(Runtime::kTraceExit, 1);
447     }
448     // Pretend that the exit is a backwards jump to the entry.
449     int weight = 1;
450     if (info_->ShouldSelfOptimize()) {
451       weight = FLAG_interrupt_budget / FLAG_self_opt_count;
452     } else {
453       int distance = masm_->pc_offset();
454       weight = Min(kMaxBackEdgeWeight,
455                    Max(1, distance / kCodeSizeMultiplier));
456     }
457     EmitProfilingCounterDecrement(weight);
458     Label ok;
459     __ j(positive, &ok, Label::kNear);
460     __ Push(rax);
461     __ call(isolate()->builtins()->InterruptCheck(),
462             RelocInfo::CODE_TARGET);
463     __ Pop(rax);
464     EmitProfilingCounterReset();
465     __ bind(&ok);
466
467     SetReturnPosition(function());
468     int no_frame_start = masm_->pc_offset();
469     __ leave();
470
471     int arg_count = info_->scope()->num_parameters() + 1;
472     int arguments_bytes = arg_count * kPointerSize;
473     __ Ret(arguments_bytes, rcx);
474
475     info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
476   }
477 }
478
479
480 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
481   DCHECK(var->IsStackAllocated() || var->IsContextSlot());
482   MemOperand operand = codegen()->VarOperand(var, result_register());
483   __ Push(operand);
484 }
485
486
487 void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
488 }
489
490
491 void FullCodeGenerator::AccumulatorValueContext::Plug(
492     Heap::RootListIndex index) const {
493   __ LoadRoot(result_register(), index);
494 }
495
496
497 void FullCodeGenerator::StackValueContext::Plug(
498     Heap::RootListIndex index) const {
499   __ PushRoot(index);
500 }
501
502
503 void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
504   codegen()->PrepareForBailoutBeforeSplit(condition(),
505                                           true,
506                                           true_label_,
507                                           false_label_);
508   if (index == Heap::kUndefinedValueRootIndex ||
509       index == Heap::kNullValueRootIndex ||
510       index == Heap::kFalseValueRootIndex) {
511     if (false_label_ != fall_through_) __ jmp(false_label_);
512   } else if (index == Heap::kTrueValueRootIndex) {
513     if (true_label_ != fall_through_) __ jmp(true_label_);
514   } else {
515     __ LoadRoot(result_register(), index);
516     codegen()->DoTest(this);
517   }
518 }
519
520
521 void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
522 }
523
524
525 void FullCodeGenerator::AccumulatorValueContext::Plug(
526     Handle<Object> lit) const {
527   if (lit->IsSmi()) {
528     __ SafeMove(result_register(), Smi::cast(*lit));
529   } else {
530     __ Move(result_register(), lit);
531   }
532 }
533
534
535 void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
536   if (lit->IsSmi()) {
537     __ SafePush(Smi::cast(*lit));
538   } else {
539     __ Push(lit);
540   }
541 }
542
543
544 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
545   codegen()->PrepareForBailoutBeforeSplit(condition(),
546                                           true,
547                                           true_label_,
548                                           false_label_);
549   DCHECK(!lit->IsUndetectableObject());  // There are no undetectable literals.
550   if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
551     if (false_label_ != fall_through_) __ jmp(false_label_);
552   } else if (lit->IsTrue() || lit->IsJSObject()) {
553     if (true_label_ != fall_through_) __ jmp(true_label_);
554   } else if (lit->IsString()) {
555     if (String::cast(*lit)->length() == 0) {
556       if (false_label_ != fall_through_) __ jmp(false_label_);
557     } else {
558       if (true_label_ != fall_through_) __ jmp(true_label_);
559     }
560   } else if (lit->IsSmi()) {
561     if (Smi::cast(*lit)->value() == 0) {
562       if (false_label_ != fall_through_) __ jmp(false_label_);
563     } else {
564       if (true_label_ != fall_through_) __ jmp(true_label_);
565     }
566   } else {
567     // For simplicity we always test the accumulator register.
568     __ Move(result_register(), lit);
569     codegen()->DoTest(this);
570   }
571 }
572
573
574 void FullCodeGenerator::EffectContext::DropAndPlug(int count,
575                                                    Register reg) const {
576   DCHECK(count > 0);
577   __ Drop(count);
578 }
579
580
581 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
582     int count,
583     Register reg) const {
584   DCHECK(count > 0);
585   __ Drop(count);
586   __ Move(result_register(), reg);
587 }
588
589
590 void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
591                                                        Register reg) const {
592   DCHECK(count > 0);
593   if (count > 1) __ Drop(count - 1);
594   __ movp(Operand(rsp, 0), reg);
595 }
596
597
598 void FullCodeGenerator::TestContext::DropAndPlug(int count,
599                                                  Register reg) const {
600   DCHECK(count > 0);
601   // For simplicity we always test the accumulator register.
602   __ Drop(count);
603   __ Move(result_register(), reg);
604   codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
605   codegen()->DoTest(this);
606 }
607
608
609 void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
610                                             Label* materialize_false) const {
611   DCHECK(materialize_true == materialize_false);
612   __ bind(materialize_true);
613 }
614
615
616 void FullCodeGenerator::AccumulatorValueContext::Plug(
617     Label* materialize_true,
618     Label* materialize_false) const {
619   Label done;
620   __ bind(materialize_true);
621   __ Move(result_register(), isolate()->factory()->true_value());
622   __ jmp(&done, Label::kNear);
623   __ bind(materialize_false);
624   __ Move(result_register(), isolate()->factory()->false_value());
625   __ bind(&done);
626 }
627
628
629 void FullCodeGenerator::StackValueContext::Plug(
630     Label* materialize_true,
631     Label* materialize_false) const {
632   Label done;
633   __ bind(materialize_true);
634   __ Push(isolate()->factory()->true_value());
635   __ jmp(&done, Label::kNear);
636   __ bind(materialize_false);
637   __ Push(isolate()->factory()->false_value());
638   __ bind(&done);
639 }
640
641
642 void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
643                                           Label* materialize_false) const {
644   DCHECK(materialize_true == true_label_);
645   DCHECK(materialize_false == false_label_);
646 }
647
648
649 void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
650   Heap::RootListIndex value_root_index =
651       flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
652   __ LoadRoot(result_register(), value_root_index);
653 }
654
655
656 void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
657   Heap::RootListIndex value_root_index =
658       flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
659   __ PushRoot(value_root_index);
660 }
661
662
663 void FullCodeGenerator::TestContext::Plug(bool flag) const {
664   codegen()->PrepareForBailoutBeforeSplit(condition(),
665                                           true,
666                                           true_label_,
667                                           false_label_);
668   if (flag) {
669     if (true_label_ != fall_through_) __ jmp(true_label_);
670   } else {
671     if (false_label_ != fall_through_) __ jmp(false_label_);
672   }
673 }
674
675
676 void FullCodeGenerator::DoTest(Expression* condition,
677                                Label* if_true,
678                                Label* if_false,
679                                Label* fall_through) {
680   Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
681   CallIC(ic, condition->test_id());
682   __ testp(result_register(), result_register());
683   // The stub returns nonzero for true.
684   Split(not_zero, if_true, if_false, fall_through);
685 }
686
687
688 void FullCodeGenerator::Split(Condition cc,
689                               Label* if_true,
690                               Label* if_false,
691                               Label* fall_through) {
692   if (if_false == fall_through) {
693     __ j(cc, if_true);
694   } else if (if_true == fall_through) {
695     __ j(NegateCondition(cc), if_false);
696   } else {
697     __ j(cc, if_true);
698     __ jmp(if_false);
699   }
700 }
701
702
703 MemOperand FullCodeGenerator::StackOperand(Variable* var) {
704   DCHECK(var->IsStackAllocated());
705   // Offset is negative because higher indexes are at lower addresses.
706   int offset = -var->index() * kPointerSize;
707   // Adjust by a (parameter or local) base offset.
708   if (var->IsParameter()) {
709     offset += kFPOnStackSize + kPCOnStackSize +
710               (info_->scope()->num_parameters() - 1) * kPointerSize;
711   } else {
712     offset += JavaScriptFrameConstants::kLocal0Offset;
713   }
714   return Operand(rbp, offset);
715 }
716
717
718 MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
719   DCHECK(var->IsContextSlot() || var->IsStackAllocated());
720   if (var->IsContextSlot()) {
721     int context_chain_length = scope()->ContextChainLength(var->scope());
722     __ LoadContext(scratch, context_chain_length);
723     return ContextOperand(scratch, var->index());
724   } else {
725     return StackOperand(var);
726   }
727 }
728
729
730 void FullCodeGenerator::GetVar(Register dest, Variable* var) {
731   DCHECK(var->IsContextSlot() || var->IsStackAllocated());
732   MemOperand location = VarOperand(var, dest);
733   __ movp(dest, location);
734 }
735
736
737 void FullCodeGenerator::SetVar(Variable* var,
738                                Register src,
739                                Register scratch0,
740                                Register scratch1) {
741   DCHECK(var->IsContextSlot() || var->IsStackAllocated());
742   DCHECK(!scratch0.is(src));
743   DCHECK(!scratch0.is(scratch1));
744   DCHECK(!scratch1.is(src));
745   MemOperand location = VarOperand(var, scratch0);
746   __ movp(location, src);
747
748   // Emit the write barrier code if the location is in the heap.
749   if (var->IsContextSlot()) {
750     int offset = Context::SlotOffset(var->index());
751     __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
752   }
753 }
754
755
756 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
757                                                      bool should_normalize,
758                                                      Label* if_true,
759                                                      Label* if_false) {
760   // Only prepare for bailouts before splits if we're in a test
761   // context. Otherwise, we let the Visit function deal with the
762   // preparation to avoid preparing with the same AST id twice.
763   if (!context()->IsTest() || !info_->IsOptimizable()) return;
764
765   Label skip;
766   if (should_normalize) __ jmp(&skip, Label::kNear);
767   PrepareForBailout(expr, TOS_REG);
768   if (should_normalize) {
769     __ CompareRoot(rax, Heap::kTrueValueRootIndex);
770     Split(equal, if_true, if_false, NULL);
771     __ bind(&skip);
772   }
773 }
774
775
776 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
777   // The variable in the declaration always resides in the current context.
778   DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
779   if (generate_debug_code_) {
780     // Check that we're not inside a with or catch context.
781     __ movp(rbx, FieldOperand(rsi, HeapObject::kMapOffset));
782     __ CompareRoot(rbx, Heap::kWithContextMapRootIndex);
783     __ Check(not_equal, kDeclarationInWithContext);
784     __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
785     __ Check(not_equal, kDeclarationInCatchContext);
786   }
787 }
788
789
790 void FullCodeGenerator::VisitVariableDeclaration(
791     VariableDeclaration* declaration) {
792   // If it was not possible to allocate the variable at compile time, we
793   // need to "declare" it at runtime to make sure it actually exists in the
794   // local context.
795   VariableProxy* proxy = declaration->proxy();
796   VariableMode mode = declaration->mode();
797   Variable* variable = proxy->var();
798   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
799   switch (variable->location()) {
800     case VariableLocation::GLOBAL:
801     case VariableLocation::UNALLOCATED:
802       globals_->Add(variable->name(), zone());
803       globals_->Add(variable->binding_needs_init()
804                         ? isolate()->factory()->the_hole_value()
805                     : isolate()->factory()->undefined_value(),
806                     zone());
807       break;
808
809     case VariableLocation::PARAMETER:
810     case VariableLocation::LOCAL:
811       if (hole_init) {
812         Comment cmnt(masm_, "[ VariableDeclaration");
813         __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
814         __ movp(StackOperand(variable), kScratchRegister);
815       }
816       break;
817
818     case VariableLocation::CONTEXT:
819       if (hole_init) {
820         Comment cmnt(masm_, "[ VariableDeclaration");
821         EmitDebugCheckDeclarationContext(variable);
822         __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
823         __ movp(ContextOperand(rsi, variable->index()), kScratchRegister);
824         // No write barrier since the hole value is in old space.
825         PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
826       }
827       break;
828
829     case VariableLocation::LOOKUP: {
830       Comment cmnt(masm_, "[ VariableDeclaration");
831       __ Push(variable->name());
832       // Declaration nodes are always introduced in one of four modes.
833       DCHECK(IsDeclaredVariableMode(mode));
834       // Push initial value, if any.
835       // Note: For variables we must not push an initial value (such as
836       // 'undefined') because we may have a (legal) redeclaration and we
837       // must not destroy the current value.
838       if (hole_init) {
839         __ PushRoot(Heap::kTheHoleValueRootIndex);
840       } else {
841         __ Push(Smi::FromInt(0));  // Indicates no initial value.
842       }
843       __ CallRuntime(IsImmutableVariableMode(mode)
844                          ? Runtime::kDeclareReadOnlyLookupSlot
845                          : Runtime::kDeclareLookupSlot,
846                      2);
847       break;
848     }
849   }
850 }
851
852
853 void FullCodeGenerator::VisitFunctionDeclaration(
854     FunctionDeclaration* declaration) {
855   VariableProxy* proxy = declaration->proxy();
856   Variable* variable = proxy->var();
857   switch (variable->location()) {
858     case VariableLocation::GLOBAL:
859     case VariableLocation::UNALLOCATED: {
860       globals_->Add(variable->name(), zone());
861       Handle<SharedFunctionInfo> function =
862           Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
863       // Check for stack-overflow exception.
864       if (function.is_null()) return SetStackOverflow();
865       globals_->Add(function, zone());
866       break;
867     }
868
869     case VariableLocation::PARAMETER:
870     case VariableLocation::LOCAL: {
871       Comment cmnt(masm_, "[ FunctionDeclaration");
872       VisitForAccumulatorValue(declaration->fun());
873       __ movp(StackOperand(variable), result_register());
874       break;
875     }
876
877     case VariableLocation::CONTEXT: {
878       Comment cmnt(masm_, "[ FunctionDeclaration");
879       EmitDebugCheckDeclarationContext(variable);
880       VisitForAccumulatorValue(declaration->fun());
881       __ movp(ContextOperand(rsi, variable->index()), result_register());
882       int offset = Context::SlotOffset(variable->index());
883       // We know that we have written a function, which is not a smi.
884       __ RecordWriteContextSlot(rsi,
885                                 offset,
886                                 result_register(),
887                                 rcx,
888                                 kDontSaveFPRegs,
889                                 EMIT_REMEMBERED_SET,
890                                 OMIT_SMI_CHECK);
891       PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
892       break;
893     }
894
895     case VariableLocation::LOOKUP: {
896       Comment cmnt(masm_, "[ FunctionDeclaration");
897       __ Push(variable->name());
898       VisitForStackValue(declaration->fun());
899       __ CallRuntime(Runtime::kDeclareLookupSlot, 2);
900       break;
901     }
902   }
903 }
904
905
906 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
907   // Call the runtime to declare the globals.
908   __ Push(pairs);
909   __ Push(Smi::FromInt(DeclareGlobalsFlags()));
910   __ CallRuntime(Runtime::kDeclareGlobals, 2);
911   // Return value is ignored.
912 }
913
914
915 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) {
916   // Call the runtime to declare the modules.
917   __ Push(descriptions);
918   __ CallRuntime(Runtime::kDeclareModules, 1);
919   // Return value is ignored.
920 }
921
922
923 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
924   Comment cmnt(masm_, "[ SwitchStatement");
925   Breakable nested_statement(this, stmt);
926   SetStatementPosition(stmt);
927
928   // Keep the switch value on the stack until a case matches.
929   VisitForStackValue(stmt->tag());
930   PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
931
932   ZoneList<CaseClause*>* clauses = stmt->cases();
933   CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
934
935   Label next_test;  // Recycled for each test.
936   // Compile all the tests with branches to their bodies.
937   for (int i = 0; i < clauses->length(); i++) {
938     CaseClause* clause = clauses->at(i);
939     clause->body_target()->Unuse();
940
941     // The default is not a test, but remember it as final fall through.
942     if (clause->is_default()) {
943       default_clause = clause;
944       continue;
945     }
946
947     Comment cmnt(masm_, "[ Case comparison");
948     __ bind(&next_test);
949     next_test.Unuse();
950
951     // Compile the label expression.
952     VisitForAccumulatorValue(clause->label());
953
954     // Perform the comparison as if via '==='.
955     __ movp(rdx, Operand(rsp, 0));  // Switch value.
956     bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
957     JumpPatchSite patch_site(masm_);
958     if (inline_smi_code) {
959       Label slow_case;
960       __ movp(rcx, rdx);
961       __ orp(rcx, rax);
962       patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
963
964       __ cmpp(rdx, rax);
965       __ j(not_equal, &next_test);
966       __ Drop(1);  // Switch value is no longer needed.
967       __ jmp(clause->body_target());
968       __ bind(&slow_case);
969     }
970
971     // Record position before stub call for type feedback.
972     SetExpressionPosition(clause);
973     Handle<Code> ic = CodeFactory::CompareIC(isolate(), Token::EQ_STRICT,
974                                              strength(language_mode())).code();
975     CallIC(ic, clause->CompareId());
976     patch_site.EmitPatchInfo();
977
978     Label skip;
979     __ jmp(&skip, Label::kNear);
980     PrepareForBailout(clause, TOS_REG);
981     __ CompareRoot(rax, Heap::kTrueValueRootIndex);
982     __ j(not_equal, &next_test);
983     __ Drop(1);
984     __ jmp(clause->body_target());
985     __ bind(&skip);
986
987     __ testp(rax, rax);
988     __ j(not_equal, &next_test);
989     __ Drop(1);  // Switch value is no longer needed.
990     __ jmp(clause->body_target());
991   }
992
993   // Discard the test value and jump to the default if present, otherwise to
994   // the end of the statement.
995   __ bind(&next_test);
996   __ Drop(1);  // Switch value is no longer needed.
997   if (default_clause == NULL) {
998     __ jmp(nested_statement.break_label());
999   } else {
1000     __ jmp(default_clause->body_target());
1001   }
1002
1003   // Compile all the case bodies.
1004   for (int i = 0; i < clauses->length(); i++) {
1005     Comment cmnt(masm_, "[ Case body");
1006     CaseClause* clause = clauses->at(i);
1007     __ bind(clause->body_target());
1008     PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
1009     VisitStatements(clause->statements());
1010   }
1011
1012   __ bind(nested_statement.break_label());
1013   PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1014 }
1015
1016
1017 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1018   Comment cmnt(masm_, "[ ForInStatement");
1019   SetStatementPosition(stmt, SKIP_BREAK);
1020
1021   FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
1022
1023   Label loop, exit;
1024   ForIn loop_statement(this, stmt);
1025   increment_loop_depth();
1026
1027   // Get the object to enumerate over. If the object is null or undefined, skip
1028   // over the loop.  See ECMA-262 version 5, section 12.6.4.
1029   SetExpressionAsStatementPosition(stmt->enumerable());
1030   VisitForAccumulatorValue(stmt->enumerable());
1031   __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
1032   __ j(equal, &exit);
1033   Register null_value = rdi;
1034   __ LoadRoot(null_value, Heap::kNullValueRootIndex);
1035   __ cmpp(rax, null_value);
1036   __ j(equal, &exit);
1037
1038   PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
1039
1040   // Convert the object to a JS object.
1041   Label convert, done_convert;
1042   __ JumpIfSmi(rax, &convert);
1043   __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
1044   __ j(above_equal, &done_convert);
1045   __ bind(&convert);
1046   __ Push(rax);
1047   __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1048   __ bind(&done_convert);
1049   PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
1050   __ Push(rax);
1051
1052   // Check for proxies.
1053   Label call_runtime;
1054   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1055   __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx);
1056   __ j(below_equal, &call_runtime);
1057
1058   // Check cache validity in generated code. This is a fast case for
1059   // the JSObject::IsSimpleEnum cache validity checks. If we cannot
1060   // guarantee cache validity, call the runtime system to check cache
1061   // validity or get the property names in a fixed array.
1062   __ CheckEnumCache(null_value, &call_runtime);
1063
1064   // The enum cache is valid.  Load the map of the object being
1065   // iterated over and use the cache for the iteration.
1066   Label use_cache;
1067   __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
1068   __ jmp(&use_cache, Label::kNear);
1069
1070   // Get the set of properties to enumerate.
1071   __ bind(&call_runtime);
1072   __ Push(rax);  // Duplicate the enumerable object on the stack.
1073   __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1074   PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
1075
1076   // If we got a map from the runtime call, we can do a fast
1077   // modification check. Otherwise, we got a fixed array, and we have
1078   // to do a slow check.
1079   Label fixed_array;
1080   __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
1081                  Heap::kMetaMapRootIndex);
1082   __ j(not_equal, &fixed_array);
1083
1084   // We got a map in register rax. Get the enumeration cache from it.
1085   __ bind(&use_cache);
1086
1087   Label no_descriptors;
1088
1089   __ EnumLength(rdx, rax);
1090   __ Cmp(rdx, Smi::FromInt(0));
1091   __ j(equal, &no_descriptors);
1092
1093   __ LoadInstanceDescriptors(rax, rcx);
1094   __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheOffset));
1095   __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1096
1097   // Set up the four remaining stack slots.
1098   __ Push(rax);  // Map.
1099   __ Push(rcx);  // Enumeration cache.
1100   __ Push(rdx);  // Number of valid entries for the map in the enum cache.
1101   __ Push(Smi::FromInt(0));  // Initial index.
1102   __ jmp(&loop);
1103
1104   __ bind(&no_descriptors);
1105   __ addp(rsp, Immediate(kPointerSize));
1106   __ jmp(&exit);
1107
1108   // We got a fixed array in register rax. Iterate through that.
1109   Label non_proxy;
1110   __ bind(&fixed_array);
1111
1112   // No need for a write barrier, we are storing a Smi in the feedback vector.
1113   __ Move(rbx, FeedbackVector());
1114   int vector_index = FeedbackVector()->GetIndex(slot);
1115   __ Move(FieldOperand(rbx, FixedArray::OffsetOfElementAt(vector_index)),
1116           TypeFeedbackVector::MegamorphicSentinel(isolate()));
1117   __ Move(rbx, Smi::FromInt(1));  // Smi indicates slow check
1118   __ movp(rcx, Operand(rsp, 0 * kPointerSize));  // Get enumerated object
1119   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1120   __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx);
1121   __ j(above, &non_proxy);
1122   __ Move(rbx, Smi::FromInt(0));  // Zero indicates proxy
1123   __ bind(&non_proxy);
1124   __ Push(rbx);  // Smi
1125   __ Push(rax);  // Array
1126   __ movp(rax, FieldOperand(rax, FixedArray::kLengthOffset));
1127   __ Push(rax);  // Fixed array length (as smi).
1128   __ Push(Smi::FromInt(0));  // Initial index.
1129
1130   // Generate code for doing the condition check.
1131   PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1132   __ bind(&loop);
1133   SetExpressionAsStatementPosition(stmt->each());
1134
1135   __ movp(rax, Operand(rsp, 0 * kPointerSize));  // Get the current index.
1136   __ cmpp(rax, Operand(rsp, 1 * kPointerSize));  // Compare to the array length.
1137   __ j(above_equal, loop_statement.break_label());
1138
1139   // Get the current entry of the array into register rbx.
1140   __ movp(rbx, Operand(rsp, 2 * kPointerSize));
1141   SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2);
1142   __ movp(rbx, FieldOperand(rbx,
1143                             index.reg,
1144                             index.scale,
1145                             FixedArray::kHeaderSize));
1146
1147   // Get the expected map from the stack or a smi in the
1148   // permanent slow case into register rdx.
1149   __ movp(rdx, Operand(rsp, 3 * kPointerSize));
1150
1151   // Check if the expected map still matches that of the enumerable.
1152   // If not, we may have to filter the key.
1153   Label update_each;
1154   __ movp(rcx, Operand(rsp, 4 * kPointerSize));
1155   __ cmpp(rdx, FieldOperand(rcx, HeapObject::kMapOffset));
1156   __ j(equal, &update_each, Label::kNear);
1157
1158   // For proxies, no filtering is done.
1159   // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
1160   __ Cmp(rdx, Smi::FromInt(0));
1161   __ j(equal, &update_each, Label::kNear);
1162
1163   // Convert the entry to a string or null if it isn't a property
1164   // anymore. If the property has been removed while iterating, we
1165   // just skip it.
1166   __ Push(rcx);  // Enumerable.
1167   __ Push(rbx);  // Current entry.
1168   __ CallRuntime(Runtime::kForInFilter, 2);
1169   PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
1170   __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
1171   __ j(equal, loop_statement.continue_label());
1172   __ movp(rbx, rax);
1173
1174   // Update the 'each' property or variable from the possibly filtered
1175   // entry in register rbx.
1176   __ bind(&update_each);
1177   __ movp(result_register(), rbx);
1178   // Perform the assignment as if via '='.
1179   { EffectContext context(this);
1180     EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
1181     PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
1182   }
1183
1184   // Generate code for the body of the loop.
1185   Visit(stmt->body());
1186
1187   // Generate code for going to the next element by incrementing the
1188   // index (smi) stored on top of the stack.
1189   __ bind(loop_statement.continue_label());
1190   __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1));
1191
1192   EmitBackEdgeBookkeeping(stmt, &loop);
1193   __ jmp(&loop);
1194
1195   // Remove the pointers stored on the stack.
1196   __ bind(loop_statement.break_label());
1197   __ addp(rsp, Immediate(5 * kPointerSize));
1198
1199   // Exit and decrement the loop depth.
1200   PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1201   __ bind(&exit);
1202   decrement_loop_depth();
1203 }
1204
1205
1206 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
1207                                        bool pretenure) {
1208   // Use the fast case closure allocation code that allocates in new
1209   // space for nested functions that don't need literals cloning. If
1210   // we're running with the --always-opt or the --prepare-always-opt
1211   // flag, we need to use the runtime function so that the new function
1212   // we are creating here gets a chance to have its code optimized and
1213   // doesn't just get a copy of the existing unoptimized code.
1214   if (!FLAG_always_opt &&
1215       !FLAG_prepare_always_opt &&
1216       !pretenure &&
1217       scope()->is_function_scope() &&
1218       info->num_literals() == 0) {
1219     FastNewClosureStub stub(isolate(), info->language_mode(), info->kind());
1220     __ Move(rbx, info);
1221     __ CallStub(&stub);
1222   } else {
1223     __ Push(rsi);
1224     __ Push(info);
1225     __ Push(pretenure
1226             ? isolate()->factory()->true_value()
1227             : isolate()->factory()->false_value());
1228     __ CallRuntime(Runtime::kNewClosure, 3);
1229   }
1230   context()->Plug(rax);
1231 }
1232
1233
1234 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
1235                                                   int offset,
1236                                                   FeedbackVectorICSlot slot) {
1237   if (NeedsHomeObject(initializer)) {
1238     __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
1239     __ Move(StoreDescriptor::NameRegister(),
1240             isolate()->factory()->home_object_symbol());
1241     __ movp(StoreDescriptor::ValueRegister(),
1242             Operand(rsp, offset * kPointerSize));
1243     if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
1244     CallStoreIC();
1245   }
1246 }
1247
1248
1249 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
1250                                                       TypeofMode typeof_mode,
1251                                                       Label* slow) {
1252   Register context = rsi;
1253   Register temp = rdx;
1254
1255   Scope* s = scope();
1256   while (s != NULL) {
1257     if (s->num_heap_slots() > 0) {
1258       if (s->calls_sloppy_eval()) {
1259         // Check that extension is NULL.
1260         __ cmpp(ContextOperand(context, Context::EXTENSION_INDEX),
1261                 Immediate(0));
1262         __ j(not_equal, slow);
1263       }
1264       // Load next context in chain.
1265       __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1266       // Walk the rest of the chain without clobbering rsi.
1267       context = temp;
1268     }
1269     // If no outer scope calls eval, we do not need to check more
1270     // context extensions.  If we have reached an eval scope, we check
1271     // all extensions from this point.
1272     if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
1273     s = s->outer_scope();
1274   }
1275
1276   if (s != NULL && s->is_eval_scope()) {
1277     // Loop up the context chain.  There is no frame effect so it is
1278     // safe to use raw labels here.
1279     Label next, fast;
1280     if (!context.is(temp)) {
1281       __ movp(temp, context);
1282     }
1283     // Load map for comparison into register, outside loop.
1284     __ LoadRoot(kScratchRegister, Heap::kNativeContextMapRootIndex);
1285     __ bind(&next);
1286     // Terminate at native context.
1287     __ cmpp(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset));
1288     __ j(equal, &fast, Label::kNear);
1289     // Check that extension is NULL.
1290     __ cmpp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
1291     __ j(not_equal, slow);
1292     // Load next context in chain.
1293     __ movp(temp, ContextOperand(temp, Context::PREVIOUS_INDEX));
1294     __ jmp(&next);
1295     __ bind(&fast);
1296   }
1297
1298   // All extension objects were empty and it is safe to use a normal global
1299   // load machinery.
1300   EmitGlobalVariableLoad(proxy, typeof_mode);
1301 }
1302
1303
1304 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1305                                                                 Label* slow) {
1306   DCHECK(var->IsContextSlot());
1307   Register context = rsi;
1308   Register temp = rbx;
1309
1310   for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
1311     if (s->num_heap_slots() > 0) {
1312       if (s->calls_sloppy_eval()) {
1313         // Check that extension is NULL.
1314         __ cmpp(ContextOperand(context, Context::EXTENSION_INDEX),
1315                 Immediate(0));
1316         __ j(not_equal, slow);
1317       }
1318       __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1319       // Walk the rest of the chain without clobbering rsi.
1320       context = temp;
1321     }
1322   }
1323   // Check that last extension is NULL.
1324   __ cmpp(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
1325   __ j(not_equal, slow);
1326
1327   // This function is used only for loads, not stores, so it's safe to
1328   // return an rsi-based operand (the write barrier cannot be allowed to
1329   // destroy the rsi register).
1330   return ContextOperand(context, var->index());
1331 }
1332
1333
1334 void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
1335                                                   TypeofMode typeof_mode,
1336                                                   Label* slow, Label* done) {
1337   // Generate fast-case code for variables that might be shadowed by
1338   // eval-introduced variables.  Eval is used a lot without
1339   // introducing variables.  In those cases, we do not want to
1340   // perform a runtime call for all variables in the scope
1341   // containing the eval.
1342   Variable* var = proxy->var();
1343   if (var->mode() == DYNAMIC_GLOBAL) {
1344     EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow);
1345     __ jmp(done);
1346   } else if (var->mode() == DYNAMIC_LOCAL) {
1347     Variable* local = var->local_if_not_shadowed();
1348     __ movp(rax, ContextSlotOperandCheckExtensions(local, slow));
1349     if (local->mode() == LET || local->mode() == CONST ||
1350         local->mode() == CONST_LEGACY) {
1351       __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1352       __ j(not_equal, done);
1353       if (local->mode() == CONST_LEGACY) {
1354         __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1355       } else {  // LET || CONST
1356         __ Push(var->name());
1357         __ CallRuntime(Runtime::kThrowReferenceError, 1);
1358       }
1359     }
1360     __ jmp(done);
1361   }
1362 }
1363
1364
1365 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
1366                                                TypeofMode typeof_mode) {
1367   Variable* var = proxy->var();
1368   DCHECK(var->IsUnallocatedOrGlobalSlot() ||
1369          (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
1370   if (var->IsGlobalSlot()) {
1371     DCHECK(var->index() > 0);
1372     DCHECK(var->IsStaticGlobalObjectProperty());
1373     int const slot = var->index();
1374     int const depth = scope()->ContextChainLength(var->scope());
1375     if (depth <= LoadGlobalViaContextStub::kMaximumDepth) {
1376       __ Set(LoadGlobalViaContextDescriptor::SlotRegister(), slot);
1377       LoadGlobalViaContextStub stub(isolate(), depth);
1378       __ CallStub(&stub);
1379     } else {
1380       __ Push(Smi::FromInt(slot));
1381       __ CallRuntime(Runtime::kLoadGlobalViaContext, 1);
1382     }
1383
1384   } else {
1385     __ Move(LoadDescriptor::NameRegister(), var->name());
1386     __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
1387     __ Move(LoadDescriptor::SlotRegister(),
1388             SmiFromSlot(proxy->VariableFeedbackSlot()));
1389     CallLoadIC(typeof_mode);
1390   }
1391 }
1392
1393
1394 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
1395                                          TypeofMode typeof_mode) {
1396   // Record position before possible IC call.
1397   SetExpressionPosition(proxy);
1398   PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
1399   Variable* var = proxy->var();
1400
1401   // Three cases: global variables, lookup variables, and all other types of
1402   // variables.
1403   switch (var->location()) {
1404     case VariableLocation::GLOBAL:
1405     case VariableLocation::UNALLOCATED: {
1406       Comment cmnt(masm_, "[ Global variable");
1407       EmitGlobalVariableLoad(proxy, typeof_mode);
1408       context()->Plug(rax);
1409       break;
1410     }
1411
1412     case VariableLocation::PARAMETER:
1413     case VariableLocation::LOCAL:
1414     case VariableLocation::CONTEXT: {
1415       DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode);
1416       Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot"
1417                                                : "[ Stack slot");
1418       if (var->binding_needs_init()) {
1419         // var->scope() may be NULL when the proxy is located in eval code and
1420         // refers to a potential outside binding. Currently those bindings are
1421         // always looked up dynamically, i.e. in that case
1422         //     var->location() == LOOKUP.
1423         // always holds.
1424         DCHECK(var->scope() != NULL);
1425
1426         // Check if the binding really needs an initialization check. The check
1427         // can be skipped in the following situation: we have a LET or CONST
1428         // binding in harmony mode, both the Variable and the VariableProxy have
1429         // the same declaration scope (i.e. they are both in global code, in the
1430         // same function or in the same eval code) and the VariableProxy is in
1431         // the source physically located after the initializer of the variable.
1432         //
1433         // We cannot skip any initialization checks for CONST in non-harmony
1434         // mode because const variables may be declared but never initialized:
1435         //   if (false) { const x; }; var y = x;
1436         //
1437         // The condition on the declaration scopes is a conservative check for
1438         // nested functions that access a binding and are called before the
1439         // binding is initialized:
1440         //   function() { f(); let x = 1; function f() { x = 2; } }
1441         //
1442         bool skip_init_check;
1443         if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
1444           skip_init_check = false;
1445         } else if (var->is_this()) {
1446           CHECK(info_->function() != nullptr &&
1447                 (info_->function()->kind() & kSubclassConstructor) != 0);
1448           // TODO(dslomov): implement 'this' hole check elimination.
1449           skip_init_check = false;
1450         } else {
1451           // Check that we always have valid source position.
1452           DCHECK(var->initializer_position() != RelocInfo::kNoPosition);
1453           DCHECK(proxy->position() != RelocInfo::kNoPosition);
1454           skip_init_check = var->mode() != CONST_LEGACY &&
1455               var->initializer_position() < proxy->position();
1456         }
1457
1458         if (!skip_init_check) {
1459           // Let and const need a read barrier.
1460           Label done;
1461           GetVar(rax, var);
1462           __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1463           __ j(not_equal, &done, Label::kNear);
1464           if (var->mode() == LET || var->mode() == CONST) {
1465             // Throw a reference error when using an uninitialized let/const
1466             // binding in harmony mode.
1467             __ Push(var->name());
1468             __ CallRuntime(Runtime::kThrowReferenceError, 1);
1469           } else {
1470             // Uninitalized const bindings outside of harmony mode are unholed.
1471             DCHECK(var->mode() == CONST_LEGACY);
1472             __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1473           }
1474           __ bind(&done);
1475           context()->Plug(rax);
1476           break;
1477         }
1478       }
1479       context()->Plug(var);
1480       break;
1481     }
1482
1483     case VariableLocation::LOOKUP: {
1484       Comment cmnt(masm_, "[ Lookup slot");
1485       Label done, slow;
1486       // Generate code for loading from variables potentially shadowed
1487       // by eval-introduced variables.
1488       EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done);
1489       __ bind(&slow);
1490       __ Push(rsi);  // Context.
1491       __ Push(var->name());
1492       Runtime::FunctionId function_id =
1493           typeof_mode == NOT_INSIDE_TYPEOF
1494               ? Runtime::kLoadLookupSlot
1495               : Runtime::kLoadLookupSlotNoReferenceError;
1496       __ CallRuntime(function_id, 2);
1497       __ bind(&done);
1498       context()->Plug(rax);
1499       break;
1500     }
1501   }
1502 }
1503
1504
1505 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1506   Comment cmnt(masm_, "[ RegExpLiteral");
1507   Label materialized;
1508   // Registers will be used as follows:
1509   // rdi = JS function.
1510   // rcx = literals array.
1511   // rbx = regexp literal.
1512   // rax = regexp literal clone.
1513   __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1514   __ movp(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
1515   int literal_offset =
1516       FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1517   __ movp(rbx, FieldOperand(rcx, literal_offset));
1518   __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
1519   __ j(not_equal, &materialized, Label::kNear);
1520
1521   // Create regexp literal using runtime function
1522   // Result will be in rax.
1523   __ Push(rcx);
1524   __ Push(Smi::FromInt(expr->literal_index()));
1525   __ Push(expr->pattern());
1526   __ Push(expr->flags());
1527   __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1528   __ movp(rbx, rax);
1529
1530   __ bind(&materialized);
1531   int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1532   Label allocated, runtime_allocate;
1533   __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
1534   __ jmp(&allocated);
1535
1536   __ bind(&runtime_allocate);
1537   __ Push(rbx);
1538   __ Push(Smi::FromInt(size));
1539   __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1540   __ Pop(rbx);
1541
1542   __ bind(&allocated);
1543   // Copy the content into the newly allocated memory.
1544   // (Unroll copy loop once for better throughput).
1545   for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
1546     __ movp(rdx, FieldOperand(rbx, i));
1547     __ movp(rcx, FieldOperand(rbx, i + kPointerSize));
1548     __ movp(FieldOperand(rax, i), rdx);
1549     __ movp(FieldOperand(rax, i + kPointerSize), rcx);
1550   }
1551   if ((size % (2 * kPointerSize)) != 0) {
1552     __ movp(rdx, FieldOperand(rbx, size - kPointerSize));
1553     __ movp(FieldOperand(rax, size - kPointerSize), rdx);
1554   }
1555   context()->Plug(rax);
1556 }
1557
1558
1559 void FullCodeGenerator::EmitAccessor(Expression* expression) {
1560   if (expression == NULL) {
1561     __ PushRoot(Heap::kNullValueRootIndex);
1562   } else {
1563     VisitForStackValue(expression);
1564   }
1565 }
1566
1567
1568 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1569   Comment cmnt(masm_, "[ ObjectLiteral");
1570
1571   Handle<FixedArray> constant_properties = expr->constant_properties();
1572   int flags = expr->ComputeFlags();
1573   if (MustCreateObjectLiteralWithRuntime(expr)) {
1574     __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1575     __ Push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
1576     __ Push(Smi::FromInt(expr->literal_index()));
1577     __ Push(constant_properties);
1578     __ Push(Smi::FromInt(flags));
1579     __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
1580   } else {
1581     __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1582     __ movp(rax, FieldOperand(rdi, JSFunction::kLiteralsOffset));
1583     __ Move(rbx, Smi::FromInt(expr->literal_index()));
1584     __ Move(rcx, constant_properties);
1585     __ Move(rdx, Smi::FromInt(flags));
1586     FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
1587     __ CallStub(&stub);
1588   }
1589   PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
1590
1591   // If result_saved is true the result is on top of the stack.  If
1592   // result_saved is false the result is in rax.
1593   bool result_saved = false;
1594
1595   AccessorTable accessor_table(zone());
1596   int property_index = 0;
1597   // store_slot_index points to the vector IC slot for the next store IC used.
1598   // ObjectLiteral::ComputeFeedbackRequirements controls the allocation of slots
1599   // and must be updated if the number of store ICs emitted here changes.
1600   int store_slot_index = 0;
1601   for (; property_index < expr->properties()->length(); property_index++) {
1602     ObjectLiteral::Property* property = expr->properties()->at(property_index);
1603     if (property->is_computed_name()) break;
1604     if (property->IsCompileTimeValue()) continue;
1605
1606     Literal* key = property->key()->AsLiteral();
1607     Expression* value = property->value();
1608     if (!result_saved) {
1609       __ Push(rax);  // Save result on the stack
1610       result_saved = true;
1611     }
1612     switch (property->kind()) {
1613       case ObjectLiteral::Property::CONSTANT:
1614         UNREACHABLE();
1615       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1616         DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
1617         // Fall through.
1618       case ObjectLiteral::Property::COMPUTED:
1619         // It is safe to use [[Put]] here because the boilerplate already
1620         // contains computed properties with an uninitialized value.
1621         if (key->value()->IsInternalizedString()) {
1622           if (property->emit_store()) {
1623             VisitForAccumulatorValue(value);
1624             DCHECK(StoreDescriptor::ValueRegister().is(rax));
1625             __ Move(StoreDescriptor::NameRegister(), key->value());
1626             __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
1627             if (FLAG_vector_stores) {
1628               EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
1629               CallStoreIC();
1630             } else {
1631               CallStoreIC(key->LiteralFeedbackId());
1632             }
1633             PrepareForBailoutForId(key->id(), NO_REGISTERS);
1634
1635             if (NeedsHomeObject(value)) {
1636               __ movp(StoreDescriptor::ReceiverRegister(), rax);
1637               __ Move(StoreDescriptor::NameRegister(),
1638                       isolate()->factory()->home_object_symbol());
1639               __ movp(StoreDescriptor::ValueRegister(), Operand(rsp, 0));
1640               if (FLAG_vector_stores) {
1641                 EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
1642               }
1643               CallStoreIC();
1644             }
1645           } else {
1646             VisitForEffect(value);
1647           }
1648           break;
1649         }
1650         __ Push(Operand(rsp, 0));  // Duplicate receiver.
1651         VisitForStackValue(key);
1652         VisitForStackValue(value);
1653         if (property->emit_store()) {
1654           EmitSetHomeObjectIfNeeded(
1655               value, 2, expr->SlotForHomeObject(value, &store_slot_index));
1656           __ Push(Smi::FromInt(SLOPPY));  // Language mode
1657           __ CallRuntime(Runtime::kSetProperty, 4);
1658         } else {
1659           __ Drop(3);
1660         }
1661         break;
1662       case ObjectLiteral::Property::PROTOTYPE:
1663         __ Push(Operand(rsp, 0));  // Duplicate receiver.
1664         VisitForStackValue(value);
1665         DCHECK(property->emit_store());
1666         __ CallRuntime(Runtime::kInternalSetPrototype, 2);
1667         break;
1668       case ObjectLiteral::Property::GETTER:
1669         if (property->emit_store()) {
1670           accessor_table.lookup(key)->second->getter = value;
1671         }
1672         break;
1673       case ObjectLiteral::Property::SETTER:
1674         if (property->emit_store()) {
1675           accessor_table.lookup(key)->second->setter = value;
1676         }
1677         break;
1678     }
1679   }
1680
1681   // Emit code to define accessors, using only a single call to the runtime for
1682   // each pair of corresponding getters and setters.
1683   for (AccessorTable::Iterator it = accessor_table.begin();
1684        it != accessor_table.end();
1685        ++it) {
1686     __ Push(Operand(rsp, 0));  // Duplicate receiver.
1687     VisitForStackValue(it->first);
1688     EmitAccessor(it->second->getter);
1689     EmitSetHomeObjectIfNeeded(
1690         it->second->getter, 2,
1691         expr->SlotForHomeObject(it->second->getter, &store_slot_index));
1692     EmitAccessor(it->second->setter);
1693     EmitSetHomeObjectIfNeeded(
1694         it->second->setter, 3,
1695         expr->SlotForHomeObject(it->second->setter, &store_slot_index));
1696     __ Push(Smi::FromInt(NONE));
1697     __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
1698   }
1699
1700   // Object literals have two parts. The "static" part on the left contains no
1701   // computed property names, and so we can compute its map ahead of time; see
1702   // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part
1703   // starts with the first computed property name, and continues with all
1704   // properties to its right.  All the code from above initializes the static
1705   // component of the object literal, and arranges for the map of the result to
1706   // reflect the static order in which the keys appear. For the dynamic
1707   // properties, we compile them into a series of "SetOwnProperty" runtime
1708   // calls. This will preserve insertion order.
1709   for (; property_index < expr->properties()->length(); property_index++) {
1710     ObjectLiteral::Property* property = expr->properties()->at(property_index);
1711
1712     Expression* value = property->value();
1713     if (!result_saved) {
1714       __ Push(rax);  // Save result on the stack
1715       result_saved = true;
1716     }
1717
1718     __ Push(Operand(rsp, 0));  // Duplicate receiver.
1719
1720     if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1721       DCHECK(!property->is_computed_name());
1722       VisitForStackValue(value);
1723       DCHECK(property->emit_store());
1724       __ CallRuntime(Runtime::kInternalSetPrototype, 2);
1725     } else {
1726       EmitPropertyKey(property, expr->GetIdForProperty(property_index));
1727       VisitForStackValue(value);
1728       EmitSetHomeObjectIfNeeded(
1729           value, 2, expr->SlotForHomeObject(value, &store_slot_index));
1730
1731       switch (property->kind()) {
1732         case ObjectLiteral::Property::CONSTANT:
1733         case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1734         case ObjectLiteral::Property::COMPUTED:
1735           if (property->emit_store()) {
1736             __ Push(Smi::FromInt(NONE));
1737             __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4);
1738           } else {
1739             __ Drop(3);
1740           }
1741           break;
1742
1743         case ObjectLiteral::Property::PROTOTYPE:
1744           UNREACHABLE();
1745           break;
1746
1747         case ObjectLiteral::Property::GETTER:
1748           __ Push(Smi::FromInt(NONE));
1749           __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4);
1750           break;
1751
1752         case ObjectLiteral::Property::SETTER:
1753           __ Push(Smi::FromInt(NONE));
1754           __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4);
1755           break;
1756       }
1757     }
1758   }
1759
1760   if (expr->has_function()) {
1761     DCHECK(result_saved);
1762     __ Push(Operand(rsp, 0));
1763     __ CallRuntime(Runtime::kToFastProperties, 1);
1764   }
1765
1766   if (result_saved) {
1767     context()->PlugTOS();
1768   } else {
1769     context()->Plug(rax);
1770   }
1771
1772   // Verify that compilation exactly consumed the number of store ic slots that
1773   // the ObjectLiteral node had to offer.
1774   DCHECK(!FLAG_vector_stores || store_slot_index == expr->slot_count());
1775 }
1776
1777
1778 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1779   Comment cmnt(masm_, "[ ArrayLiteral");
1780
1781   expr->BuildConstantElements(isolate());
1782   Handle<FixedArray> constant_elements = expr->constant_elements();
1783   bool has_constant_fast_elements =
1784       IsFastObjectElementsKind(expr->constant_elements_kind());
1785
1786   AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1787   if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
1788     // If the only customer of allocation sites is transitioning, then
1789     // we can turn it off if we don't have anywhere else to transition to.
1790     allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1791   }
1792
1793   if (MustCreateArrayLiteralWithRuntime(expr)) {
1794     __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1795     __ Push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
1796     __ Push(Smi::FromInt(expr->literal_index()));
1797     __ Push(constant_elements);
1798     __ Push(Smi::FromInt(expr->ComputeFlags()));
1799     __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
1800   } else {
1801     __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1802     __ movp(rax, FieldOperand(rbx, JSFunction::kLiteralsOffset));
1803     __ Move(rbx, Smi::FromInt(expr->literal_index()));
1804     __ Move(rcx, constant_elements);
1805     FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
1806     __ CallStub(&stub);
1807   }
1808   PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
1809
1810   bool result_saved = false;  // Is the result saved to the stack?
1811   ZoneList<Expression*>* subexprs = expr->values();
1812   int length = subexprs->length();
1813
1814   // Emit code to evaluate all the non-constant subexpressions and to store
1815   // them into the newly cloned array.
1816   int array_index = 0;
1817   for (; array_index < length; array_index++) {
1818     Expression* subexpr = subexprs->at(array_index);
1819     if (subexpr->IsSpread()) break;
1820
1821     // If the subexpression is a literal or a simple materialized literal it
1822     // is already set in the cloned array.
1823     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1824
1825     if (!result_saved) {
1826       __ Push(rax);  // array literal
1827       __ Push(Smi::FromInt(expr->literal_index()));
1828       result_saved = true;
1829     }
1830     VisitForAccumulatorValue(subexpr);
1831
1832     if (has_constant_fast_elements) {
1833       // Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
1834       // cannot transition and don't need to call the runtime stub.
1835       int offset = FixedArray::kHeaderSize + (array_index * kPointerSize);
1836       __ movp(rbx, Operand(rsp, kPointerSize));  // Copy of array literal.
1837       __ movp(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
1838       // Store the subexpression value in the array's elements.
1839       __ movp(FieldOperand(rbx, offset), result_register());
1840       // Update the write barrier for the array store.
1841       __ RecordWriteField(rbx, offset, result_register(), rcx,
1842                           kDontSaveFPRegs,
1843                           EMIT_REMEMBERED_SET,
1844                           INLINE_SMI_CHECK);
1845     } else {
1846       // Store the subexpression value in the array's elements.
1847       __ Move(rcx, Smi::FromInt(array_index));
1848       StoreArrayLiteralElementStub stub(isolate());
1849       __ CallStub(&stub);
1850     }
1851
1852     PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
1853   }
1854
1855   // In case the array literal contains spread expressions it has two parts. The
1856   // first part is  the "static" array which has a literal index is  handled
1857   // above. The second part is the part after the first spread expression
1858   // (inclusive) and these elements gets appended to the array. Note that the
1859   // number elements an iterable produces is unknown ahead of time.
1860   if (array_index < length && result_saved) {
1861     __ Drop(1);  // literal index
1862     __ Pop(rax);
1863     result_saved = false;
1864   }
1865   for (; array_index < length; array_index++) {
1866     Expression* subexpr = subexprs->at(array_index);
1867
1868     __ Push(rax);
1869     if (subexpr->IsSpread()) {
1870       VisitForStackValue(subexpr->AsSpread()->expression());
1871       __ InvokeBuiltin(Builtins::CONCAT_ITERABLE_TO_ARRAY, CALL_FUNCTION);
1872     } else {
1873       VisitForStackValue(subexpr);
1874       __ CallRuntime(Runtime::kAppendElement, 2);
1875     }
1876
1877     PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
1878   }
1879
1880   if (result_saved) {
1881     __ Drop(1);  // literal index
1882     context()->PlugTOS();
1883   } else {
1884     context()->Plug(rax);
1885   }
1886 }
1887
1888
1889 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1890   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
1891
1892   Comment cmnt(masm_, "[ Assignment");
1893   SetExpressionPosition(expr, INSERT_BREAK);
1894
1895   Property* property = expr->target()->AsProperty();
1896   LhsKind assign_type = Property::GetAssignType(property);
1897
1898   // Evaluate LHS expression.
1899   switch (assign_type) {
1900     case VARIABLE:
1901       // Nothing to do here.
1902       break;
1903     case NAMED_PROPERTY:
1904       if (expr->is_compound()) {
1905         // We need the receiver both on the stack and in the register.
1906         VisitForStackValue(property->obj());
1907         __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
1908       } else {
1909         VisitForStackValue(property->obj());
1910       }
1911       break;
1912     case NAMED_SUPER_PROPERTY:
1913       VisitForStackValue(
1914           property->obj()->AsSuperPropertyReference()->this_var());
1915       VisitForAccumulatorValue(
1916           property->obj()->AsSuperPropertyReference()->home_object());
1917       __ Push(result_register());
1918       if (expr->is_compound()) {
1919         __ Push(MemOperand(rsp, kPointerSize));
1920         __ Push(result_register());
1921       }
1922       break;
1923     case KEYED_SUPER_PROPERTY:
1924       VisitForStackValue(
1925           property->obj()->AsSuperPropertyReference()->this_var());
1926       VisitForStackValue(
1927           property->obj()->AsSuperPropertyReference()->home_object());
1928       VisitForAccumulatorValue(property->key());
1929       __ Push(result_register());
1930       if (expr->is_compound()) {
1931         __ Push(MemOperand(rsp, 2 * kPointerSize));
1932         __ Push(MemOperand(rsp, 2 * kPointerSize));
1933         __ Push(result_register());
1934       }
1935       break;
1936     case KEYED_PROPERTY: {
1937       if (expr->is_compound()) {
1938         VisitForStackValue(property->obj());
1939         VisitForStackValue(property->key());
1940         __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize));
1941         __ movp(LoadDescriptor::NameRegister(), Operand(rsp, 0));
1942       } else {
1943         VisitForStackValue(property->obj());
1944         VisitForStackValue(property->key());
1945       }
1946       break;
1947     }
1948   }
1949
1950   // For compound assignments we need another deoptimization point after the
1951   // variable/property load.
1952   if (expr->is_compound()) {
1953     { AccumulatorValueContext context(this);
1954       switch (assign_type) {
1955         case VARIABLE:
1956           EmitVariableLoad(expr->target()->AsVariableProxy());
1957           PrepareForBailout(expr->target(), TOS_REG);
1958           break;
1959         case NAMED_PROPERTY:
1960           EmitNamedPropertyLoad(property);
1961           PrepareForBailoutForId(property->LoadId(), TOS_REG);
1962           break;
1963         case NAMED_SUPER_PROPERTY:
1964           EmitNamedSuperPropertyLoad(property);
1965           PrepareForBailoutForId(property->LoadId(), TOS_REG);
1966           break;
1967         case KEYED_SUPER_PROPERTY:
1968           EmitKeyedSuperPropertyLoad(property);
1969           PrepareForBailoutForId(property->LoadId(), TOS_REG);
1970           break;
1971         case KEYED_PROPERTY:
1972           EmitKeyedPropertyLoad(property);
1973           PrepareForBailoutForId(property->LoadId(), TOS_REG);
1974           break;
1975       }
1976     }
1977
1978     Token::Value op = expr->binary_op();
1979     __ Push(rax);  // Left operand goes on the stack.
1980     VisitForAccumulatorValue(expr->value());
1981
1982     AccumulatorValueContext context(this);
1983     if (ShouldInlineSmiCase(op)) {
1984       EmitInlineSmiBinaryOp(expr->binary_operation(),
1985                             op,
1986                             expr->target(),
1987                             expr->value());
1988     } else {
1989       EmitBinaryOp(expr->binary_operation(), op);
1990     }
1991     // Deoptimization point in case the binary operation may have side effects.
1992     PrepareForBailout(expr->binary_operation(), TOS_REG);
1993   } else {
1994     VisitForAccumulatorValue(expr->value());
1995   }
1996
1997   SetExpressionPosition(expr);
1998
1999   // Store the value.
2000   switch (assign_type) {
2001     case VARIABLE:
2002       EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
2003                              expr->op(), expr->AssignmentSlot());
2004       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2005       context()->Plug(rax);
2006       break;
2007     case NAMED_PROPERTY:
2008       EmitNamedPropertyAssignment(expr);
2009       break;
2010     case NAMED_SUPER_PROPERTY:
2011       EmitNamedSuperPropertyStore(property);
2012       context()->Plug(rax);
2013       break;
2014     case KEYED_SUPER_PROPERTY:
2015       EmitKeyedSuperPropertyStore(property);
2016       context()->Plug(rax);
2017       break;
2018     case KEYED_PROPERTY:
2019       EmitKeyedPropertyAssignment(expr);
2020       break;
2021   }
2022 }
2023
2024
2025 void FullCodeGenerator::VisitYield(Yield* expr) {
2026   Comment cmnt(masm_, "[ Yield");
2027   SetExpressionPosition(expr);
2028
2029   // Evaluate yielded value first; the initial iterator definition depends on
2030   // this.  It stays on the stack while we update the iterator.
2031   VisitForStackValue(expr->expression());
2032
2033   switch (expr->yield_kind()) {
2034     case Yield::kSuspend:
2035       // Pop value from top-of-stack slot; box result into result register.
2036       EmitCreateIteratorResult(false);
2037       __ Push(result_register());
2038       // Fall through.
2039     case Yield::kInitial: {
2040       Label suspend, continuation, post_runtime, resume;
2041
2042       __ jmp(&suspend);
2043       __ bind(&continuation);
2044       __ RecordGeneratorContinuation();
2045       __ jmp(&resume);
2046
2047       __ bind(&suspend);
2048       VisitForAccumulatorValue(expr->generator_object());
2049       DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
2050       __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset),
2051               Smi::FromInt(continuation.pos()));
2052       __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi);
2053       __ movp(rcx, rsi);
2054       __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx,
2055                           kDontSaveFPRegs);
2056       __ leap(rbx, Operand(rbp, StandardFrameConstants::kExpressionsOffset));
2057       __ cmpp(rsp, rbx);
2058       __ j(equal, &post_runtime);
2059       __ Push(rax);  // generator object
2060       __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2061       __ movp(context_register(),
2062               Operand(rbp, StandardFrameConstants::kContextOffset));
2063       __ bind(&post_runtime);
2064
2065       __ Pop(result_register());
2066       EmitReturnSequence();
2067
2068       __ bind(&resume);
2069       context()->Plug(result_register());
2070       break;
2071     }
2072
2073     case Yield::kFinal: {
2074       VisitForAccumulatorValue(expr->generator_object());
2075       __ Move(FieldOperand(result_register(),
2076                            JSGeneratorObject::kContinuationOffset),
2077               Smi::FromInt(JSGeneratorObject::kGeneratorClosed));
2078       // Pop value from top-of-stack slot, box result into result register.
2079       EmitCreateIteratorResult(true);
2080       EmitUnwindBeforeReturn();
2081       EmitReturnSequence();
2082       break;
2083     }
2084
2085     case Yield::kDelegating: {
2086       VisitForStackValue(expr->generator_object());
2087
2088       // Initial stack layout is as follows:
2089       // [sp + 1 * kPointerSize] iter
2090       // [sp + 0 * kPointerSize] g
2091
2092       Label l_catch, l_try, l_suspend, l_continuation, l_resume;
2093       Label l_next, l_call, l_loop;
2094       Register load_receiver = LoadDescriptor::ReceiverRegister();
2095       Register load_name = LoadDescriptor::NameRegister();
2096
2097       // Initial send value is undefined.
2098       __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2099       __ jmp(&l_next);
2100
2101       // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
2102       __ bind(&l_catch);
2103       __ LoadRoot(load_name, Heap::kthrow_stringRootIndex);  // "throw"
2104       __ Push(load_name);
2105       __ Push(Operand(rsp, 2 * kPointerSize));               // iter
2106       __ Push(rax);                                          // exception
2107       __ jmp(&l_call);
2108
2109       // try { received = %yield result }
2110       // Shuffle the received result above a try handler and yield it without
2111       // re-boxing.
2112       __ bind(&l_try);
2113       __ Pop(rax);                                       // result
2114       int handler_index = NewHandlerTableEntry();
2115       EnterTryBlock(handler_index, &l_catch);
2116       const int try_block_size = TryCatch::kElementCount * kPointerSize;
2117       __ Push(rax);                                      // result
2118
2119       __ jmp(&l_suspend);
2120       __ bind(&l_continuation);
2121       __ RecordGeneratorContinuation();
2122       __ jmp(&l_resume);
2123
2124       __ bind(&l_suspend);
2125       const int generator_object_depth = kPointerSize + try_block_size;
2126       __ movp(rax, Operand(rsp, generator_object_depth));
2127       __ Push(rax);                                      // g
2128       __ Push(Smi::FromInt(handler_index));              // handler-index
2129       DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
2130       __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset),
2131               Smi::FromInt(l_continuation.pos()));
2132       __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi);
2133       __ movp(rcx, rsi);
2134       __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx,
2135                           kDontSaveFPRegs);
2136       __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 2);
2137       __ movp(context_register(),
2138               Operand(rbp, StandardFrameConstants::kContextOffset));
2139       __ Pop(rax);                                       // result
2140       EmitReturnSequence();
2141       __ bind(&l_resume);                                // received in rax
2142       ExitTryBlock(handler_index);
2143
2144       // receiver = iter; f = 'next'; arg = received;
2145       __ bind(&l_next);
2146
2147       __ LoadRoot(load_name, Heap::knext_stringRootIndex);
2148       __ Push(load_name);                           // "next"
2149       __ Push(Operand(rsp, 2 * kPointerSize));      // iter
2150       __ Push(rax);                                 // received
2151
2152       // result = receiver[f](arg);
2153       __ bind(&l_call);
2154       __ movp(load_receiver, Operand(rsp, kPointerSize));
2155       __ Move(LoadDescriptor::SlotRegister(),
2156               SmiFromSlot(expr->KeyedLoadFeedbackSlot()));
2157       Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code();
2158       CallIC(ic, TypeFeedbackId::None());
2159       __ movp(rdi, rax);
2160       __ movp(Operand(rsp, 2 * kPointerSize), rdi);
2161
2162       SetCallPosition(expr, 1);
2163       CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
2164       __ CallStub(&stub);
2165
2166       __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2167       __ Drop(1);  // The function is still on the stack; drop it.
2168
2169       // if (!result.done) goto l_try;
2170       __ bind(&l_loop);
2171       __ Move(load_receiver, rax);
2172       __ Push(load_receiver);                               // save result
2173       __ LoadRoot(load_name, Heap::kdone_stringRootIndex);  // "done"
2174       __ Move(LoadDescriptor::SlotRegister(),
2175               SmiFromSlot(expr->DoneFeedbackSlot()));
2176       CallLoadIC(NOT_INSIDE_TYPEOF);  // rax=result.done
2177       Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2178       CallIC(bool_ic);
2179       __ testp(result_register(), result_register());
2180       __ j(zero, &l_try);
2181
2182       // result.value
2183       __ Pop(load_receiver);                             // result
2184       __ LoadRoot(load_name, Heap::kvalue_stringRootIndex);  // "value"
2185       __ Move(LoadDescriptor::SlotRegister(),
2186               SmiFromSlot(expr->ValueFeedbackSlot()));
2187       CallLoadIC(NOT_INSIDE_TYPEOF);                     // result.value in rax
2188       context()->DropAndPlug(2, rax);                    // drop iter and g
2189       break;
2190     }
2191   }
2192 }
2193
2194
2195 void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
2196     Expression *value,
2197     JSGeneratorObject::ResumeMode resume_mode) {
2198   // The value stays in rax, and is ultimately read by the resumed generator, as
2199   // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
2200   // is read to throw the value when the resumed generator is already closed.
2201   // rbx will hold the generator object until the activation has been resumed.
2202   VisitForStackValue(generator);
2203   VisitForAccumulatorValue(value);
2204   __ Pop(rbx);
2205
2206   // Load suspended function and context.
2207   __ movp(rsi, FieldOperand(rbx, JSGeneratorObject::kContextOffset));
2208   __ movp(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset));
2209
2210   // Push receiver.
2211   __ Push(FieldOperand(rbx, JSGeneratorObject::kReceiverOffset));
2212
2213   // Push holes for arguments to generator function.
2214   __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
2215   __ LoadSharedFunctionInfoSpecialField(rdx, rdx,
2216       SharedFunctionInfo::kFormalParameterCountOffset);
2217   __ LoadRoot(rcx, Heap::kTheHoleValueRootIndex);
2218   Label push_argument_holes, push_frame;
2219   __ bind(&push_argument_holes);
2220   __ subp(rdx, Immediate(1));
2221   __ j(carry, &push_frame);
2222   __ Push(rcx);
2223   __ jmp(&push_argument_holes);
2224
2225   // Enter a new JavaScript frame, and initialize its slots as they were when
2226   // the generator was suspended.
2227   Label resume_frame, done;
2228   __ bind(&push_frame);
2229   __ call(&resume_frame);
2230   __ jmp(&done);
2231   __ bind(&resume_frame);
2232   __ pushq(rbp);  // Caller's frame pointer.
2233   __ movp(rbp, rsp);
2234   __ Push(rsi);  // Callee's context.
2235   __ Push(rdi);  // Callee's JS Function.
2236
2237   // Load the operand stack size.
2238   __ movp(rdx, FieldOperand(rbx, JSGeneratorObject::kOperandStackOffset));
2239   __ movp(rdx, FieldOperand(rdx, FixedArray::kLengthOffset));
2240   __ SmiToInteger32(rdx, rdx);
2241
2242   // If we are sending a value and there is no operand stack, we can jump back
2243   // in directly.
2244   if (resume_mode == JSGeneratorObject::NEXT) {
2245     Label slow_resume;
2246     __ cmpp(rdx, Immediate(0));
2247     __ j(not_zero, &slow_resume);
2248     __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
2249     __ SmiToInteger64(rcx,
2250         FieldOperand(rbx, JSGeneratorObject::kContinuationOffset));
2251     __ addp(rdx, rcx);
2252     __ Move(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset),
2253             Smi::FromInt(JSGeneratorObject::kGeneratorExecuting));
2254     __ jmp(rdx);
2255     __ bind(&slow_resume);
2256   }
2257
2258   // Otherwise, we push holes for the operand stack and call the runtime to fix
2259   // up the stack and the handlers.
2260   Label push_operand_holes, call_resume;
2261   __ bind(&push_operand_holes);
2262   __ subp(rdx, Immediate(1));
2263   __ j(carry, &call_resume);
2264   __ Push(rcx);
2265   __ jmp(&push_operand_holes);
2266   __ bind(&call_resume);
2267   __ Push(rbx);
2268   __ Push(result_register());
2269   __ Push(Smi::FromInt(resume_mode));
2270   __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3);
2271   // Not reached: the runtime call returns elsewhere.
2272   __ Abort(kGeneratorFailedToResume);
2273
2274   __ bind(&done);
2275   context()->Plug(result_register());
2276 }
2277
2278
2279 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
2280   Label gc_required;
2281   Label allocated;
2282
2283   const int instance_size = 5 * kPointerSize;
2284   DCHECK_EQ(isolate()->native_context()->iterator_result_map()->instance_size(),
2285             instance_size);
2286
2287   __ Allocate(instance_size, rax, rcx, rdx, &gc_required, TAG_OBJECT);
2288   __ jmp(&allocated);
2289
2290   __ bind(&gc_required);
2291   __ Push(Smi::FromInt(instance_size));
2292   __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2293   __ movp(context_register(),
2294           Operand(rbp, StandardFrameConstants::kContextOffset));
2295
2296   __ bind(&allocated);
2297   __ movp(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
2298   __ movp(rbx, FieldOperand(rbx, GlobalObject::kNativeContextOffset));
2299   __ movp(rbx, ContextOperand(rbx, Context::ITERATOR_RESULT_MAP_INDEX));
2300   __ Pop(rcx);
2301   __ Move(rdx, isolate()->factory()->ToBoolean(done));
2302   __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx);
2303   __ Move(FieldOperand(rax, JSObject::kPropertiesOffset),
2304           isolate()->factory()->empty_fixed_array());
2305   __ Move(FieldOperand(rax, JSObject::kElementsOffset),
2306           isolate()->factory()->empty_fixed_array());
2307   __ movp(FieldOperand(rax, JSGeneratorObject::kResultValuePropertyOffset),
2308           rcx);
2309   __ movp(FieldOperand(rax, JSGeneratorObject::kResultDonePropertyOffset),
2310           rdx);
2311
2312   // Only the value field needs a write barrier, as the other values are in the
2313   // root set.
2314   __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset,
2315                       rcx, rdx, kDontSaveFPRegs);
2316 }
2317
2318
2319 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
2320   SetExpressionPosition(prop);
2321   Literal* key = prop->key()->AsLiteral();
2322   DCHECK(!prop->IsSuperAccess());
2323
2324   __ Move(LoadDescriptor::NameRegister(), key->value());
2325   __ Move(LoadDescriptor::SlotRegister(),
2326           SmiFromSlot(prop->PropertyFeedbackSlot()));
2327   CallLoadIC(NOT_INSIDE_TYPEOF, language_mode());
2328 }
2329
2330
2331 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
2332   // Stack: receiver, home_object
2333   SetExpressionPosition(prop);
2334   Literal* key = prop->key()->AsLiteral();
2335   DCHECK(!key->value()->IsSmi());
2336   DCHECK(prop->IsSuperAccess());
2337
2338   __ Push(key->value());
2339   __ Push(Smi::FromInt(language_mode()));
2340   __ CallRuntime(Runtime::kLoadFromSuper, 4);
2341 }
2342
2343
2344 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
2345   SetExpressionPosition(prop);
2346   Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
2347   __ Move(LoadDescriptor::SlotRegister(),
2348           SmiFromSlot(prop->PropertyFeedbackSlot()));
2349   CallIC(ic);
2350 }
2351
2352
2353 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
2354   // Stack: receiver, home_object, key.
2355   SetExpressionPosition(prop);
2356   __ Push(Smi::FromInt(language_mode()));
2357   __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
2358 }
2359
2360
2361 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
2362                                               Token::Value op,
2363                                               Expression* left,
2364                                               Expression* right) {
2365   // Do combined smi check of the operands. Left operand is on the
2366   // stack (popped into rdx). Right operand is in rax but moved into
2367   // rcx to make the shifts easier.
2368   Label done, stub_call, smi_case;
2369   __ Pop(rdx);
2370   __ movp(rcx, rax);
2371   __ orp(rax, rdx);
2372   JumpPatchSite patch_site(masm_);
2373   patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear);
2374
2375   __ bind(&stub_call);
2376   __ movp(rax, rcx);
2377   Handle<Code> code =
2378       CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code();
2379   CallIC(code, expr->BinaryOperationFeedbackId());
2380   patch_site.EmitPatchInfo();
2381   __ jmp(&done, Label::kNear);
2382
2383   __ bind(&smi_case);
2384   switch (op) {
2385     case Token::SAR:
2386       __ SmiShiftArithmeticRight(rax, rdx, rcx);
2387       break;
2388     case Token::SHL:
2389       __ SmiShiftLeft(rax, rdx, rcx, &stub_call);
2390       break;
2391     case Token::SHR:
2392       __ SmiShiftLogicalRight(rax, rdx, rcx, &stub_call);
2393       break;
2394     case Token::ADD:
2395       __ SmiAdd(rax, rdx, rcx, &stub_call);
2396       break;
2397     case Token::SUB:
2398       __ SmiSub(rax, rdx, rcx, &stub_call);
2399       break;
2400     case Token::MUL:
2401       __ SmiMul(rax, rdx, rcx, &stub_call);
2402       break;
2403     case Token::BIT_OR:
2404       __ SmiOr(rax, rdx, rcx);
2405       break;
2406     case Token::BIT_AND:
2407       __ SmiAnd(rax, rdx, rcx);
2408       break;
2409     case Token::BIT_XOR:
2410       __ SmiXor(rax, rdx, rcx);
2411       break;
2412     default:
2413       UNREACHABLE();
2414       break;
2415   }
2416
2417   __ bind(&done);
2418   context()->Plug(rax);
2419 }
2420
2421
2422 void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
2423                                                   int* used_store_slots) {
2424   // Constructor is in rax.
2425   DCHECK(lit != NULL);
2426   __ Push(rax);
2427
2428   // No access check is needed here since the constructor is created by the
2429   // class literal.
2430   Register scratch = rbx;
2431   __ movp(scratch, FieldOperand(rax, JSFunction::kPrototypeOrInitialMapOffset));
2432   __ Push(scratch);
2433
2434   for (int i = 0; i < lit->properties()->length(); i++) {
2435     ObjectLiteral::Property* property = lit->properties()->at(i);
2436     Expression* value = property->value();
2437
2438     if (property->is_static()) {
2439       __ Push(Operand(rsp, kPointerSize));  // constructor
2440     } else {
2441       __ Push(Operand(rsp, 0));  // prototype
2442     }
2443     EmitPropertyKey(property, lit->GetIdForProperty(i));
2444
2445     // The static prototype property is read only. We handle the non computed
2446     // property name case in the parser. Since this is the only case where we
2447     // need to check for an own read only property we special case this so we do
2448     // not need to do this for every property.
2449     if (property->is_static() && property->is_computed_name()) {
2450       __ CallRuntime(Runtime::kThrowIfStaticPrototype, 1);
2451       __ Push(rax);
2452     }
2453
2454     VisitForStackValue(value);
2455     EmitSetHomeObjectIfNeeded(value, 2,
2456                               lit->SlotForHomeObject(value, used_store_slots));
2457
2458     switch (property->kind()) {
2459       case ObjectLiteral::Property::CONSTANT:
2460       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
2461       case ObjectLiteral::Property::PROTOTYPE:
2462         UNREACHABLE();
2463       case ObjectLiteral::Property::COMPUTED:
2464         __ CallRuntime(Runtime::kDefineClassMethod, 3);
2465         break;
2466
2467       case ObjectLiteral::Property::GETTER:
2468         __ Push(Smi::FromInt(DONT_ENUM));
2469         __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4);
2470         break;
2471
2472       case ObjectLiteral::Property::SETTER:
2473         __ Push(Smi::FromInt(DONT_ENUM));
2474         __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4);
2475         break;
2476
2477       default:
2478         UNREACHABLE();
2479     }
2480   }
2481
2482   // Set both the prototype and constructor to have fast properties, and also
2483   // freeze them in strong mode.
2484   __ CallRuntime(is_strong(language_mode())
2485                      ? Runtime::kFinalizeClassDefinitionStrong
2486                      : Runtime::kFinalizeClassDefinition,
2487                  2);
2488 }
2489
2490
2491 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
2492   __ Pop(rdx);
2493   Handle<Code> code =
2494       CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code();
2495   JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
2496   CallIC(code, expr->BinaryOperationFeedbackId());
2497   patch_site.EmitPatchInfo();
2498   context()->Plug(rax);
2499 }
2500
2501
2502 void FullCodeGenerator::EmitAssignment(Expression* expr,
2503                                        FeedbackVectorICSlot slot) {
2504   DCHECK(expr->IsValidReferenceExpressionOrThis());
2505
2506   Property* prop = expr->AsProperty();
2507   LhsKind assign_type = Property::GetAssignType(prop);
2508
2509   switch (assign_type) {
2510     case VARIABLE: {
2511       Variable* var = expr->AsVariableProxy()->var();
2512       EffectContext context(this);
2513       EmitVariableAssignment(var, Token::ASSIGN, slot);
2514       break;
2515     }
2516     case NAMED_PROPERTY: {
2517       __ Push(rax);  // Preserve value.
2518       VisitForAccumulatorValue(prop->obj());
2519       __ Move(StoreDescriptor::ReceiverRegister(), rax);
2520       __ Pop(StoreDescriptor::ValueRegister());  // Restore value.
2521       __ Move(StoreDescriptor::NameRegister(),
2522               prop->key()->AsLiteral()->value());
2523       if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
2524       CallStoreIC();
2525       break;
2526     }
2527     case NAMED_SUPER_PROPERTY: {
2528       __ Push(rax);
2529       VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
2530       VisitForAccumulatorValue(
2531           prop->obj()->AsSuperPropertyReference()->home_object());
2532       // stack: value, this; rax: home_object
2533       Register scratch = rcx;
2534       Register scratch2 = rdx;
2535       __ Move(scratch, result_register());               // home_object
2536       __ movp(rax, MemOperand(rsp, kPointerSize));       // value
2537       __ movp(scratch2, MemOperand(rsp, 0));             // this
2538       __ movp(MemOperand(rsp, kPointerSize), scratch2);  // this
2539       __ movp(MemOperand(rsp, 0), scratch);              // home_object
2540       // stack: this, home_object; rax: value
2541       EmitNamedSuperPropertyStore(prop);
2542       break;
2543     }
2544     case KEYED_SUPER_PROPERTY: {
2545       __ Push(rax);
2546       VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
2547       VisitForStackValue(
2548           prop->obj()->AsSuperPropertyReference()->home_object());
2549       VisitForAccumulatorValue(prop->key());
2550       Register scratch = rcx;
2551       Register scratch2 = rdx;
2552       __ movp(scratch2, MemOperand(rsp, 2 * kPointerSize));  // value
2553       // stack: value, this, home_object; rax: key, rdx: value
2554       __ movp(scratch, MemOperand(rsp, kPointerSize));  // this
2555       __ movp(MemOperand(rsp, 2 * kPointerSize), scratch);
2556       __ movp(scratch, MemOperand(rsp, 0));  // home_object
2557       __ movp(MemOperand(rsp, kPointerSize), scratch);
2558       __ movp(MemOperand(rsp, 0), rax);
2559       __ Move(rax, scratch2);
2560       // stack: this, home_object, key; rax: value.
2561       EmitKeyedSuperPropertyStore(prop);
2562       break;
2563     }
2564     case KEYED_PROPERTY: {
2565       __ Push(rax);  // Preserve value.
2566       VisitForStackValue(prop->obj());
2567       VisitForAccumulatorValue(prop->key());
2568       __ Move(StoreDescriptor::NameRegister(), rax);
2569       __ Pop(StoreDescriptor::ReceiverRegister());
2570       __ Pop(StoreDescriptor::ValueRegister());  // Restore value.
2571       if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
2572       Handle<Code> ic =
2573           CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
2574       CallIC(ic);
2575       break;
2576     }
2577   }
2578   context()->Plug(rax);
2579 }
2580
2581
2582 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2583     Variable* var, MemOperand location) {
2584   __ movp(location, rax);
2585   if (var->IsContextSlot()) {
2586     __ movp(rdx, rax);
2587     __ RecordWriteContextSlot(
2588         rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
2589   }
2590 }
2591
2592
2593 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
2594                                                FeedbackVectorICSlot slot) {
2595   if (var->IsUnallocated()) {
2596     // Global var, const, or let.
2597     __ Move(StoreDescriptor::NameRegister(), var->name());
2598     __ movp(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
2599     if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
2600     CallStoreIC();
2601
2602   } else if (var->IsGlobalSlot()) {
2603     // Global var, const, or let.
2604     DCHECK(var->index() > 0);
2605     DCHECK(var->IsStaticGlobalObjectProperty());
2606     int const slot = var->index();
2607     int const depth = scope()->ContextChainLength(var->scope());
2608     if (depth <= StoreGlobalViaContextStub::kMaximumDepth) {
2609       __ Set(StoreGlobalViaContextDescriptor::SlotRegister(), slot);
2610       DCHECK(StoreGlobalViaContextDescriptor::ValueRegister().is(rax));
2611       StoreGlobalViaContextStub stub(isolate(), depth, language_mode());
2612       __ CallStub(&stub);
2613     } else {
2614       __ Push(Smi::FromInt(slot));
2615       __ Push(rax);
2616       __ CallRuntime(is_strict(language_mode())
2617                          ? Runtime::kStoreGlobalViaContext_Strict
2618                          : Runtime::kStoreGlobalViaContext_Sloppy,
2619                      2);
2620     }
2621
2622   } else if (var->mode() == LET && op != Token::INIT_LET) {
2623     // Non-initializing assignment to let variable needs a write barrier.
2624     DCHECK(!var->IsLookupSlot());
2625     DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2626     Label assign;
2627     MemOperand location = VarOperand(var, rcx);
2628     __ movp(rdx, location);
2629     __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2630     __ j(not_equal, &assign, Label::kNear);
2631     __ Push(var->name());
2632     __ CallRuntime(Runtime::kThrowReferenceError, 1);
2633     __ bind(&assign);
2634     EmitStoreToStackLocalOrContextSlot(var, location);
2635
2636   } else if (var->mode() == CONST && op != Token::INIT_CONST) {
2637     // Assignment to const variable needs a write barrier.
2638     DCHECK(!var->IsLookupSlot());
2639     DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2640     Label const_error;
2641     MemOperand location = VarOperand(var, rcx);
2642     __ movp(rdx, location);
2643     __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2644     __ j(not_equal, &const_error, Label::kNear);
2645     __ Push(var->name());
2646     __ CallRuntime(Runtime::kThrowReferenceError, 1);
2647     __ bind(&const_error);
2648     __ CallRuntime(Runtime::kThrowConstAssignError, 0);
2649
2650   } else if (var->is_this() && op == Token::INIT_CONST) {
2651     // Initializing assignment to const {this} needs a write barrier.
2652     DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2653     Label uninitialized_this;
2654     MemOperand location = VarOperand(var, rcx);
2655     __ movp(rdx, location);
2656     __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2657     __ j(equal, &uninitialized_this);
2658     __ Push(var->name());
2659     __ CallRuntime(Runtime::kThrowReferenceError, 1);
2660     __ bind(&uninitialized_this);
2661     EmitStoreToStackLocalOrContextSlot(var, location);
2662
2663   } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
2664     if (var->IsLookupSlot()) {
2665       // Assignment to var.
2666       __ Push(rax);  // Value.
2667       __ Push(rsi);  // Context.
2668       __ Push(var->name());
2669       __ Push(Smi::FromInt(language_mode()));
2670       __ CallRuntime(Runtime::kStoreLookupSlot, 4);
2671     } else {
2672       // Assignment to var or initializing assignment to let/const in harmony
2673       // mode.
2674       DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2675       MemOperand location = VarOperand(var, rcx);
2676       if (generate_debug_code_ && op == Token::INIT_LET) {
2677         // Check for an uninitialized let binding.
2678         __ movp(rdx, location);
2679         __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2680         __ Check(equal, kLetBindingReInitialization);
2681       }
2682       EmitStoreToStackLocalOrContextSlot(var, location);
2683     }
2684
2685   } else if (op == Token::INIT_CONST_LEGACY) {
2686     // Const initializers need a write barrier.
2687     DCHECK(var->mode() == CONST_LEGACY);
2688     DCHECK(!var->IsParameter());  // No const parameters.
2689     if (var->IsLookupSlot()) {
2690       __ Push(rax);
2691       __ Push(rsi);
2692       __ Push(var->name());
2693       __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3);
2694     } else {
2695       DCHECK(var->IsStackLocal() || var->IsContextSlot());
2696       Label skip;
2697       MemOperand location = VarOperand(var, rcx);
2698       __ movp(rdx, location);
2699       __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2700       __ j(not_equal, &skip);
2701       EmitStoreToStackLocalOrContextSlot(var, location);
2702       __ bind(&skip);
2703     }
2704
2705   } else {
2706     DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT_CONST_LEGACY);
2707     if (is_strict(language_mode())) {
2708       __ CallRuntime(Runtime::kThrowConstAssignError, 0);
2709     }
2710     // Silently ignore store in sloppy mode.
2711   }
2712 }
2713
2714
2715 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2716   // Assignment to a property, using a named store IC.
2717   Property* prop = expr->target()->AsProperty();
2718   DCHECK(prop != NULL);
2719   DCHECK(prop->key()->IsLiteral());
2720
2721   __ Move(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value());
2722   __ Pop(StoreDescriptor::ReceiverRegister());
2723   if (FLAG_vector_stores) {
2724     EmitLoadStoreICSlot(expr->AssignmentSlot());
2725     CallStoreIC();
2726   } else {
2727     CallStoreIC(expr->AssignmentFeedbackId());
2728   }
2729
2730   PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2731   context()->Plug(rax);
2732 }
2733
2734
2735 void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
2736   // Assignment to named property of super.
2737   // rax : value
2738   // stack : receiver ('this'), home_object
2739   DCHECK(prop != NULL);
2740   Literal* key = prop->key()->AsLiteral();
2741   DCHECK(key != NULL);
2742
2743   __ Push(key->value());
2744   __ Push(rax);
2745   __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict
2746                                              : Runtime::kStoreToSuper_Sloppy),
2747                  4);
2748 }
2749
2750
2751 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
2752   // Assignment to named property of super.
2753   // rax : value
2754   // stack : receiver ('this'), home_object, key
2755   DCHECK(prop != NULL);
2756
2757   __ Push(rax);
2758   __ CallRuntime(
2759       (is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict
2760                                   : Runtime::kStoreKeyedToSuper_Sloppy),
2761       4);
2762 }
2763
2764
2765 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2766   // Assignment to a property, using a keyed store IC.
2767   __ Pop(StoreDescriptor::NameRegister());  // Key.
2768   __ Pop(StoreDescriptor::ReceiverRegister());
2769   DCHECK(StoreDescriptor::ValueRegister().is(rax));
2770   Handle<Code> ic =
2771       CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
2772   if (FLAG_vector_stores) {
2773     EmitLoadStoreICSlot(expr->AssignmentSlot());
2774     CallIC(ic);
2775   } else {
2776     CallIC(ic, expr->AssignmentFeedbackId());
2777   }
2778
2779   PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2780   context()->Plug(rax);
2781 }
2782
2783
2784 void FullCodeGenerator::VisitProperty(Property* expr) {
2785   Comment cmnt(masm_, "[ Property");
2786   SetExpressionPosition(expr);
2787
2788   Expression* key = expr->key();
2789
2790   if (key->IsPropertyName()) {
2791     if (!expr->IsSuperAccess()) {
2792       VisitForAccumulatorValue(expr->obj());
2793       DCHECK(!rax.is(LoadDescriptor::ReceiverRegister()));
2794       __ movp(LoadDescriptor::ReceiverRegister(), rax);
2795       EmitNamedPropertyLoad(expr);
2796     } else {
2797       VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
2798       VisitForStackValue(
2799           expr->obj()->AsSuperPropertyReference()->home_object());
2800       EmitNamedSuperPropertyLoad(expr);
2801     }
2802   } else {
2803     if (!expr->IsSuperAccess()) {
2804       VisitForStackValue(expr->obj());
2805       VisitForAccumulatorValue(expr->key());
2806       __ Move(LoadDescriptor::NameRegister(), rax);
2807       __ Pop(LoadDescriptor::ReceiverRegister());
2808       EmitKeyedPropertyLoad(expr);
2809     } else {
2810       VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
2811       VisitForStackValue(
2812           expr->obj()->AsSuperPropertyReference()->home_object());
2813       VisitForStackValue(expr->key());
2814       EmitKeyedSuperPropertyLoad(expr);
2815     }
2816   }
2817   PrepareForBailoutForId(expr->LoadId(), TOS_REG);
2818   context()->Plug(rax);
2819 }
2820
2821
2822 void FullCodeGenerator::CallIC(Handle<Code> code,
2823                                TypeFeedbackId ast_id) {
2824   ic_total_count_++;
2825   __ call(code, RelocInfo::CODE_TARGET, ast_id);
2826 }
2827
2828
2829 // Code common for calls using the IC.
2830 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
2831   Expression* callee = expr->expression();
2832
2833   CallICState::CallType call_type =
2834       callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD;
2835   // Get the target function.
2836   if (call_type == CallICState::FUNCTION) {
2837     { StackValueContext context(this);
2838       EmitVariableLoad(callee->AsVariableProxy());
2839       PrepareForBailout(callee, NO_REGISTERS);
2840     }
2841     // Push undefined as receiver. This is patched in the method prologue if it
2842     // is a sloppy mode method.
2843     __ Push(isolate()->factory()->undefined_value());
2844   } else {
2845     // Load the function from the receiver.
2846     DCHECK(callee->IsProperty());
2847     DCHECK(!callee->AsProperty()->IsSuperAccess());
2848     __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
2849     EmitNamedPropertyLoad(callee->AsProperty());
2850     PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2851     // Push the target function under the receiver.
2852     __ Push(Operand(rsp, 0));
2853     __ movp(Operand(rsp, kPointerSize), rax);
2854   }
2855
2856   EmitCall(expr, call_type);
2857 }
2858
2859
2860 void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
2861   Expression* callee = expr->expression();
2862   DCHECK(callee->IsProperty());
2863   Property* prop = callee->AsProperty();
2864   DCHECK(prop->IsSuperAccess());
2865   SetExpressionPosition(prop);
2866
2867   Literal* key = prop->key()->AsLiteral();
2868   DCHECK(!key->value()->IsSmi());
2869   // Load the function from the receiver.
2870   SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
2871   VisitForStackValue(super_ref->home_object());
2872   VisitForAccumulatorValue(super_ref->this_var());
2873   __ Push(rax);
2874   __ Push(rax);
2875   __ Push(Operand(rsp, kPointerSize * 2));
2876   __ Push(key->value());
2877   __ Push(Smi::FromInt(language_mode()));
2878
2879   // Stack here:
2880   //  - home_object
2881   //  - this (receiver)
2882   //  - this (receiver) <-- LoadFromSuper will pop here and below.
2883   //  - home_object
2884   //  - key
2885   //  - language_mode
2886   __ CallRuntime(Runtime::kLoadFromSuper, 4);
2887
2888   // Replace home_object with target function.
2889   __ movp(Operand(rsp, kPointerSize), rax);
2890
2891   // Stack here:
2892   // - target function
2893   // - this (receiver)
2894   EmitCall(expr, CallICState::METHOD);
2895 }
2896
2897
2898 // Common code for calls using the IC.
2899 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2900                                                 Expression* key) {
2901   // Load the key.
2902   VisitForAccumulatorValue(key);
2903
2904   Expression* callee = expr->expression();
2905
2906   // Load the function from the receiver.
2907   DCHECK(callee->IsProperty());
2908   __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
2909   __ Move(LoadDescriptor::NameRegister(), rax);
2910   EmitKeyedPropertyLoad(callee->AsProperty());
2911   PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2912
2913   // Push the target function under the receiver.
2914   __ Push(Operand(rsp, 0));
2915   __ movp(Operand(rsp, kPointerSize), rax);
2916
2917   EmitCall(expr, CallICState::METHOD);
2918 }
2919
2920
2921 void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
2922   Expression* callee = expr->expression();
2923   DCHECK(callee->IsProperty());
2924   Property* prop = callee->AsProperty();
2925   DCHECK(prop->IsSuperAccess());
2926
2927   SetExpressionPosition(prop);
2928   // Load the function from the receiver.
2929   SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
2930   VisitForStackValue(super_ref->home_object());
2931   VisitForAccumulatorValue(super_ref->this_var());
2932   __ Push(rax);
2933   __ Push(rax);
2934   __ Push(Operand(rsp, kPointerSize * 2));
2935   VisitForStackValue(prop->key());
2936   __ Push(Smi::FromInt(language_mode()));
2937
2938   // Stack here:
2939   //  - home_object
2940   //  - this (receiver)
2941   //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
2942   //  - home_object
2943   //  - key
2944   //  - language_mode
2945   __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
2946
2947   // Replace home_object with target function.
2948   __ movp(Operand(rsp, kPointerSize), rax);
2949
2950   // Stack here:
2951   // - target function
2952   // - this (receiver)
2953   EmitCall(expr, CallICState::METHOD);
2954 }
2955
2956
2957 void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
2958   // Load the arguments.
2959   ZoneList<Expression*>* args = expr->arguments();
2960   int arg_count = args->length();
2961   for (int i = 0; i < arg_count; i++) {
2962     VisitForStackValue(args->at(i));
2963   }
2964
2965   SetCallPosition(expr, arg_count);
2966   Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
2967   __ Move(rdx, SmiFromSlot(expr->CallFeedbackICSlot()));
2968   __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2969   // Don't assign a type feedback id to the IC, since type feedback is provided
2970   // by the vector above.
2971   CallIC(ic);
2972
2973   RecordJSReturnSite(expr);
2974
2975   // Restore context register.
2976   __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2977   // Discard the function left on TOS.
2978   context()->DropAndPlug(1, rax);
2979 }
2980
2981
2982 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2983   // Push copy of the first argument or undefined if it doesn't exist.
2984   if (arg_count > 0) {
2985     __ Push(Operand(rsp, arg_count * kPointerSize));
2986   } else {
2987     __ PushRoot(Heap::kUndefinedValueRootIndex);
2988   }
2989
2990   // Push the enclosing function.
2991   __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
2992
2993   // Push the language mode.
2994   __ Push(Smi::FromInt(language_mode()));
2995
2996   // Push the start position of the scope the calls resides in.
2997   __ Push(Smi::FromInt(scope()->start_position()));
2998
2999   // Do the runtime call.
3000   __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
3001 }
3002
3003
3004 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
3005 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
3006   VariableProxy* callee = expr->expression()->AsVariableProxy();
3007   if (callee->var()->IsLookupSlot()) {
3008     Label slow, done;
3009     SetExpressionPosition(callee);
3010     // Generate code for loading from variables potentially shadowed by
3011     // eval-introduced variables.
3012     EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
3013     __ bind(&slow);
3014     // Call the runtime to find the function to call (returned in rax) and
3015     // the object holding it (returned in rdx).
3016     __ Push(context_register());
3017     __ Push(callee->name());
3018     __ CallRuntime(Runtime::kLoadLookupSlot, 2);
3019     __ Push(rax);  // Function.
3020     __ Push(rdx);  // Receiver.
3021     PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
3022
3023     // If fast case code has been generated, emit code to push the function
3024     // and receiver and have the slow path jump around this code.
3025     if (done.is_linked()) {
3026       Label call;
3027       __ jmp(&call, Label::kNear);
3028       __ bind(&done);
3029       // Push function.
3030       __ Push(rax);
3031       // Pass undefined as the receiver, which is the WithBaseObject of a
3032       // non-object environment record.  If the callee is sloppy, it will patch
3033       // it up to be the global receiver.
3034       __ PushRoot(Heap::kUndefinedValueRootIndex);
3035       __ bind(&call);
3036     }
3037   } else {
3038     VisitForStackValue(callee);
3039     // refEnv.WithBaseObject()
3040     __ PushRoot(Heap::kUndefinedValueRootIndex);
3041   }
3042 }
3043
3044
3045 void FullCodeGenerator::VisitCall(Call* expr) {
3046 #ifdef DEBUG
3047   // We want to verify that RecordJSReturnSite gets called on all paths
3048   // through this function.  Avoid early returns.
3049   expr->return_is_recorded_ = false;
3050 #endif
3051
3052   Comment cmnt(masm_, "[ Call");
3053   Expression* callee = expr->expression();
3054   Call::CallType call_type = expr->GetCallType(isolate());
3055
3056   if (call_type == Call::POSSIBLY_EVAL_CALL) {
3057     // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
3058     // to resolve the function we need to call.  Then we call the resolved
3059     // function using the given arguments.
3060     ZoneList<Expression*>* args = expr->arguments();
3061     int arg_count = args->length();
3062     PushCalleeAndWithBaseObject(expr);
3063
3064     // Push the arguments.
3065     for (int i = 0; i < arg_count; i++) {
3066       VisitForStackValue(args->at(i));
3067     }
3068
3069     // Push a copy of the function (found below the arguments) and resolve
3070     // eval.
3071     __ Push(Operand(rsp, (arg_count + 1) * kPointerSize));
3072     EmitResolvePossiblyDirectEval(arg_count);
3073
3074     // Touch up the callee.
3075     __ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
3076
3077     PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
3078
3079     SetCallPosition(expr, arg_count);
3080     CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
3081     __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
3082     __ CallStub(&stub);
3083     RecordJSReturnSite(expr);
3084     // Restore context register.
3085     __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3086     context()->DropAndPlug(1, rax);
3087   } else if (call_type == Call::GLOBAL_CALL) {
3088     EmitCallWithLoadIC(expr);
3089
3090   } else if (call_type == Call::LOOKUP_SLOT_CALL) {
3091     // Call to a lookup slot (dynamically introduced variable).
3092     PushCalleeAndWithBaseObject(expr);
3093     EmitCall(expr);
3094   } else if (call_type == Call::PROPERTY_CALL) {
3095     Property* property = callee->AsProperty();
3096     bool is_named_call = property->key()->IsPropertyName();
3097     if (property->IsSuperAccess()) {
3098       if (is_named_call) {
3099         EmitSuperCallWithLoadIC(expr);
3100       } else {
3101         EmitKeyedSuperCallWithLoadIC(expr);
3102       }
3103     } else {
3104         VisitForStackValue(property->obj());
3105       if (is_named_call) {
3106         EmitCallWithLoadIC(expr);
3107       } else {
3108         EmitKeyedCallWithLoadIC(expr, property->key());
3109       }
3110     }
3111   } else if (call_type == Call::SUPER_CALL) {
3112     EmitSuperConstructorCall(expr);
3113   } else {
3114     DCHECK(call_type == Call::OTHER_CALL);
3115     // Call to an arbitrary expression not handled specially above.
3116       VisitForStackValue(callee);
3117     __ PushRoot(Heap::kUndefinedValueRootIndex);
3118     // Emit function call.
3119     EmitCall(expr);
3120   }
3121
3122 #ifdef DEBUG
3123   // RecordJSReturnSite should have been called.
3124   DCHECK(expr->return_is_recorded_);
3125 #endif
3126 }
3127
3128
3129 void FullCodeGenerator::VisitCallNew(CallNew* expr) {
3130   Comment cmnt(masm_, "[ CallNew");
3131   // According to ECMA-262, section 11.2.2, page 44, the function
3132   // expression in new calls must be evaluated before the
3133   // arguments.
3134
3135   // Push constructor on the stack.  If it's not a function it's used as
3136   // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
3137   // ignored.
3138   DCHECK(!expr->expression()->IsSuperPropertyReference());
3139   VisitForStackValue(expr->expression());
3140
3141   // Push the arguments ("left-to-right") on the stack.
3142   ZoneList<Expression*>* args = expr->arguments();
3143   int arg_count = args->length();
3144   for (int i = 0; i < arg_count; i++) {
3145     VisitForStackValue(args->at(i));
3146   }
3147
3148   // Call the construct call builtin that handles allocation and
3149   // constructor invocation.
3150   SetConstructCallPosition(expr);
3151
3152   // Load function and argument count into rdi and rax.
3153   __ Set(rax, arg_count);
3154   __ movp(rdi, Operand(rsp, arg_count * kPointerSize));
3155
3156   // Record call targets in unoptimized code, but not in the snapshot.
3157   if (FLAG_pretenuring_call_new) {
3158     EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot());
3159     DCHECK(expr->AllocationSiteFeedbackSlot().ToInt() ==
3160            expr->CallNewFeedbackSlot().ToInt() + 1);
3161   }
3162
3163   __ Move(rbx, FeedbackVector());
3164   __ Move(rdx, SmiFromSlot(expr->CallNewFeedbackSlot()));
3165
3166   CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET);
3167   __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
3168   PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
3169   context()->Plug(rax);
3170 }
3171
3172
3173 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
3174   SuperCallReference* super_call_ref =
3175       expr->expression()->AsSuperCallReference();
3176   DCHECK_NOT_NULL(super_call_ref);
3177
3178   EmitLoadSuperConstructor(super_call_ref);
3179   __ Push(result_register());
3180
3181   // Push the arguments ("left-to-right") on the stack.
3182   ZoneList<Expression*>* args = expr->arguments();
3183   int arg_count = args->length();
3184   for (int i = 0; i < arg_count; i++) {
3185     VisitForStackValue(args->at(i));
3186   }
3187
3188   // Call the construct call builtin that handles allocation and
3189   // constructor invocation.
3190   SetConstructCallPosition(expr);
3191
3192   // Load original constructor into rcx.
3193   VisitForAccumulatorValue(super_call_ref->new_target_var());
3194   __ movp(rcx, result_register());
3195
3196   // Load function and argument count into rdi and rax.
3197   __ Set(rax, arg_count);
3198   __ movp(rdi, Operand(rsp, arg_count * kPointerSize));
3199
3200   // Record call targets in unoptimized code.
3201   if (FLAG_pretenuring_call_new) {
3202     UNREACHABLE();
3203     /* TODO(dslomov): support pretenuring.
3204     EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot());
3205     DCHECK(expr->AllocationSiteFeedbackSlot().ToInt() ==
3206            expr->CallNewFeedbackSlot().ToInt() + 1);
3207     */
3208   }
3209
3210   __ Move(rbx, FeedbackVector());
3211   __ Move(rdx, SmiFromSlot(expr->CallFeedbackSlot()));
3212
3213   CallConstructStub stub(isolate(), SUPER_CALL_RECORD_TARGET);
3214   __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
3215
3216   RecordJSReturnSite(expr);
3217
3218   context()->Plug(rax);
3219 }
3220
3221
3222 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
3223   ZoneList<Expression*>* args = expr->arguments();
3224   DCHECK(args->length() == 1);
3225
3226   VisitForAccumulatorValue(args->at(0));
3227
3228   Label materialize_true, materialize_false;
3229   Label* if_true = NULL;
3230   Label* if_false = NULL;
3231   Label* fall_through = NULL;
3232   context()->PrepareTest(&materialize_true, &materialize_false,
3233                          &if_true, &if_false, &fall_through);
3234
3235   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3236   __ JumpIfSmi(rax, if_true);
3237   __ jmp(if_false);
3238
3239   context()->Plug(if_true, if_false);
3240 }
3241
3242
3243 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
3244   ZoneList<Expression*>* args = expr->arguments();
3245   DCHECK(args->length() == 1);
3246
3247   VisitForAccumulatorValue(args->at(0));
3248
3249   Label materialize_true, materialize_false;
3250   Label* if_true = NULL;
3251   Label* if_false = NULL;
3252   Label* fall_through = NULL;
3253   context()->PrepareTest(&materialize_true, &materialize_false,
3254                          &if_true, &if_false, &fall_through);
3255
3256   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3257   Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
3258   Split(non_negative_smi, if_true, if_false, fall_through);
3259
3260   context()->Plug(if_true, if_false);
3261 }
3262
3263
3264 void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
3265   ZoneList<Expression*>* args = expr->arguments();
3266   DCHECK(args->length() == 1);
3267
3268   VisitForAccumulatorValue(args->at(0));
3269
3270   Label materialize_true, materialize_false;
3271   Label* if_true = NULL;
3272   Label* if_false = NULL;
3273   Label* fall_through = NULL;
3274   context()->PrepareTest(&materialize_true, &materialize_false,
3275                          &if_true, &if_false, &fall_through);
3276
3277   __ JumpIfSmi(rax, if_false);
3278   __ CompareRoot(rax, Heap::kNullValueRootIndex);
3279   __ j(equal, if_true);
3280   __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
3281   // Undetectable objects behave like undefined when tested with typeof.
3282   __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
3283            Immediate(1 << Map::kIsUndetectable));
3284   __ j(not_zero, if_false);
3285   __ movzxbp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
3286   __ cmpp(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
3287   __ j(below, if_false);
3288   __ cmpp(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
3289   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3290   Split(below_equal, if_true, if_false, fall_through);
3291
3292   context()->Plug(if_true, if_false);
3293 }
3294
3295
3296 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
3297   ZoneList<Expression*>* args = expr->arguments();
3298   DCHECK(args->length() == 1);
3299
3300   VisitForAccumulatorValue(args->at(0));
3301
3302   Label materialize_true, materialize_false;
3303   Label* if_true = NULL;
3304   Label* if_false = NULL;
3305   Label* fall_through = NULL;
3306   context()->PrepareTest(&materialize_true, &materialize_false,
3307                          &if_true, &if_false, &fall_through);
3308
3309   __ JumpIfSmi(rax, if_false);
3310   __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx);
3311   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3312   Split(above_equal, if_true, if_false, fall_through);
3313
3314   context()->Plug(if_true, if_false);
3315 }
3316
3317
3318 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
3319   ZoneList<Expression*>* args = expr->arguments();
3320   DCHECK(args->length() == 1);
3321
3322   VisitForAccumulatorValue(args->at(0));
3323
3324   Label materialize_true, materialize_false;
3325   Label* if_true = NULL;
3326   Label* if_false = NULL;
3327   Label* fall_through = NULL;
3328   context()->PrepareTest(&materialize_true, &materialize_false,
3329                          &if_true, &if_false, &fall_through);
3330
3331   __ JumpIfSmi(rax, if_false);
3332   __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
3333   __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
3334            Immediate(1 << Map::kIsUndetectable));
3335   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3336   Split(not_zero, if_true, if_false, fall_through);
3337
3338   context()->Plug(if_true, if_false);
3339 }
3340
3341
3342 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
3343     CallRuntime* expr) {
3344   ZoneList<Expression*>* args = expr->arguments();
3345   DCHECK(args->length() == 1);
3346
3347   VisitForAccumulatorValue(args->at(0));
3348
3349   Label materialize_true, materialize_false, skip_lookup;
3350   Label* if_true = NULL;
3351   Label* if_false = NULL;
3352   Label* fall_through = NULL;
3353   context()->PrepareTest(&materialize_true, &materialize_false,
3354                          &if_true, &if_false, &fall_through);
3355
3356   __ AssertNotSmi(rax);
3357
3358   // Check whether this map has already been checked to be safe for default
3359   // valueOf.
3360   __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
3361   __ testb(FieldOperand(rbx, Map::kBitField2Offset),
3362            Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
3363   __ j(not_zero, &skip_lookup);
3364
3365   // Check for fast case object. Generate false result for slow case object.
3366   __ movp(rcx, FieldOperand(rax, JSObject::kPropertiesOffset));
3367   __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
3368   __ CompareRoot(rcx, Heap::kHashTableMapRootIndex);
3369   __ j(equal, if_false);
3370
3371   // Look for valueOf string in the descriptor array, and indicate false if
3372   // found. Since we omit an enumeration index check, if it is added via a
3373   // transition that shares its descriptor array, this is a false positive.
3374   Label entry, loop, done;
3375
3376   // Skip loop if no descriptors are valid.
3377   __ NumberOfOwnDescriptors(rcx, rbx);
3378   __ cmpp(rcx, Immediate(0));
3379   __ j(equal, &done);
3380
3381   __ LoadInstanceDescriptors(rbx, r8);
3382   // rbx: descriptor array.
3383   // rcx: valid entries in the descriptor array.
3384   // Calculate the end of the descriptor array.
3385   __ imulp(rcx, rcx, Immediate(DescriptorArray::kDescriptorSize));
3386   __ leap(rcx,
3387           Operand(r8, rcx, times_pointer_size, DescriptorArray::kFirstOffset));
3388   // Calculate location of the first key name.
3389   __ addp(r8, Immediate(DescriptorArray::kFirstOffset));
3390   // Loop through all the keys in the descriptor array. If one of these is the
3391   // internalized string "valueOf" the result is false.
3392   __ jmp(&entry);
3393   __ bind(&loop);
3394   __ movp(rdx, FieldOperand(r8, 0));
3395   __ Cmp(rdx, isolate()->factory()->value_of_string());
3396   __ j(equal, if_false);
3397   __ addp(r8, Immediate(DescriptorArray::kDescriptorSize * kPointerSize));
3398   __ bind(&entry);
3399   __ cmpp(r8, rcx);
3400   __ j(not_equal, &loop);
3401
3402   __ bind(&done);
3403
3404   // Set the bit in the map to indicate that there is no local valueOf field.
3405   __ orp(FieldOperand(rbx, Map::kBitField2Offset),
3406          Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
3407
3408   __ bind(&skip_lookup);
3409
3410   // If a valueOf property is not found on the object check that its
3411   // prototype is the un-modified String prototype. If not result is false.
3412   __ movp(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
3413   __ testp(rcx, Immediate(kSmiTagMask));
3414   __ j(zero, if_false);
3415   __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
3416   __ movp(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
3417   __ movp(rdx, FieldOperand(rdx, GlobalObject::kNativeContextOffset));
3418   __ cmpp(rcx,
3419           ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
3420   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3421   Split(equal, if_true, if_false, fall_through);
3422
3423   context()->Plug(if_true, if_false);
3424 }
3425
3426
3427 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
3428   ZoneList<Expression*>* args = expr->arguments();
3429   DCHECK(args->length() == 1);
3430
3431   VisitForAccumulatorValue(args->at(0));
3432
3433   Label materialize_true, materialize_false;
3434   Label* if_true = NULL;
3435   Label* if_false = NULL;
3436   Label* fall_through = NULL;
3437   context()->PrepareTest(&materialize_true, &materialize_false,
3438                          &if_true, &if_false, &fall_through);
3439
3440   __ JumpIfSmi(rax, if_false);
3441   __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
3442   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3443   Split(equal, if_true, if_false, fall_through);
3444
3445   context()->Plug(if_true, if_false);
3446 }
3447
3448
3449 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
3450   ZoneList<Expression*>* args = expr->arguments();
3451   DCHECK(args->length() == 1);
3452
3453   VisitForAccumulatorValue(args->at(0));
3454
3455   Label materialize_true, materialize_false;
3456   Label* if_true = NULL;
3457   Label* if_false = NULL;
3458   Label* fall_through = NULL;
3459   context()->PrepareTest(&materialize_true, &materialize_false,
3460                          &if_true, &if_false, &fall_through);
3461
3462   Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
3463   __ CheckMap(rax, map, if_false, DO_SMI_CHECK);
3464   __ cmpl(FieldOperand(rax, HeapNumber::kExponentOffset),
3465           Immediate(0x1));
3466   __ j(no_overflow, if_false);
3467   __ cmpl(FieldOperand(rax, HeapNumber::kMantissaOffset),
3468           Immediate(0x00000000));
3469   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3470   Split(equal, if_true, if_false, fall_through);
3471
3472   context()->Plug(if_true, if_false);
3473 }
3474
3475
3476 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
3477   ZoneList<Expression*>* args = expr->arguments();
3478   DCHECK(args->length() == 1);
3479
3480   VisitForAccumulatorValue(args->at(0));
3481
3482   Label materialize_true, materialize_false;
3483   Label* if_true = NULL;
3484   Label* if_false = NULL;
3485   Label* fall_through = NULL;
3486   context()->PrepareTest(&materialize_true, &materialize_false,
3487                          &if_true, &if_false, &fall_through);
3488
3489   __ JumpIfSmi(rax, if_false);
3490   __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
3491   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3492   Split(equal, if_true, if_false, fall_through);
3493
3494   context()->Plug(if_true, if_false);
3495 }
3496
3497
3498 void FullCodeGenerator::EmitIsTypedArray(CallRuntime* expr) {
3499   ZoneList<Expression*>* args = expr->arguments();
3500   DCHECK(args->length() == 1);
3501
3502   VisitForAccumulatorValue(args->at(0));
3503
3504   Label materialize_true, materialize_false;
3505   Label* if_true = NULL;
3506   Label* if_false = NULL;
3507   Label* fall_through = NULL;
3508   context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
3509                          &if_false, &fall_through);
3510
3511   __ JumpIfSmi(rax, if_false);
3512   __ CmpObjectType(rax, JS_TYPED_ARRAY_TYPE, rbx);
3513   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3514   Split(equal, if_true, if_false, fall_through);
3515
3516   context()->Plug(if_true, if_false);
3517 }
3518
3519
3520 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
3521   ZoneList<Expression*>* args = expr->arguments();
3522   DCHECK(args->length() == 1);
3523
3524   VisitForAccumulatorValue(args->at(0));
3525
3526   Label materialize_true, materialize_false;
3527   Label* if_true = NULL;
3528   Label* if_false = NULL;
3529   Label* fall_through = NULL;
3530   context()->PrepareTest(&materialize_true, &materialize_false,
3531                          &if_true, &if_false, &fall_through);
3532
3533   __ JumpIfSmi(rax, if_false);
3534   __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
3535   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3536   Split(equal, if_true, if_false, fall_through);
3537
3538   context()->Plug(if_true, if_false);
3539 }
3540
3541
3542 void FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) {
3543   ZoneList<Expression*>* args = expr->arguments();
3544   DCHECK(args->length() == 1);
3545
3546   VisitForAccumulatorValue(args->at(0));
3547
3548   Label materialize_true, materialize_false;
3549   Label* if_true = NULL;
3550   Label* if_false = NULL;
3551   Label* fall_through = NULL;
3552   context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
3553                          &if_false, &fall_through);
3554
3555   __ JumpIfSmi(rax, if_false);
3556   Register map = rbx;
3557   __ movp(map, FieldOperand(rax, HeapObject::kMapOffset));
3558   __ CmpInstanceType(map, FIRST_JS_PROXY_TYPE);
3559   __ j(less, if_false);
3560   __ CmpInstanceType(map, LAST_JS_PROXY_TYPE);
3561   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3562   Split(less_equal, if_true, if_false, fall_through);
3563
3564   context()->Plug(if_true, if_false);
3565 }
3566
3567
3568 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
3569   DCHECK(expr->arguments()->length() == 0);
3570
3571   Label materialize_true, materialize_false;
3572   Label* if_true = NULL;
3573   Label* if_false = NULL;
3574   Label* fall_through = NULL;
3575   context()->PrepareTest(&materialize_true, &materialize_false,
3576                          &if_true, &if_false, &fall_through);
3577
3578   // Get the frame pointer for the calling frame.
3579   __ movp(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
3580
3581   // Skip the arguments adaptor frame if it exists.
3582   Label check_frame_marker;
3583   __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset),
3584          Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
3585   __ j(not_equal, &check_frame_marker);
3586   __ movp(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
3587
3588   // Check the marker in the calling frame.
3589   __ bind(&check_frame_marker);
3590   __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset),
3591          Smi::FromInt(StackFrame::CONSTRUCT));
3592   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3593   Split(equal, if_true, if_false, fall_through);
3594
3595   context()->Plug(if_true, if_false);
3596 }
3597
3598
3599 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
3600   ZoneList<Expression*>* args = expr->arguments();
3601   DCHECK(args->length() == 2);
3602
3603   // Load the two objects into registers and perform the comparison.
3604   VisitForStackValue(args->at(0));
3605   VisitForAccumulatorValue(args->at(1));
3606
3607   Label materialize_true, materialize_false;
3608   Label* if_true = NULL;
3609   Label* if_false = NULL;
3610   Label* fall_through = NULL;
3611   context()->PrepareTest(&materialize_true, &materialize_false,
3612                          &if_true, &if_false, &fall_through);
3613
3614   __ Pop(rbx);
3615   __ cmpp(rax, rbx);
3616   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3617   Split(equal, if_true, if_false, fall_through);
3618
3619   context()->Plug(if_true, if_false);
3620 }
3621
3622
3623 void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
3624   ZoneList<Expression*>* args = expr->arguments();
3625   DCHECK(args->length() == 1);
3626
3627   // ArgumentsAccessStub expects the key in rdx and the formal
3628   // parameter count in rax.
3629   VisitForAccumulatorValue(args->at(0));
3630   __ movp(rdx, rax);
3631   __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
3632   ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT);
3633   __ CallStub(&stub);
3634   context()->Plug(rax);
3635 }
3636
3637
3638 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
3639   DCHECK(expr->arguments()->length() == 0);
3640
3641   Label exit;
3642   // Get the number of formal parameters.
3643   __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
3644
3645   // Check if the calling frame is an arguments adaptor frame.
3646   __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
3647   __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
3648          Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
3649   __ j(not_equal, &exit, Label::kNear);
3650
3651   // Arguments adaptor case: Read the arguments length from the
3652   // adaptor frame.
3653   __ movp(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
3654
3655   __ bind(&exit);
3656   __ AssertSmi(rax);
3657   context()->Plug(rax);
3658 }
3659
3660
3661 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
3662   ZoneList<Expression*>* args = expr->arguments();
3663   DCHECK(args->length() == 1);
3664   Label done, null, function, non_function_constructor;
3665
3666   VisitForAccumulatorValue(args->at(0));
3667
3668   // If the object is a smi, we return null.
3669   __ JumpIfSmi(rax, &null);
3670
3671   // Check that the object is a JS object but take special care of JS
3672   // functions to make sure they have 'Function' as their class.
3673   // Assume that there are only two callable types, and one of them is at
3674   // either end of the type range for JS object types. Saves extra comparisons.
3675   STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
3676   __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax);
3677   // Map is now in rax.
3678   __ j(below, &null);
3679   STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
3680                 FIRST_SPEC_OBJECT_TYPE + 1);
3681   __ j(equal, &function);
3682
3683   __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE);
3684   STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
3685                 LAST_SPEC_OBJECT_TYPE - 1);
3686   __ j(equal, &function);
3687   // Assume that there is no larger type.
3688   STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
3689
3690   // Check if the constructor in the map is a JS function.
3691   __ GetMapConstructor(rax, rax, rbx);
3692   __ CmpInstanceType(rbx, JS_FUNCTION_TYPE);
3693   __ j(not_equal, &non_function_constructor);
3694
3695   // rax now contains the constructor function. Grab the
3696   // instance class name from there.
3697   __ movp(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
3698   __ movp(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset));
3699   __ jmp(&done);
3700
3701   // Functions have class 'Function'.
3702   __ bind(&function);
3703   __ Move(rax, isolate()->factory()->Function_string());
3704   __ jmp(&done);
3705
3706   // Objects with a non-function constructor have class 'Object'.
3707   __ bind(&non_function_constructor);
3708   __ Move(rax, isolate()->factory()->Object_string());
3709   __ jmp(&done);
3710
3711   // Non-JS objects have class null.
3712   __ bind(&null);
3713   __ LoadRoot(rax, Heap::kNullValueRootIndex);
3714
3715   // All done.
3716   __ bind(&done);
3717
3718   context()->Plug(rax);
3719 }
3720
3721
3722 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
3723   ZoneList<Expression*>* args = expr->arguments();
3724   DCHECK(args->length() == 1);
3725
3726   VisitForAccumulatorValue(args->at(0));  // Load the object.
3727
3728   Label done;
3729   // If the object is a smi return the object.
3730   __ JumpIfSmi(rax, &done);
3731   // If the object is not a value type, return the object.
3732   __ CmpObjectType(rax, JS_VALUE_TYPE, rbx);
3733   __ j(not_equal, &done);
3734   __ movp(rax, FieldOperand(rax, JSValue::kValueOffset));
3735
3736   __ bind(&done);
3737   context()->Plug(rax);
3738 }
3739
3740
3741 void FullCodeGenerator::EmitIsDate(CallRuntime* expr) {
3742   ZoneList<Expression*>* args = expr->arguments();
3743   DCHECK_EQ(1, args->length());
3744
3745   VisitForAccumulatorValue(args->at(0));
3746
3747   Label materialize_true, materialize_false;
3748   Label* if_true = nullptr;
3749   Label* if_false = nullptr;
3750   Label* fall_through = nullptr;
3751   context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
3752                          &if_false, &fall_through);
3753
3754   __ JumpIfSmi(rax, if_false);
3755   __ CmpObjectType(rax, JS_DATE_TYPE, rbx);
3756   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3757   Split(equal, if_true, if_false, fall_through);
3758
3759   context()->Plug(if_true, if_false);
3760 }
3761
3762
3763 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
3764   ZoneList<Expression*>* args = expr->arguments();
3765   DCHECK(args->length() == 2);
3766   DCHECK_NOT_NULL(args->at(1)->AsLiteral());
3767   Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value()));
3768
3769   VisitForAccumulatorValue(args->at(0));  // Load the object.
3770
3771   Register object = rax;
3772   Register result = rax;
3773   Register scratch = rcx;
3774
3775   if (FLAG_debug_code) {
3776     __ AssertNotSmi(object);
3777     __ CmpObjectType(object, JS_DATE_TYPE, scratch);
3778     __ Check(equal, kOperandIsNotADate);
3779   }
3780
3781   if (index->value() == 0) {
3782     __ movp(result, FieldOperand(object, JSDate::kValueOffset));
3783   } else {
3784     Label runtime, done;
3785     if (index->value() < JSDate::kFirstUncachedField) {
3786       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
3787       Operand stamp_operand = __ ExternalOperand(stamp);
3788       __ movp(scratch, stamp_operand);
3789       __ cmpp(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
3790       __ j(not_equal, &runtime, Label::kNear);
3791       __ movp(result, FieldOperand(object, JSDate::kValueOffset +
3792                                            kPointerSize * index->value()));
3793       __ jmp(&done, Label::kNear);
3794     }
3795     __ bind(&runtime);
3796     __ PrepareCallCFunction(2);
3797     __ movp(arg_reg_1, object);
3798     __ Move(arg_reg_2, index, Assembler::RelocInfoNone());
3799     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
3800     __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3801     __ bind(&done);
3802   }
3803
3804   context()->Plug(rax);
3805 }
3806
3807
3808 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
3809   ZoneList<Expression*>* args = expr->arguments();
3810   DCHECK_EQ(3, args->length());
3811
3812   Register string = rax;
3813   Register index = rbx;
3814   Register value = rcx;
3815
3816   VisitForStackValue(args->at(0));        // index
3817   VisitForStackValue(args->at(1));        // value
3818   VisitForAccumulatorValue(args->at(2));  // string
3819   __ Pop(value);
3820   __ Pop(index);
3821
3822   if (FLAG_debug_code) {
3823     __ Check(__ CheckSmi(value), kNonSmiValue);
3824     __ Check(__ CheckSmi(index), kNonSmiValue);
3825   }
3826
3827   __ SmiToInteger32(value, value);
3828   __ SmiToInteger32(index, index);
3829
3830   if (FLAG_debug_code) {
3831     static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
3832     __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
3833   }
3834
3835   __ movb(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize),
3836           value);
3837   context()->Plug(string);
3838 }
3839
3840
3841 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
3842   ZoneList<Expression*>* args = expr->arguments();
3843   DCHECK_EQ(3, args->length());
3844
3845   Register string = rax;
3846   Register index = rbx;
3847   Register value = rcx;
3848
3849   VisitForStackValue(args->at(0));        // index
3850   VisitForStackValue(args->at(1));        // value
3851   VisitForAccumulatorValue(args->at(2));  // string
3852   __ Pop(value);
3853   __ Pop(index);
3854
3855   if (FLAG_debug_code) {
3856     __ Check(__ CheckSmi(value), kNonSmiValue);
3857     __ Check(__ CheckSmi(index), kNonSmiValue);
3858   }
3859
3860   __ SmiToInteger32(value, value);
3861   __ SmiToInteger32(index, index);
3862
3863   if (FLAG_debug_code) {
3864     static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
3865     __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
3866   }
3867
3868   __ movw(FieldOperand(string, index, times_2, SeqTwoByteString::kHeaderSize),
3869           value);
3870   context()->Plug(rax);
3871 }
3872
3873
3874 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
3875   ZoneList<Expression*>* args = expr->arguments();
3876   DCHECK(args->length() == 2);
3877
3878   VisitForStackValue(args->at(0));  // Load the object.
3879   VisitForAccumulatorValue(args->at(1));  // Load the value.
3880   __ Pop(rbx);  // rax = value. rbx = object.
3881
3882   Label done;
3883   // If the object is a smi, return the value.
3884   __ JumpIfSmi(rbx, &done);
3885
3886   // If the object is not a value type, return the value.
3887   __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx);
3888   __ j(not_equal, &done);
3889
3890   // Store the value.
3891   __ movp(FieldOperand(rbx, JSValue::kValueOffset), rax);
3892   // Update the write barrier.  Save the value as it will be
3893   // overwritten by the write barrier code and is needed afterward.
3894   __ movp(rdx, rax);
3895   __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs);
3896
3897   __ bind(&done);
3898   context()->Plug(rax);
3899 }
3900
3901
3902 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
3903   ZoneList<Expression*>* args = expr->arguments();
3904   DCHECK_EQ(args->length(), 1);
3905
3906   // Load the argument into rax and call the stub.
3907   VisitForAccumulatorValue(args->at(0));
3908
3909   NumberToStringStub stub(isolate());
3910   __ CallStub(&stub);
3911   context()->Plug(rax);
3912 }
3913
3914
3915 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
3916   ZoneList<Expression*>* args = expr->arguments();
3917   DCHECK(args->length() == 1);
3918
3919   VisitForAccumulatorValue(args->at(0));
3920
3921   Label done;
3922   StringCharFromCodeGenerator generator(rax, rbx);
3923   generator.GenerateFast(masm_);
3924   __ jmp(&done);
3925
3926   NopRuntimeCallHelper call_helper;
3927   generator.GenerateSlow(masm_, call_helper);
3928
3929   __ bind(&done);
3930   context()->Plug(rbx);
3931 }
3932
3933
3934 void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
3935   ZoneList<Expression*>* args = expr->arguments();
3936   DCHECK(args->length() == 2);
3937
3938   VisitForStackValue(args->at(0));
3939   VisitForAccumulatorValue(args->at(1));
3940
3941   Register object = rbx;
3942   Register index = rax;
3943   Register result = rdx;
3944
3945   __ Pop(object);
3946
3947   Label need_conversion;
3948   Label index_out_of_range;
3949   Label done;
3950   StringCharCodeAtGenerator generator(object,
3951                                       index,
3952                                       result,
3953                                       &need_conversion,
3954                                       &need_conversion,
3955                                       &index_out_of_range,
3956                                       STRING_INDEX_IS_NUMBER);
3957   generator.GenerateFast(masm_);
3958   __ jmp(&done);
3959
3960   __ bind(&index_out_of_range);
3961   // When the index is out of range, the spec requires us to return
3962   // NaN.
3963   __ LoadRoot(result, Heap::kNanValueRootIndex);
3964   __ jmp(&done);
3965
3966   __ bind(&need_conversion);
3967   // Move the undefined value into the result register, which will
3968   // trigger conversion.
3969   __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
3970   __ jmp(&done);
3971
3972   NopRuntimeCallHelper call_helper;
3973   generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
3974
3975   __ bind(&done);
3976   context()->Plug(result);
3977 }
3978
3979
3980 void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
3981   ZoneList<Expression*>* args = expr->arguments();
3982   DCHECK(args->length() == 2);
3983
3984   VisitForStackValue(args->at(0));
3985   VisitForAccumulatorValue(args->at(1));
3986
3987   Register object = rbx;
3988   Register index = rax;
3989   Register scratch = rdx;
3990   Register result = rax;
3991
3992   __ Pop(object);
3993
3994   Label need_conversion;
3995   Label index_out_of_range;
3996   Label done;
3997   StringCharAtGenerator generator(object,
3998                                   index,
3999                                   scratch,
4000                                   result,
4001                                   &need_conversion,
4002                                   &need_conversion,
4003                                   &index_out_of_range,
4004                                   STRING_INDEX_IS_NUMBER);
4005   generator.GenerateFast(masm_);
4006   __ jmp(&done);
4007
4008   __ bind(&index_out_of_range);
4009   // When the index is out of range, the spec requires us to return
4010   // the empty string.
4011   __ LoadRoot(result, Heap::kempty_stringRootIndex);
4012   __ jmp(&done);
4013
4014   __ bind(&need_conversion);
4015   // Move smi zero into the result register, which will trigger
4016   // conversion.
4017   __ Move(result, Smi::FromInt(0));
4018   __ jmp(&done);
4019
4020   NopRuntimeCallHelper call_helper;
4021   generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
4022
4023   __ bind(&done);
4024   context()->Plug(result);
4025 }
4026
4027
4028 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
4029   ZoneList<Expression*>* args = expr->arguments();
4030   DCHECK_EQ(2, args->length());
4031   VisitForStackValue(args->at(0));
4032   VisitForAccumulatorValue(args->at(1));
4033
4034   __ Pop(rdx);
4035   StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED);
4036   __ CallStub(&stub);
4037   context()->Plug(rax);
4038 }
4039
4040
4041 void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
4042   ZoneList<Expression*>* args = expr->arguments();
4043   DCHECK(args->length() >= 2);
4044
4045   int arg_count = args->length() - 2;  // 2 ~ receiver and function.
4046   for (int i = 0; i < arg_count + 1; i++) {
4047     VisitForStackValue(args->at(i));
4048   }
4049   VisitForAccumulatorValue(args->last());  // Function.
4050
4051   Label runtime, done;
4052   // Check for non-function argument (including proxy).
4053   __ JumpIfSmi(rax, &runtime);
4054   __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
4055   __ j(not_equal, &runtime);
4056
4057   // InvokeFunction requires the function in rdi. Move it in there.
4058   __ movp(rdi, result_register());
4059   ParameterCount count(arg_count);
4060   __ InvokeFunction(rdi, count, CALL_FUNCTION, NullCallWrapper());
4061   __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4062   __ jmp(&done);
4063
4064   __ bind(&runtime);
4065   __ Push(rax);
4066   __ CallRuntime(Runtime::kCall, args->length());
4067   __ bind(&done);
4068
4069   context()->Plug(rax);
4070 }
4071
4072
4073 void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
4074   ZoneList<Expression*>* args = expr->arguments();
4075   DCHECK(args->length() == 2);
4076
4077   // new.target
4078   VisitForStackValue(args->at(0));
4079
4080   // .this_function
4081   VisitForStackValue(args->at(1));
4082   __ CallRuntime(Runtime::kGetPrototype, 1);
4083   __ Push(result_register());
4084
4085   // Load original constructor into rcx.
4086   __ movp(rcx, Operand(rsp, 1 * kPointerSize));
4087
4088   // Check if the calling frame is an arguments adaptor frame.
4089   Label adaptor_frame, args_set_up, runtime;
4090   __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
4091   __ movp(rbx, Operand(rdx, StandardFrameConstants::kContextOffset));
4092   __ Cmp(rbx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
4093   __ j(equal, &adaptor_frame);
4094   // default constructor has no arguments, so no adaptor frame means no args.
4095   __ movp(rax, Immediate(0));
4096   __ jmp(&args_set_up);
4097
4098   // Copy arguments from adaptor frame.
4099   {
4100     __ bind(&adaptor_frame);
4101     __ movp(rbx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
4102     __ SmiToInteger64(rbx, rbx);
4103
4104     __ movp(rax, rbx);
4105     __ leap(rdx, Operand(rdx, rbx, times_pointer_size,
4106                          StandardFrameConstants::kCallerSPOffset));
4107     Label loop;
4108     __ bind(&loop);
4109     __ Push(Operand(rdx, -1 * kPointerSize));
4110     __ subp(rdx, Immediate(kPointerSize));
4111     __ decp(rbx);
4112     __ j(not_zero, &loop);
4113   }
4114
4115   __ bind(&args_set_up);
4116   __ movp(rdi, Operand(rsp, rax, times_pointer_size, 0));
4117   __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
4118
4119   CallConstructStub stub(isolate(), SUPER_CONSTRUCTOR_CALL);
4120   __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
4121
4122   __ Drop(1);
4123
4124   context()->Plug(result_register());
4125 }
4126
4127
4128 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
4129   RegExpConstructResultStub stub(isolate());
4130   ZoneList<Expression*>* args = expr->arguments();
4131   DCHECK(args->length() == 3);
4132   VisitForStackValue(args->at(0));
4133   VisitForStackValue(args->at(1));
4134   VisitForAccumulatorValue(args->at(2));
4135   __ Pop(rbx);
4136   __ Pop(rcx);
4137   __ CallStub(&stub);
4138   context()->Plug(rax);
4139 }
4140
4141
4142 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
4143   ZoneList<Expression*>* args = expr->arguments();
4144   DCHECK_EQ(2, args->length());
4145
4146   DCHECK_NOT_NULL(args->at(0)->AsLiteral());
4147   int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value();
4148
4149   Handle<FixedArray> jsfunction_result_caches(
4150       isolate()->native_context()->jsfunction_result_caches());
4151   if (jsfunction_result_caches->length() <= cache_id) {
4152     __ Abort(kAttemptToUseUndefinedCache);
4153     __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
4154     context()->Plug(rax);
4155     return;
4156   }
4157
4158   VisitForAccumulatorValue(args->at(1));
4159
4160   Register key = rax;
4161   Register cache = rbx;
4162   Register tmp = rcx;
4163   __ movp(cache, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX));
4164   __ movp(cache,
4165           FieldOperand(cache, GlobalObject::kNativeContextOffset));
4166   __ movp(cache,
4167           ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
4168   __ movp(cache,
4169           FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
4170
4171   Label done, not_found;
4172   STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
4173   __ movp(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
4174   // tmp now holds finger offset as a smi.
4175   SmiIndex index =
4176       __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2);
4177   __ cmpp(key, FieldOperand(cache,
4178                             index.reg,
4179                             index.scale,
4180                             FixedArray::kHeaderSize));
4181   __ j(not_equal, &not_found, Label::kNear);
4182   __ movp(rax, FieldOperand(cache,
4183                             index.reg,
4184                             index.scale,
4185                             FixedArray::kHeaderSize + kPointerSize));
4186   __ jmp(&done, Label::kNear);
4187
4188   __ bind(&not_found);
4189   // Call runtime to perform the lookup.
4190   __ Push(cache);
4191   __ Push(key);
4192   __ CallRuntime(Runtime::kGetFromCacheRT, 2);
4193
4194   __ bind(&done);
4195   context()->Plug(rax);
4196 }
4197
4198
4199 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
4200   ZoneList<Expression*>* args = expr->arguments();
4201   DCHECK(args->length() == 1);
4202
4203   VisitForAccumulatorValue(args->at(0));
4204
4205   Label materialize_true, materialize_false;
4206   Label* if_true = NULL;
4207   Label* if_false = NULL;
4208   Label* fall_through = NULL;
4209   context()->PrepareTest(&materialize_true, &materialize_false,
4210                          &if_true, &if_false, &fall_through);
4211
4212   __ testl(FieldOperand(rax, String::kHashFieldOffset),
4213            Immediate(String::kContainsCachedArrayIndexMask));
4214   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4215   __ j(zero, if_true);
4216   __ jmp(if_false);
4217
4218   context()->Plug(if_true, if_false);
4219 }
4220
4221
4222 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
4223   ZoneList<Expression*>* args = expr->arguments();
4224   DCHECK(args->length() == 1);
4225   VisitForAccumulatorValue(args->at(0));
4226
4227   __ AssertString(rax);
4228
4229   __ movl(rax, FieldOperand(rax, String::kHashFieldOffset));
4230   DCHECK(String::kHashShift >= kSmiTagSize);
4231   __ IndexFromHash(rax, rax);
4232
4233   context()->Plug(rax);
4234 }
4235
4236
4237 void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) {
4238   Label bailout, return_result, done, one_char_separator, long_separator,
4239       non_trivial_array, not_size_one_array, loop,
4240       loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
4241   ZoneList<Expression*>* args = expr->arguments();
4242   DCHECK(args->length() == 2);
4243   // We will leave the separator on the stack until the end of the function.
4244   VisitForStackValue(args->at(1));
4245   // Load this to rax (= array)
4246   VisitForAccumulatorValue(args->at(0));
4247   // All aliases of the same register have disjoint lifetimes.
4248   Register array = rax;
4249   Register elements = no_reg;  // Will be rax.
4250
4251   Register index = rdx;
4252
4253   Register string_length = rcx;
4254
4255   Register string = rsi;
4256
4257   Register scratch = rbx;
4258
4259   Register array_length = rdi;
4260   Register result_pos = no_reg;  // Will be rdi.
4261
4262   Operand separator_operand =    Operand(rsp, 2 * kPointerSize);
4263   Operand result_operand =       Operand(rsp, 1 * kPointerSize);
4264   Operand array_length_operand = Operand(rsp, 0 * kPointerSize);
4265   // Separator operand is already pushed. Make room for the two
4266   // other stack fields, and clear the direction flag in anticipation
4267   // of calling CopyBytes.
4268   __ subp(rsp, Immediate(2 * kPointerSize));
4269   __ cld();
4270   // Check that the array is a JSArray
4271   __ JumpIfSmi(array, &bailout);
4272   __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
4273   __ j(not_equal, &bailout);
4274
4275   // Check that the array has fast elements.
4276   __ CheckFastElements(scratch, &bailout);
4277
4278   // Array has fast elements, so its length must be a smi.
4279   // If the array has length zero, return the empty string.
4280   __ movp(array_length, FieldOperand(array, JSArray::kLengthOffset));
4281   __ SmiCompare(array_length, Smi::FromInt(0));
4282   __ j(not_zero, &non_trivial_array);
4283   __ LoadRoot(rax, Heap::kempty_stringRootIndex);
4284   __ jmp(&return_result);
4285
4286   // Save the array length on the stack.
4287   __ bind(&non_trivial_array);
4288   __ SmiToInteger32(array_length, array_length);
4289   __ movl(array_length_operand, array_length);
4290
4291   // Save the FixedArray containing array's elements.
4292   // End of array's live range.
4293   elements = array;
4294   __ movp(elements, FieldOperand(array, JSArray::kElementsOffset));
4295   array = no_reg;
4296
4297
4298   // Check that all array elements are sequential one-byte strings, and
4299   // accumulate the sum of their lengths, as a smi-encoded value.
4300   __ Set(index, 0);
4301   __ Set(string_length, 0);
4302   // Loop condition: while (index < array_length).
4303   // Live loop registers: index(int32), array_length(int32), string(String*),
4304   //                      scratch, string_length(int32), elements(FixedArray*).
4305   if (generate_debug_code_) {
4306     __ cmpp(index, array_length);
4307     __ Assert(below, kNoEmptyArraysHereInEmitFastOneByteArrayJoin);
4308   }
4309   __ bind(&loop);
4310   __ movp(string, FieldOperand(elements,
4311                                index,
4312                                times_pointer_size,
4313                                FixedArray::kHeaderSize));
4314   __ JumpIfSmi(string, &bailout);
4315   __ movp(scratch, FieldOperand(string, HeapObject::kMapOffset));
4316   __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
4317   __ andb(scratch, Immediate(
4318       kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
4319   __ cmpb(scratch, Immediate(kStringTag | kOneByteStringTag | kSeqStringTag));
4320   __ j(not_equal, &bailout);
4321   __ AddSmiField(string_length,
4322                  FieldOperand(string, SeqOneByteString::kLengthOffset));
4323   __ j(overflow, &bailout);
4324   __ incl(index);
4325   __ cmpl(index, array_length);
4326   __ j(less, &loop);
4327
4328   // Live registers:
4329   // string_length: Sum of string lengths.
4330   // elements: FixedArray of strings.
4331   // index: Array length.
4332   // array_length: Array length.
4333
4334   // If array_length is 1, return elements[0], a string.
4335   __ cmpl(array_length, Immediate(1));
4336   __ j(not_equal, &not_size_one_array);
4337   __ movp(rax, FieldOperand(elements, FixedArray::kHeaderSize));
4338   __ jmp(&return_result);
4339
4340   __ bind(&not_size_one_array);
4341
4342   // End of array_length live range.
4343   result_pos = array_length;
4344   array_length = no_reg;
4345
4346   // Live registers:
4347   // string_length: Sum of string lengths.
4348   // elements: FixedArray of strings.
4349   // index: Array length.
4350
4351   // Check that the separator is a sequential one-byte string.
4352   __ movp(string, separator_operand);
4353   __ JumpIfSmi(string, &bailout);
4354   __ movp(scratch, FieldOperand(string, HeapObject::kMapOffset));
4355   __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
4356   __ andb(scratch, Immediate(
4357       kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
4358   __ cmpb(scratch, Immediate(kStringTag | kOneByteStringTag | kSeqStringTag));
4359   __ j(not_equal, &bailout);
4360
4361   // Live registers:
4362   // string_length: Sum of string lengths.
4363   // elements: FixedArray of strings.
4364   // index: Array length.
4365   // string: Separator string.
4366
4367   // Add (separator length times (array_length - 1)) to string_length.
4368   __ SmiToInteger32(scratch,
4369                     FieldOperand(string, SeqOneByteString::kLengthOffset));
4370   __ decl(index);
4371   __ imull(scratch, index);
4372   __ j(overflow, &bailout);
4373   __ addl(string_length, scratch);
4374   __ j(overflow, &bailout);
4375
4376   // Live registers and stack values:
4377   //   string_length: Total length of result string.
4378   //   elements: FixedArray of strings.
4379   __ AllocateOneByteString(result_pos, string_length, scratch, index, string,
4380                            &bailout);
4381   __ movp(result_operand, result_pos);
4382   __ leap(result_pos, FieldOperand(result_pos, SeqOneByteString::kHeaderSize));
4383
4384   __ movp(string, separator_operand);
4385   __ SmiCompare(FieldOperand(string, SeqOneByteString::kLengthOffset),
4386                 Smi::FromInt(1));
4387   __ j(equal, &one_char_separator);
4388   __ j(greater, &long_separator);
4389
4390
4391   // Empty separator case:
4392   __ Set(index, 0);
4393   __ movl(scratch, array_length_operand);
4394   __ jmp(&loop_1_condition);
4395   // Loop condition: while (index < array_length).
4396   __ bind(&loop_1);
4397   // Each iteration of the loop concatenates one string to the result.
4398   // Live values in registers:
4399   //   index: which element of the elements array we are adding to the result.
4400   //   result_pos: the position to which we are currently copying characters.
4401   //   elements: the FixedArray of strings we are joining.
4402   //   scratch: array length.
4403
4404   // Get string = array[index].
4405   __ movp(string, FieldOperand(elements, index,
4406                                times_pointer_size,
4407                                FixedArray::kHeaderSize));
4408   __ SmiToInteger32(string_length,
4409                     FieldOperand(string, String::kLengthOffset));
4410   __ leap(string,
4411          FieldOperand(string, SeqOneByteString::kHeaderSize));
4412   __ CopyBytes(result_pos, string, string_length);
4413   __ incl(index);
4414   __ bind(&loop_1_condition);
4415   __ cmpl(index, scratch);
4416   __ j(less, &loop_1);  // Loop while (index < array_length).
4417   __ jmp(&done);
4418
4419   // Generic bailout code used from several places.
4420   __ bind(&bailout);
4421   __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
4422   __ jmp(&return_result);
4423
4424
4425   // One-character separator case
4426   __ bind(&one_char_separator);
4427   // Get the separator one-byte character value.
4428   // Register "string" holds the separator.
4429   __ movzxbl(scratch, FieldOperand(string, SeqOneByteString::kHeaderSize));
4430   __ Set(index, 0);
4431   // Jump into the loop after the code that copies the separator, so the first
4432   // element is not preceded by a separator
4433   __ jmp(&loop_2_entry);
4434   // Loop condition: while (index < length).
4435   __ bind(&loop_2);
4436   // Each iteration of the loop concatenates one string to the result.
4437   // Live values in registers:
4438   //   elements: The FixedArray of strings we are joining.
4439   //   index: which element of the elements array we are adding to the result.
4440   //   result_pos: the position to which we are currently copying characters.
4441   //   scratch: Separator character.
4442
4443   // Copy the separator character to the result.
4444   __ movb(Operand(result_pos, 0), scratch);
4445   __ incp(result_pos);
4446
4447   __ bind(&loop_2_entry);
4448   // Get string = array[index].
4449   __ movp(string, FieldOperand(elements, index,
4450                                times_pointer_size,
4451                                FixedArray::kHeaderSize));
4452   __ SmiToInteger32(string_length,
4453                     FieldOperand(string, String::kLengthOffset));
4454   __ leap(string,
4455          FieldOperand(string, SeqOneByteString::kHeaderSize));
4456   __ CopyBytes(result_pos, string, string_length);
4457   __ incl(index);
4458   __ cmpl(index, array_length_operand);
4459   __ j(less, &loop_2);  // End while (index < length).
4460   __ jmp(&done);
4461
4462
4463   // Long separator case (separator is more than one character).
4464   __ bind(&long_separator);
4465
4466   // Make elements point to end of elements array, and index
4467   // count from -array_length to zero, so we don't need to maintain
4468   // a loop limit.
4469   __ movl(index, array_length_operand);
4470   __ leap(elements, FieldOperand(elements, index, times_pointer_size,
4471                                 FixedArray::kHeaderSize));
4472   __ negq(index);
4473
4474   // Replace separator string with pointer to its first character, and
4475   // make scratch be its length.
4476   __ movp(string, separator_operand);
4477   __ SmiToInteger32(scratch,
4478                     FieldOperand(string, String::kLengthOffset));
4479   __ leap(string,
4480          FieldOperand(string, SeqOneByteString::kHeaderSize));
4481   __ movp(separator_operand, string);
4482
4483   // Jump into the loop after the code that copies the separator, so the first
4484   // element is not preceded by a separator
4485   __ jmp(&loop_3_entry);
4486   // Loop condition: while (index < length).
4487   __ bind(&loop_3);
4488   // Each iteration of the loop concatenates one string to the result.
4489   // Live values in registers:
4490   //   index: which element of the elements array we are adding to the result.
4491   //   result_pos: the position to which we are currently copying characters.
4492   //   scratch: Separator length.
4493   //   separator_operand (rsp[0x10]): Address of first char of separator.
4494
4495   // Copy the separator to the result.
4496   __ movp(string, separator_operand);
4497   __ movl(string_length, scratch);
4498   __ CopyBytes(result_pos, string, string_length, 2);
4499
4500   __ bind(&loop_3_entry);
4501   // Get string = array[index].
4502   __ movp(string, Operand(elements, index, times_pointer_size, 0));
4503   __ SmiToInteger32(string_length,
4504                     FieldOperand(string, String::kLengthOffset));
4505   __ leap(string,
4506          FieldOperand(string, SeqOneByteString::kHeaderSize));
4507   __ CopyBytes(result_pos, string, string_length);
4508   __ incq(index);
4509   __ j(not_equal, &loop_3);  // Loop while (index < 0).
4510
4511   __ bind(&done);
4512   __ movp(rax, result_operand);
4513
4514   __ bind(&return_result);
4515   // Drop temp values from the stack, and restore context register.
4516   __ addp(rsp, Immediate(3 * kPointerSize));
4517   __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4518   context()->Plug(rax);
4519 }
4520
4521
4522 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
4523   DCHECK(expr->arguments()->length() == 0);
4524   ExternalReference debug_is_active =
4525       ExternalReference::debug_is_active_address(isolate());
4526   __ Move(kScratchRegister, debug_is_active);
4527   __ movzxbp(rax, Operand(kScratchRegister, 0));
4528   __ Integer32ToSmi(rax, rax);
4529   context()->Plug(rax);
4530 }
4531
4532
4533 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
4534   // Push the builtins object as receiver.
4535   __ movp(rax, GlobalObjectOperand());
4536   __ Push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
4537
4538   // Load the function from the receiver.
4539   __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
4540   __ Move(LoadDescriptor::NameRegister(), expr->name());
4541   __ Move(LoadDescriptor::SlotRegister(),
4542           SmiFromSlot(expr->CallRuntimeFeedbackSlot()));
4543   CallLoadIC(NOT_INSIDE_TYPEOF);
4544 }
4545
4546
4547 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
4548   ZoneList<Expression*>* args = expr->arguments();
4549   int arg_count = args->length();
4550
4551   SetCallPosition(expr, arg_count);
4552   CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
4553   __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
4554   __ CallStub(&stub);
4555 }
4556
4557
4558 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
4559   ZoneList<Expression*>* args = expr->arguments();
4560   int arg_count = args->length();
4561
4562   if (expr->is_jsruntime()) {
4563     Comment cmnt(masm_, "[ CallRuntime");
4564
4565     EmitLoadJSRuntimeFunction(expr);
4566
4567     // Push the target function under the receiver.
4568     __ Push(Operand(rsp, 0));
4569     __ movp(Operand(rsp, kPointerSize), rax);
4570
4571     // Push the arguments ("left-to-right").
4572     for (int i = 0; i < arg_count; i++) {
4573       VisitForStackValue(args->at(i));
4574     }
4575
4576     PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
4577     EmitCallJSRuntimeFunction(expr);
4578
4579     // Restore context register.
4580     __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4581     context()->DropAndPlug(1, rax);
4582
4583   } else {
4584     const Runtime::Function* function = expr->function();
4585     switch (function->function_id) {
4586 #define CALL_INTRINSIC_GENERATOR(Name)     \
4587   case Runtime::kInline##Name: {           \
4588     Comment cmnt(masm_, "[ Inline" #Name); \
4589     return Emit##Name(expr);               \
4590   }
4591       FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR)
4592 #undef CALL_INTRINSIC_GENERATOR
4593       default: {
4594         Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic");
4595         // Push the arguments ("left-to-right").
4596         for (int i = 0; i < arg_count; i++) {
4597           VisitForStackValue(args->at(i));
4598         }
4599
4600         // Call the C runtime.
4601         PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
4602         __ CallRuntime(function, arg_count);
4603         context()->Plug(rax);
4604       }
4605     }
4606   }
4607 }
4608
4609
4610 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4611   switch (expr->op()) {
4612     case Token::DELETE: {
4613       Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
4614       Property* property = expr->expression()->AsProperty();
4615       VariableProxy* proxy = expr->expression()->AsVariableProxy();
4616
4617       if (property != NULL) {
4618         VisitForStackValue(property->obj());
4619         VisitForStackValue(property->key());
4620         __ Push(Smi::FromInt(language_mode()));
4621         __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4622         context()->Plug(rax);
4623       } else if (proxy != NULL) {
4624         Variable* var = proxy->var();
4625         // Delete of an unqualified identifier is disallowed in strict mode but
4626         // "delete this" is allowed.
4627         bool is_this = var->HasThisName(isolate());
4628         DCHECK(is_sloppy(language_mode()) || is_this);
4629         if (var->IsUnallocatedOrGlobalSlot()) {
4630           __ Push(GlobalObjectOperand());
4631           __ Push(var->name());
4632           __ Push(Smi::FromInt(SLOPPY));
4633           __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4634           context()->Plug(rax);
4635         } else if (var->IsStackAllocated() || var->IsContextSlot()) {
4636           // Result of deleting non-global variables is false.  'this' is
4637           // not really a variable, though we implement it as one.  The
4638           // subexpression does not have side effects.
4639           context()->Plug(is_this);
4640         } else {
4641           // Non-global variable.  Call the runtime to try to delete from the
4642           // context where the variable was introduced.
4643           __ Push(context_register());
4644           __ Push(var->name());
4645           __ CallRuntime(Runtime::kDeleteLookupSlot, 2);
4646           context()->Plug(rax);
4647         }
4648       } else {
4649         // Result of deleting non-property, non-variable reference is true.
4650         // The subexpression may have side effects.
4651         VisitForEffect(expr->expression());
4652         context()->Plug(true);
4653       }
4654       break;
4655     }
4656
4657     case Token::VOID: {
4658       Comment cmnt(masm_, "[ UnaryOperation (VOID)");
4659       VisitForEffect(expr->expression());
4660       context()->Plug(Heap::kUndefinedValueRootIndex);
4661       break;
4662     }
4663
4664     case Token::NOT: {
4665       Comment cmnt(masm_, "[ UnaryOperation (NOT)");
4666       if (context()->IsEffect()) {
4667         // Unary NOT has no side effects so it's only necessary to visit the
4668         // subexpression.  Match the optimizing compiler by not branching.
4669         VisitForEffect(expr->expression());
4670       } else if (context()->IsTest()) {
4671         const TestContext* test = TestContext::cast(context());
4672         // The labels are swapped for the recursive call.
4673         VisitForControl(expr->expression(),
4674                         test->false_label(),
4675                         test->true_label(),
4676                         test->fall_through());
4677         context()->Plug(test->true_label(), test->false_label());
4678       } else {
4679         // We handle value contexts explicitly rather than simply visiting
4680         // for control and plugging the control flow into the context,
4681         // because we need to prepare a pair of extra administrative AST ids
4682         // for the optimizing compiler.
4683         DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
4684         Label materialize_true, materialize_false, done;
4685         VisitForControl(expr->expression(),
4686                         &materialize_false,
4687                         &materialize_true,
4688                         &materialize_true);
4689         __ bind(&materialize_true);
4690         PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
4691         if (context()->IsAccumulatorValue()) {
4692           __ LoadRoot(rax, Heap::kTrueValueRootIndex);
4693         } else {
4694           __ PushRoot(Heap::kTrueValueRootIndex);
4695         }
4696         __ jmp(&done, Label::kNear);
4697         __ bind(&materialize_false);
4698         PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
4699         if (context()->IsAccumulatorValue()) {
4700           __ LoadRoot(rax, Heap::kFalseValueRootIndex);
4701         } else {
4702           __ PushRoot(Heap::kFalseValueRootIndex);
4703         }
4704         __ bind(&done);
4705       }
4706       break;
4707     }
4708
4709     case Token::TYPEOF: {
4710       Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
4711       {
4712         AccumulatorValueContext context(this);
4713         VisitForTypeofValue(expr->expression());
4714       }
4715       __ movp(rbx, rax);
4716       TypeofStub typeof_stub(isolate());
4717       __ CallStub(&typeof_stub);
4718       context()->Plug(rax);
4719       break;
4720     }
4721
4722     default:
4723       UNREACHABLE();
4724   }
4725 }
4726
4727
4728 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
4729   DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
4730
4731   Comment cmnt(masm_, "[ CountOperation");
4732
4733   Property* prop = expr->expression()->AsProperty();
4734   LhsKind assign_type = Property::GetAssignType(prop);
4735
4736   // Evaluate expression and get value.
4737   if (assign_type == VARIABLE) {
4738     DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
4739     AccumulatorValueContext context(this);
4740     EmitVariableLoad(expr->expression()->AsVariableProxy());
4741   } else {
4742     // Reserve space for result of postfix operation.
4743     if (expr->is_postfix() && !context()->IsEffect()) {
4744       __ Push(Smi::FromInt(0));
4745     }
4746     switch (assign_type) {
4747       case NAMED_PROPERTY: {
4748         VisitForStackValue(prop->obj());
4749         __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
4750         EmitNamedPropertyLoad(prop);
4751         break;
4752       }
4753
4754       case NAMED_SUPER_PROPERTY: {
4755         VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
4756         VisitForAccumulatorValue(
4757             prop->obj()->AsSuperPropertyReference()->home_object());
4758         __ Push(result_register());
4759         __ Push(MemOperand(rsp, kPointerSize));
4760         __ Push(result_register());
4761         EmitNamedSuperPropertyLoad(prop);
4762         break;
4763       }
4764
4765       case KEYED_SUPER_PROPERTY: {
4766         VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
4767         VisitForStackValue(
4768             prop->obj()->AsSuperPropertyReference()->home_object());
4769         VisitForAccumulatorValue(prop->key());
4770         __ Push(result_register());
4771         __ Push(MemOperand(rsp, 2 * kPointerSize));
4772         __ Push(MemOperand(rsp, 2 * kPointerSize));
4773         __ Push(result_register());
4774         EmitKeyedSuperPropertyLoad(prop);
4775         break;
4776       }
4777
4778       case KEYED_PROPERTY: {
4779         VisitForStackValue(prop->obj());
4780         VisitForStackValue(prop->key());
4781         // Leave receiver on stack
4782         __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize));
4783         // Copy of key, needed for later store.
4784         __ movp(LoadDescriptor::NameRegister(), Operand(rsp, 0));
4785         EmitKeyedPropertyLoad(prop);
4786         break;
4787       }
4788
4789       case VARIABLE:
4790         UNREACHABLE();
4791     }
4792   }
4793
4794   // We need a second deoptimization point after loading the value
4795   // in case evaluating the property load my have a side effect.
4796   if (assign_type == VARIABLE) {
4797     PrepareForBailout(expr->expression(), TOS_REG);
4798   } else {
4799     PrepareForBailoutForId(prop->LoadId(), TOS_REG);
4800   }
4801
4802   // Inline smi case if we are in a loop.
4803   Label done, stub_call;
4804   JumpPatchSite patch_site(masm_);
4805   if (ShouldInlineSmiCase(expr->op())) {
4806     Label slow;
4807     patch_site.EmitJumpIfNotSmi(rax, &slow, Label::kNear);
4808
4809     // Save result for postfix expressions.
4810     if (expr->is_postfix()) {
4811       if (!context()->IsEffect()) {
4812         // Save the result on the stack. If we have a named or keyed property
4813         // we store the result under the receiver that is currently on top
4814         // of the stack.
4815         switch (assign_type) {
4816           case VARIABLE:
4817             __ Push(rax);
4818             break;
4819           case NAMED_PROPERTY:
4820             __ movp(Operand(rsp, kPointerSize), rax);
4821             break;
4822           case NAMED_SUPER_PROPERTY:
4823             __ movp(Operand(rsp, 2 * kPointerSize), rax);
4824             break;
4825           case KEYED_PROPERTY:
4826             __ movp(Operand(rsp, 2 * kPointerSize), rax);
4827             break;
4828           case KEYED_SUPER_PROPERTY:
4829             __ movp(Operand(rsp, 3 * kPointerSize), rax);
4830             break;
4831         }
4832       }
4833     }
4834
4835     SmiOperationConstraints constraints =
4836         SmiOperationConstraint::kPreserveSourceRegister |
4837         SmiOperationConstraint::kBailoutOnNoOverflow;
4838     if (expr->op() == Token::INC) {
4839       __ SmiAddConstant(rax, rax, Smi::FromInt(1), constraints, &done,
4840                         Label::kNear);
4841     } else {
4842       __ SmiSubConstant(rax, rax, Smi::FromInt(1), constraints, &done,
4843                         Label::kNear);
4844     }
4845     __ jmp(&stub_call, Label::kNear);
4846     __ bind(&slow);
4847   }
4848   if (!is_strong(language_mode())) {
4849     ToNumberStub convert_stub(isolate());
4850     __ CallStub(&convert_stub);
4851     PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
4852   }
4853
4854   // Save result for postfix expressions.
4855   if (expr->is_postfix()) {
4856     if (!context()->IsEffect()) {
4857       // Save the result on the stack. If we have a named or keyed property
4858       // we store the result under the receiver that is currently on top
4859       // of the stack.
4860       switch (assign_type) {
4861         case VARIABLE:
4862           __ Push(rax);
4863           break;
4864         case NAMED_PROPERTY:
4865           __ movp(Operand(rsp, kPointerSize), rax);
4866           break;
4867         case NAMED_SUPER_PROPERTY:
4868           __ movp(Operand(rsp, 2 * kPointerSize), rax);
4869           break;
4870         case KEYED_PROPERTY:
4871           __ movp(Operand(rsp, 2 * kPointerSize), rax);
4872           break;
4873         case KEYED_SUPER_PROPERTY:
4874           __ movp(Operand(rsp, 3 * kPointerSize), rax);
4875           break;
4876       }
4877     }
4878   }
4879
4880   SetExpressionPosition(expr);
4881
4882   // Call stub for +1/-1.
4883   __ bind(&stub_call);
4884   __ movp(rdx, rax);
4885   __ Move(rax, Smi::FromInt(1));
4886   Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), expr->binary_op(),
4887                                               strength(language_mode())).code();
4888   CallIC(code, expr->CountBinOpFeedbackId());
4889   patch_site.EmitPatchInfo();
4890   __ bind(&done);
4891
4892   if (is_strong(language_mode())) {
4893     PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
4894   }
4895   // Store the value returned in rax.
4896   switch (assign_type) {
4897     case VARIABLE:
4898       if (expr->is_postfix()) {
4899         // Perform the assignment as if via '='.
4900         { EffectContext context(this);
4901           EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4902                                  Token::ASSIGN, expr->CountSlot());
4903           PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4904           context.Plug(rax);
4905         }
4906         // For all contexts except kEffect: We have the result on
4907         // top of the stack.
4908         if (!context()->IsEffect()) {
4909           context()->PlugTOS();
4910         }
4911       } else {
4912         // Perform the assignment as if via '='.
4913         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4914                                Token::ASSIGN, expr->CountSlot());
4915         PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4916         context()->Plug(rax);
4917       }
4918       break;
4919     case NAMED_PROPERTY: {
4920       __ Move(StoreDescriptor::NameRegister(),
4921               prop->key()->AsLiteral()->value());
4922       __ Pop(StoreDescriptor::ReceiverRegister());
4923       if (FLAG_vector_stores) {
4924         EmitLoadStoreICSlot(expr->CountSlot());
4925         CallStoreIC();
4926       } else {
4927         CallStoreIC(expr->CountStoreFeedbackId());
4928       }
4929       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4930       if (expr->is_postfix()) {
4931         if (!context()->IsEffect()) {
4932           context()->PlugTOS();
4933         }
4934       } else {
4935         context()->Plug(rax);
4936       }
4937       break;
4938     }
4939     case NAMED_SUPER_PROPERTY: {
4940       EmitNamedSuperPropertyStore(prop);
4941       if (expr->is_postfix()) {
4942         if (!context()->IsEffect()) {
4943           context()->PlugTOS();
4944         }
4945       } else {
4946         context()->Plug(rax);
4947       }
4948       break;
4949     }
4950     case KEYED_SUPER_PROPERTY: {
4951       EmitKeyedSuperPropertyStore(prop);
4952       if (expr->is_postfix()) {
4953         if (!context()->IsEffect()) {
4954           context()->PlugTOS();
4955         }
4956       } else {
4957         context()->Plug(rax);
4958       }
4959       break;
4960     }
4961     case KEYED_PROPERTY: {
4962       __ Pop(StoreDescriptor::NameRegister());
4963       __ Pop(StoreDescriptor::ReceiverRegister());
4964       Handle<Code> ic =
4965           CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
4966       if (FLAG_vector_stores) {
4967         EmitLoadStoreICSlot(expr->CountSlot());
4968         CallIC(ic);
4969       } else {
4970         CallIC(ic, expr->CountStoreFeedbackId());
4971       }
4972       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4973       if (expr->is_postfix()) {
4974         if (!context()->IsEffect()) {
4975           context()->PlugTOS();
4976         }
4977       } else {
4978         context()->Plug(rax);
4979       }
4980       break;
4981     }
4982   }
4983 }
4984
4985
4986 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
4987                                                  Expression* sub_expr,
4988                                                  Handle<String> check) {
4989   Label materialize_true, materialize_false;
4990   Label* if_true = NULL;
4991   Label* if_false = NULL;
4992   Label* fall_through = NULL;
4993   context()->PrepareTest(&materialize_true, &materialize_false,
4994                          &if_true, &if_false, &fall_through);
4995
4996   { AccumulatorValueContext context(this);
4997     VisitForTypeofValue(sub_expr);
4998   }
4999   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
5000
5001   Factory* factory = isolate()->factory();
5002   if (String::Equals(check, factory->number_string())) {
5003     __ JumpIfSmi(rax, if_true);
5004     __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
5005     __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
5006     Split(equal, if_true, if_false, fall_through);
5007   } else if (String::Equals(check, factory->string_string())) {
5008     __ JumpIfSmi(rax, if_false);
5009     // Check for undetectable objects => false.
5010     __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
5011     __ j(above_equal, if_false);
5012     __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
5013              Immediate(1 << Map::kIsUndetectable));
5014     Split(zero, if_true, if_false, fall_through);
5015   } else if (String::Equals(check, factory->symbol_string())) {
5016     __ JumpIfSmi(rax, if_false);
5017     __ CmpObjectType(rax, SYMBOL_TYPE, rdx);
5018     Split(equal, if_true, if_false, fall_through);
5019   } else if (String::Equals(check, factory->float32x4_string())) {
5020     __ JumpIfSmi(rax, if_false);
5021     __ CmpObjectType(rax, FLOAT32X4_TYPE, rdx);
5022     Split(equal, if_true, if_false, fall_through);
5023   } else if (String::Equals(check, factory->boolean_string())) {
5024     __ CompareRoot(rax, Heap::kTrueValueRootIndex);
5025     __ j(equal, if_true);
5026     __ CompareRoot(rax, Heap::kFalseValueRootIndex);
5027     Split(equal, if_true, if_false, fall_through);
5028   } else if (String::Equals(check, factory->undefined_string())) {
5029     __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
5030     __ j(equal, if_true);
5031     __ JumpIfSmi(rax, if_false);
5032     // Check for undetectable objects => true.
5033     __ movp(rdx, FieldOperand(rax, HeapObject::kMapOffset));
5034     __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
5035              Immediate(1 << Map::kIsUndetectable));
5036     Split(not_zero, if_true, if_false, fall_through);
5037   } else if (String::Equals(check, factory->function_string())) {
5038     __ JumpIfSmi(rax, if_false);
5039     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
5040     __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx);
5041     __ j(equal, if_true);
5042     __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE);
5043     Split(equal, if_true, if_false, fall_through);
5044   } else if (String::Equals(check, factory->object_string())) {
5045     __ JumpIfSmi(rax, if_false);
5046     __ CompareRoot(rax, Heap::kNullValueRootIndex);
5047     __ j(equal, if_true);
5048     __ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx);
5049     __ j(below, if_false);
5050     __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
5051     __ j(above, if_false);
5052     // Check for undetectable objects => false.
5053     __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
5054              Immediate(1 << Map::kIsUndetectable));
5055     Split(zero, if_true, if_false, fall_through);
5056   } else {
5057     if (if_false != fall_through) __ jmp(if_false);
5058   }
5059   context()->Plug(if_true, if_false);
5060 }
5061
5062
5063 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
5064   Comment cmnt(masm_, "[ CompareOperation");
5065   SetExpressionPosition(expr);
5066
5067   // First we try a fast inlined version of the compare when one of
5068   // the operands is a literal.
5069   if (TryLiteralCompare(expr)) return;
5070
5071   // Always perform the comparison for its control flow.  Pack the result
5072   // into the expression's context after the comparison is performed.
5073   Label materialize_true, materialize_false;
5074   Label* if_true = NULL;
5075   Label* if_false = NULL;
5076   Label* fall_through = NULL;
5077   context()->PrepareTest(&materialize_true, &materialize_false,
5078                          &if_true, &if_false, &fall_through);
5079
5080   Token::Value op = expr->op();
5081   VisitForStackValue(expr->left());
5082   switch (op) {
5083     case Token::IN:
5084       VisitForStackValue(expr->right());
5085       __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
5086       PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
5087       __ CompareRoot(rax, Heap::kTrueValueRootIndex);
5088       Split(equal, if_true, if_false, fall_through);
5089       break;
5090
5091     case Token::INSTANCEOF: {
5092       VisitForStackValue(expr->right());
5093       InstanceofStub stub(isolate(), InstanceofStub::kNoFlags);
5094       __ CallStub(&stub);
5095       PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
5096       __ testp(rax, rax);
5097        // The stub returns 0 for true.
5098       Split(zero, if_true, if_false, fall_through);
5099       break;
5100     }
5101
5102     default: {
5103       VisitForAccumulatorValue(expr->right());
5104       Condition cc = CompareIC::ComputeCondition(op);
5105       __ Pop(rdx);
5106
5107       bool inline_smi_code = ShouldInlineSmiCase(op);
5108       JumpPatchSite patch_site(masm_);
5109       if (inline_smi_code) {
5110         Label slow_case;
5111         __ movp(rcx, rdx);
5112         __ orp(rcx, rax);
5113         patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
5114         __ cmpp(rdx, rax);
5115         Split(cc, if_true, if_false, NULL);
5116         __ bind(&slow_case);
5117       }
5118
5119       Handle<Code> ic = CodeFactory::CompareIC(
5120                             isolate(), op, strength(language_mode())).code();
5121       CallIC(ic, expr->CompareOperationFeedbackId());
5122       patch_site.EmitPatchInfo();
5123
5124       PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
5125       __ testp(rax, rax);
5126       Split(cc, if_true, if_false, fall_through);
5127     }
5128   }
5129
5130   // Convert the result of the comparison into one expected for this
5131   // expression's context.
5132   context()->Plug(if_true, if_false);
5133 }
5134
5135
5136 void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
5137                                               Expression* sub_expr,
5138                                               NilValue nil) {
5139   Label materialize_true, materialize_false;
5140   Label* if_true = NULL;
5141   Label* if_false = NULL;
5142   Label* fall_through = NULL;
5143   context()->PrepareTest(&materialize_true, &materialize_false,
5144                          &if_true, &if_false, &fall_through);
5145
5146   VisitForAccumulatorValue(sub_expr);
5147   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
5148   if (expr->op() == Token::EQ_STRICT) {
5149     Heap::RootListIndex nil_value = nil == kNullValue ?
5150         Heap::kNullValueRootIndex :
5151         Heap::kUndefinedValueRootIndex;
5152     __ CompareRoot(rax, nil_value);
5153     Split(equal, if_true, if_false, fall_through);
5154   } else {
5155     Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
5156     CallIC(ic, expr->CompareOperationFeedbackId());
5157     __ testp(rax, rax);
5158     Split(not_zero, if_true, if_false, fall_through);
5159   }
5160   context()->Plug(if_true, if_false);
5161 }
5162
5163
5164 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
5165   __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
5166   context()->Plug(rax);
5167 }
5168
5169
5170 Register FullCodeGenerator::result_register() {
5171   return rax;
5172 }
5173
5174
5175 Register FullCodeGenerator::context_register() {
5176   return rsi;
5177 }
5178
5179
5180 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
5181   DCHECK(IsAligned(frame_offset, kPointerSize));
5182   __ movp(Operand(rbp, frame_offset), value);
5183 }
5184
5185
5186 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
5187   __ movp(dst, ContextOperand(rsi, context_index));
5188 }
5189
5190
5191 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
5192   Scope* closure_scope = scope()->ClosureScope();
5193   if (closure_scope->is_script_scope() ||
5194       closure_scope->is_module_scope()) {
5195     // Contexts nested in the native context have a canonical empty function
5196     // as their closure, not the anonymous closure containing the global
5197     // code.  Pass a smi sentinel and let the runtime look up the empty
5198     // function.
5199     __ Push(Smi::FromInt(0));
5200   } else if (closure_scope->is_eval_scope()) {
5201     // Contexts created by a call to eval have the same closure as the
5202     // context calling eval, not the anonymous closure containing the eval
5203     // code.  Fetch it from the context.
5204     __ Push(ContextOperand(rsi, Context::CLOSURE_INDEX));
5205   } else {
5206     DCHECK(closure_scope->is_function_scope());
5207     __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
5208   }
5209 }
5210
5211
5212 // ----------------------------------------------------------------------------
5213 // Non-local control flow support.
5214
5215
5216 void FullCodeGenerator::EnterFinallyBlock() {
5217   DCHECK(!result_register().is(rdx));
5218   DCHECK(!result_register().is(rcx));
5219   // Cook return address on top of stack (smi encoded Code* delta)
5220   __ PopReturnAddressTo(rdx);
5221   __ Move(rcx, masm_->CodeObject());
5222   __ subp(rdx, rcx);
5223   __ Integer32ToSmi(rdx, rdx);
5224   __ Push(rdx);
5225
5226   // Store result register while executing finally block.
5227   __ Push(result_register());
5228
5229   // Store pending message while executing finally block.
5230   ExternalReference pending_message_obj =
5231       ExternalReference::address_of_pending_message_obj(isolate());
5232   __ Load(rdx, pending_message_obj);
5233   __ Push(rdx);
5234
5235   ClearPendingMessage();
5236 }
5237
5238
5239 void FullCodeGenerator::ExitFinallyBlock() {
5240   DCHECK(!result_register().is(rdx));
5241   DCHECK(!result_register().is(rcx));
5242   // Restore pending message from stack.
5243   __ Pop(rdx);
5244   ExternalReference pending_message_obj =
5245       ExternalReference::address_of_pending_message_obj(isolate());
5246   __ Store(pending_message_obj, rdx);
5247
5248   // Restore result register from stack.
5249   __ Pop(result_register());
5250
5251   // Uncook return address.
5252   __ Pop(rdx);
5253   __ SmiToInteger32(rdx, rdx);
5254   __ Move(rcx, masm_->CodeObject());
5255   __ addp(rdx, rcx);
5256   __ jmp(rdx);
5257 }
5258
5259
5260 void FullCodeGenerator::ClearPendingMessage() {
5261   DCHECK(!result_register().is(rdx));
5262   ExternalReference pending_message_obj =
5263       ExternalReference::address_of_pending_message_obj(isolate());
5264   __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
5265   __ Store(pending_message_obj, rdx);
5266 }
5267
5268
5269 void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
5270   DCHECK(FLAG_vector_stores && !slot.IsInvalid());
5271   __ Move(VectorStoreICTrampolineDescriptor::SlotRegister(), SmiFromSlot(slot));
5272 }
5273
5274
5275 #undef __
5276
5277
5278 static const byte kJnsInstruction = 0x79;
5279 static const byte kNopByteOne = 0x66;
5280 static const byte kNopByteTwo = 0x90;
5281 #ifdef DEBUG
5282 static const byte kCallInstruction = 0xe8;
5283 #endif
5284
5285
5286 void BackEdgeTable::PatchAt(Code* unoptimized_code,
5287                             Address pc,
5288                             BackEdgeState target_state,
5289                             Code* replacement_code) {
5290   Address call_target_address = pc - kIntSize;
5291   Address jns_instr_address = call_target_address - 3;
5292   Address jns_offset_address = call_target_address - 2;
5293
5294   switch (target_state) {
5295     case INTERRUPT:
5296       //     sub <profiling_counter>, <delta>  ;; Not changed
5297       //     jns ok
5298       //     call <interrupt stub>
5299       //   ok:
5300       *jns_instr_address = kJnsInstruction;
5301       *jns_offset_address = kJnsOffset;
5302       break;
5303     case ON_STACK_REPLACEMENT:
5304     case OSR_AFTER_STACK_CHECK:
5305       //     sub <profiling_counter>, <delta>  ;; Not changed
5306       //     nop
5307       //     nop
5308       //     call <on-stack replacment>
5309       //   ok:
5310       *jns_instr_address = kNopByteOne;
5311       *jns_offset_address = kNopByteTwo;
5312       break;
5313   }
5314
5315   Assembler::set_target_address_at(call_target_address,
5316                                    unoptimized_code,
5317                                    replacement_code->entry());
5318   unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
5319       unoptimized_code, call_target_address, replacement_code);
5320 }
5321
5322
5323 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
5324     Isolate* isolate,
5325     Code* unoptimized_code,
5326     Address pc) {
5327   Address call_target_address = pc - kIntSize;
5328   Address jns_instr_address = call_target_address - 3;
5329   DCHECK_EQ(kCallInstruction, *(call_target_address - 1));
5330
5331   if (*jns_instr_address == kJnsInstruction) {
5332     DCHECK_EQ(kJnsOffset, *(call_target_address - 2));
5333     DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(),
5334               Assembler::target_address_at(call_target_address,
5335                                            unoptimized_code));
5336     return INTERRUPT;
5337   }
5338
5339   DCHECK_EQ(kNopByteOne, *jns_instr_address);
5340   DCHECK_EQ(kNopByteTwo, *(call_target_address - 2));
5341
5342   if (Assembler::target_address_at(call_target_address,
5343                                    unoptimized_code) ==
5344       isolate->builtins()->OnStackReplacement()->entry()) {
5345     return ON_STACK_REPLACEMENT;
5346   }
5347
5348   DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
5349             Assembler::target_address_at(call_target_address,
5350                                          unoptimized_code));
5351   return OSR_AFTER_STACK_CHECK;
5352 }
5353
5354
5355 }  // namespace internal
5356 }  // namespace v8
5357
5358 #endif  // V8_TARGET_ARCH_X64