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