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