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