1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#if V8_TARGET_ARCH_IA32
6
7#include "src/ast/compile-time-value.h"
8#include "src/ast/scopes.h"
9#include "src/builtins/builtins-constructor.h"
10#include "src/code-factory.h"
11#include "src/code-stubs.h"
12#include "src/codegen.h"
13#include "src/compilation-info.h"
14#include "src/compiler.h"
15#include "src/debug/debug.h"
16#include "src/full-codegen/full-codegen.h"
17#include "src/ia32/frames-ia32.h"
18#include "src/ic/ic.h"
19
20namespace v8 {
21namespace internal {
22
23#define __ ACCESS_MASM(masm())
24
25class JumpPatchSite BASE_EMBEDDED {
26 public:
27  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
28#ifdef DEBUG
29    info_emitted_ = false;
30#endif
31  }
32
33  ~JumpPatchSite() {
34    DCHECK(patch_site_.is_bound() == info_emitted_);
35  }
36
37  void EmitJumpIfNotSmi(Register reg,
38                        Label* target,
39                        Label::Distance distance = Label::kFar) {
40    __ test(reg, Immediate(kSmiTagMask));
41    EmitJump(not_carry, target, distance);  // Always taken before patched.
42  }
43
44  void EmitJumpIfSmi(Register reg,
45                     Label* target,
46                     Label::Distance distance = Label::kFar) {
47    __ test(reg, Immediate(kSmiTagMask));
48    EmitJump(carry, target, distance);  // Never taken before patched.
49  }
50
51  void EmitPatchInfo() {
52    if (patch_site_.is_bound()) {
53      int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
54      DCHECK(is_uint8(delta_to_patch_site));
55      __ test(eax, Immediate(delta_to_patch_site));
56#ifdef DEBUG
57      info_emitted_ = true;
58#endif
59    } else {
60      __ nop();  // Signals no inlined code.
61    }
62  }
63
64 private:
65  // jc will be patched with jz, jnc will become jnz.
66  void EmitJump(Condition cc, Label* target, Label::Distance distance) {
67    DCHECK(!patch_site_.is_bound() && !info_emitted_);
68    DCHECK(cc == carry || cc == not_carry);
69    __ bind(&patch_site_);
70    __ j(cc, target, distance);
71  }
72
73  MacroAssembler* masm() { return masm_; }
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 edi: the JS function object being called (i.e. ourselves)
89//   o edx: the new target value
90//   o esi: our context
91//   o ebp: our caller's frame pointer
92//   o esp: stack pointer (pointing to return address)
93//
94// The function builds a JS frame.  Please see JavaScriptFrameConstants in
95// frames-ia32.h for its layout.
96void FullCodeGenerator::Generate() {
97  CompilationInfo* info = info_;
98  profiling_counter_ = isolate()->factory()->NewCell(
99      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
100  SetFunctionPosition(literal());
101  Comment cmnt(masm_, "[ function compiled by full code generator");
102
103  ProfileEntryHookStub::MaybeCallEntryHook(masm_);
104
105  if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
106    int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
107    __ mov(ecx, Operand(esp, receiver_offset));
108    __ AssertNotSmi(ecx);
109    __ CmpObjectType(ecx, FIRST_JS_RECEIVER_TYPE, ecx);
110    __ Assert(above_equal, kSloppyFunctionExpectsJSReceiverReceiver);
111  }
112
113  // Open a frame scope to indicate that there is a frame on the stack.  The
114  // MANUAL indicates that the scope shouldn't actually generate code to set up
115  // the frame (that is done below).
116  FrameScope frame_scope(masm_, StackFrame::MANUAL);
117
118  info->set_prologue_offset(masm_->pc_offset());
119  __ Prologue(info->GeneratePreagedPrologue());
120
121  // Increment invocation count for the function.
122  {
123    Comment cmnt(masm_, "[ Increment invocation count");
124    __ mov(ecx, FieldOperand(edi, JSFunction::kFeedbackVectorOffset));
125    __ mov(ecx, FieldOperand(ecx, Cell::kValueOffset));
126    __ add(
127        FieldOperand(ecx, FeedbackVector::kInvocationCountIndex * kPointerSize +
128                              FeedbackVector::kHeaderSize),
129        Immediate(Smi::FromInt(1)));
130  }
131
132  { Comment cmnt(masm_, "[ Allocate locals");
133    int locals_count = info->scope()->num_stack_slots();
134    OperandStackDepthIncrement(locals_count);
135    if (locals_count == 1) {
136      __ push(Immediate(isolate()->factory()->undefined_value()));
137    } else if (locals_count > 1) {
138      if (locals_count >= 128) {
139        Label ok;
140        __ mov(ecx, esp);
141        __ sub(ecx, Immediate(locals_count * kPointerSize));
142        ExternalReference stack_limit =
143            ExternalReference::address_of_real_stack_limit(isolate());
144        __ cmp(ecx, Operand::StaticVariable(stack_limit));
145        __ j(above_equal, &ok, Label::kNear);
146        __ CallRuntime(Runtime::kThrowStackOverflow);
147        __ bind(&ok);
148      }
149      __ mov(eax, Immediate(isolate()->factory()->undefined_value()));
150      const int kMaxPushes = 32;
151      if (locals_count >= kMaxPushes) {
152        int loop_iterations = locals_count / kMaxPushes;
153        __ mov(ecx, loop_iterations);
154        Label loop_header;
155        __ bind(&loop_header);
156        // Do pushes.
157        for (int i = 0; i < kMaxPushes; i++) {
158          __ push(eax);
159        }
160        __ dec(ecx);
161        __ j(not_zero, &loop_header, Label::kNear);
162      }
163      int remaining = locals_count % kMaxPushes;
164      // Emit the remaining pushes.
165      for (int i  = 0; i < remaining; i++) {
166        __ push(eax);
167      }
168    }
169  }
170
171  bool function_in_register = true;
172
173  // Possibly allocate a local context.
174  if (info->scope()->NeedsContext()) {
175    Comment cmnt(masm_, "[ Allocate context");
176    bool need_write_barrier = true;
177    int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
178    // Argument to NewContext is the function, which is still in edi.
179    if (info->scope()->is_script_scope()) {
180      __ push(edi);
181      __ Push(info->scope()->scope_info());
182      __ CallRuntime(Runtime::kNewScriptContext);
183      PrepareForBailoutForId(BailoutId::ScriptContext(),
184                             BailoutState::TOS_REGISTER);
185      // The new target value is not used, clobbering is safe.
186      DCHECK_NULL(info->scope()->new_target_var());
187    } else {
188      if (info->scope()->new_target_var() != nullptr) {
189        __ push(edx);  // Preserve new target.
190      }
191      if (slots <=
192          ConstructorBuiltinsAssembler::MaximumFunctionContextSlots()) {
193        Callable callable = CodeFactory::FastNewFunctionContext(
194            isolate(), info->scope()->scope_type());
195        __ mov(FastNewFunctionContextDescriptor::SlotsRegister(),
196               Immediate(slots));
197        __ Call(callable.code(), RelocInfo::CODE_TARGET);
198        // Result of the FastNewFunctionContext builtin is always in new space.
199        need_write_barrier = false;
200      } else {
201        __ push(edi);
202        __ Push(Smi::FromInt(info->scope()->scope_type()));
203        __ CallRuntime(Runtime::kNewFunctionContext);
204      }
205      if (info->scope()->new_target_var() != nullptr) {
206        __ pop(edx);  // Restore new target.
207      }
208    }
209    function_in_register = false;
210    // Context is returned in eax.  It replaces the context passed to us.
211    // It's saved in the stack and kept live in esi.
212    __ mov(esi, eax);
213    __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax);
214
215    // Copy parameters into context if necessary.
216    int num_parameters = info->scope()->num_parameters();
217    int first_parameter = info->scope()->has_this_declaration() ? -1 : 0;
218    for (int i = first_parameter; i < num_parameters; i++) {
219      Variable* var =
220          (i == -1) ? info->scope()->receiver() : info->scope()->parameter(i);
221      if (var->IsContextSlot()) {
222        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
223            (num_parameters - 1 - i) * kPointerSize;
224        // Load parameter from stack.
225        __ mov(eax, Operand(ebp, parameter_offset));
226        // Store it in the context.
227        int context_offset = Context::SlotOffset(var->index());
228        __ mov(Operand(esi, context_offset), eax);
229        // Update the write barrier. This clobbers eax and ebx.
230        if (need_write_barrier) {
231          __ RecordWriteContextSlot(esi,
232                                    context_offset,
233                                    eax,
234                                    ebx,
235                                    kDontSaveFPRegs);
236        } else if (FLAG_debug_code) {
237          Label done;
238          __ JumpIfInNewSpace(esi, eax, &done, Label::kNear);
239          __ Abort(kExpectedNewSpaceObject);
240          __ bind(&done);
241        }
242      }
243    }
244  }
245
246  // Register holding this function and new target are both trashed in case we
247  // bailout here. But since that can happen only when new target is not used
248  // and we allocate a context, the value of |function_in_register| is correct.
249  PrepareForBailoutForId(BailoutId::FunctionContext(),
250                         BailoutState::NO_REGISTERS);
251
252  // We don't support new.target and rest parameters here.
253  DCHECK_NULL(info->scope()->new_target_var());
254  DCHECK_NULL(info->scope()->rest_parameter());
255  DCHECK_NULL(info->scope()->this_function_var());
256
257  Variable* arguments = info->scope()->arguments();
258  if (arguments != NULL) {
259    // Arguments object must be allocated after the context object, in
260    // case the "arguments" or ".arguments" variables are in the context.
261    Comment cmnt(masm_, "[ Allocate arguments object");
262    if (!function_in_register) {
263      __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
264    }
265    if (is_strict(language_mode()) || !has_simple_parameters()) {
266      __ call(isolate()->builtins()->FastNewStrictArguments(),
267              RelocInfo::CODE_TARGET);
268      RestoreContext();
269    } else if (literal()->has_duplicate_parameters()) {
270      __ Push(edi);
271      __ CallRuntime(Runtime::kNewSloppyArguments_Generic);
272    } else {
273      __ call(isolate()->builtins()->FastNewSloppyArguments(),
274              RelocInfo::CODE_TARGET);
275      RestoreContext();
276    }
277
278    SetVar(arguments, eax, ebx, edx);
279  }
280
281  if (FLAG_trace) {
282    __ CallRuntime(Runtime::kTraceEnter);
283  }
284
285  // Visit the declarations and body.
286  PrepareForBailoutForId(BailoutId::FunctionEntry(),
287                         BailoutState::NO_REGISTERS);
288  {
289    Comment cmnt(masm_, "[ Declarations");
290    VisitDeclarations(info->scope()->declarations());
291  }
292
293  // Assert that the declarations do not use ICs. Otherwise the debugger
294  // won't be able to redirect a PC at an IC to the correct IC in newly
295  // recompiled code.
296  DCHECK_EQ(0, ic_total_count_);
297
298  {
299    Comment cmnt(masm_, "[ Stack check");
300    PrepareForBailoutForId(BailoutId::Declarations(),
301                           BailoutState::NO_REGISTERS);
302    Label ok;
303    ExternalReference stack_limit =
304        ExternalReference::address_of_stack_limit(isolate());
305    __ cmp(esp, Operand::StaticVariable(stack_limit));
306    __ j(above_equal, &ok, Label::kNear);
307    __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET);
308    __ bind(&ok);
309  }
310
311  {
312    Comment cmnt(masm_, "[ Body");
313    DCHECK(loop_depth() == 0);
314    VisitStatements(literal()->body());
315    DCHECK(loop_depth() == 0);
316  }
317
318  // Always emit a 'return undefined' in case control fell off the end of
319  // the body.
320  { Comment cmnt(masm_, "[ return <undefined>;");
321    __ mov(eax, isolate()->factory()->undefined_value());
322    EmitReturnSequence();
323  }
324}
325
326
327void FullCodeGenerator::ClearAccumulator() {
328  __ Move(eax, Immediate(Smi::kZero));
329}
330
331
332void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
333  __ mov(ebx, Immediate(profiling_counter_));
334  __ sub(FieldOperand(ebx, Cell::kValueOffset),
335         Immediate(Smi::FromInt(delta)));
336}
337
338
339void FullCodeGenerator::EmitProfilingCounterReset() {
340  int reset_value = FLAG_interrupt_budget;
341  __ mov(ebx, Immediate(profiling_counter_));
342  __ mov(FieldOperand(ebx, Cell::kValueOffset),
343         Immediate(Smi::FromInt(reset_value)));
344}
345
346
347void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
348                                                Label* back_edge_target) {
349  Comment cmnt(masm_, "[ Back edge bookkeeping");
350  Label ok;
351
352  DCHECK(back_edge_target->is_bound());
353  int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
354  int weight = Min(kMaxBackEdgeWeight,
355                   Max(1, distance / kCodeSizeMultiplier));
356  EmitProfilingCounterDecrement(weight);
357  __ j(positive, &ok, Label::kNear);
358  __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
359
360  // Record a mapping of this PC offset to the OSR id.  This is used to find
361  // the AST id from the unoptimized code in order to use it as a key into
362  // the deoptimization input data found in the optimized code.
363  RecordBackEdge(stmt->OsrEntryId());
364
365  EmitProfilingCounterReset();
366
367  __ bind(&ok);
368  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
369  // Record a mapping of the OSR id to this PC.  This is used if the OSR
370  // entry becomes the target of a bailout.  We don't expect it to be, but
371  // we want it to work if it is.
372  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
373}
374
375void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
376    bool is_tail_call) {
377  // Pretend that the exit is a backwards jump to the entry.
378  int weight = 1;
379  if (info_->ShouldSelfOptimize()) {
380    weight = FLAG_interrupt_budget / FLAG_self_opt_count;
381  } else {
382    int distance = masm_->pc_offset();
383    weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier));
384  }
385  EmitProfilingCounterDecrement(weight);
386  Label ok;
387  __ j(positive, &ok, Label::kNear);
388  // Don't need to save result register if we are going to do a tail call.
389  if (!is_tail_call) {
390    __ push(eax);
391  }
392  __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
393  if (!is_tail_call) {
394    __ pop(eax);
395  }
396  EmitProfilingCounterReset();
397  __ bind(&ok);
398}
399
400void FullCodeGenerator::EmitReturnSequence() {
401  Comment cmnt(masm_, "[ Return sequence");
402  if (return_label_.is_bound()) {
403    __ jmp(&return_label_);
404  } else {
405    // Common return label
406    __ bind(&return_label_);
407    if (FLAG_trace) {
408      __ push(eax);
409      __ CallRuntime(Runtime::kTraceExit);
410    }
411    EmitProfilingCounterHandlingForReturnSequence(false);
412
413    SetReturnPosition(literal());
414    __ leave();
415
416    int arg_count = info_->scope()->num_parameters() + 1;
417    int arguments_bytes = arg_count * kPointerSize;
418    __ Ret(arguments_bytes, ecx);
419  }
420}
421
422void FullCodeGenerator::RestoreContext() {
423  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
424}
425
426void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
427  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
428  MemOperand operand = codegen()->VarOperand(var, result_register());
429  // Memory operands can be pushed directly.
430  codegen()->PushOperand(operand);
431}
432
433
434void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
435  UNREACHABLE();  // Not used on IA32.
436}
437
438
439void FullCodeGenerator::AccumulatorValueContext::Plug(
440    Heap::RootListIndex index) const {
441  UNREACHABLE();  // Not used on IA32.
442}
443
444
445void FullCodeGenerator::StackValueContext::Plug(
446    Heap::RootListIndex index) const {
447  UNREACHABLE();  // Not used on IA32.
448}
449
450
451void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
452  UNREACHABLE();  // Not used on IA32.
453}
454
455
456void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
457}
458
459
460void FullCodeGenerator::AccumulatorValueContext::Plug(
461    Handle<Object> lit) const {
462  if (lit->IsSmi()) {
463    __ SafeMove(result_register(), Immediate(lit));
464  } else {
465    __ Move(result_register(), Immediate(lit));
466  }
467}
468
469
470void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
471  codegen()->OperandStackDepthIncrement(1);
472  if (lit->IsSmi()) {
473    __ SafePush(Immediate(lit));
474  } else {
475    __ push(Immediate(lit));
476  }
477}
478
479
480void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
481  codegen()->PrepareForBailoutBeforeSplit(condition(),
482                                          true,
483                                          true_label_,
484                                          false_label_);
485  DCHECK(lit->IsNullOrUndefined(isolate()) || !lit->IsUndetectable());
486  if (lit->IsNullOrUndefined(isolate()) || lit->IsFalse(isolate())) {
487    if (false_label_ != fall_through_) __ jmp(false_label_);
488  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
489    if (true_label_ != fall_through_) __ jmp(true_label_);
490  } else if (lit->IsString()) {
491    if (String::cast(*lit)->length() == 0) {
492      if (false_label_ != fall_through_) __ jmp(false_label_);
493    } else {
494      if (true_label_ != fall_through_) __ jmp(true_label_);
495    }
496  } else if (lit->IsSmi()) {
497    if (Smi::cast(*lit)->value() == 0) {
498      if (false_label_ != fall_through_) __ jmp(false_label_);
499    } else {
500      if (true_label_ != fall_through_) __ jmp(true_label_);
501    }
502  } else {
503    // For simplicity we always test the accumulator register.
504    __ mov(result_register(), lit);
505    codegen()->DoTest(this);
506  }
507}
508
509
510void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
511                                                       Register reg) const {
512  DCHECK(count > 0);
513  if (count > 1) codegen()->DropOperands(count - 1);
514  __ mov(Operand(esp, 0), reg);
515}
516
517
518void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
519                                            Label* materialize_false) const {
520  DCHECK(materialize_true == materialize_false);
521  __ bind(materialize_true);
522}
523
524
525void FullCodeGenerator::AccumulatorValueContext::Plug(
526    Label* materialize_true,
527    Label* materialize_false) const {
528  Label done;
529  __ bind(materialize_true);
530  __ mov(result_register(), isolate()->factory()->true_value());
531  __ jmp(&done, Label::kNear);
532  __ bind(materialize_false);
533  __ mov(result_register(), isolate()->factory()->false_value());
534  __ bind(&done);
535}
536
537
538void FullCodeGenerator::StackValueContext::Plug(
539    Label* materialize_true,
540    Label* materialize_false) const {
541  codegen()->OperandStackDepthIncrement(1);
542  Label done;
543  __ bind(materialize_true);
544  __ push(Immediate(isolate()->factory()->true_value()));
545  __ jmp(&done, Label::kNear);
546  __ bind(materialize_false);
547  __ push(Immediate(isolate()->factory()->false_value()));
548  __ bind(&done);
549}
550
551
552void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
553                                          Label* materialize_false) const {
554  DCHECK(materialize_true == true_label_);
555  DCHECK(materialize_false == false_label_);
556}
557
558
559void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
560  Handle<Object> value = flag
561      ? isolate()->factory()->true_value()
562      : isolate()->factory()->false_value();
563  __ mov(result_register(), value);
564}
565
566
567void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
568  codegen()->OperandStackDepthIncrement(1);
569  Handle<Object> value = flag
570      ? isolate()->factory()->true_value()
571      : isolate()->factory()->false_value();
572  __ push(Immediate(value));
573}
574
575
576void FullCodeGenerator::TestContext::Plug(bool flag) const {
577  codegen()->PrepareForBailoutBeforeSplit(condition(),
578                                          true,
579                                          true_label_,
580                                          false_label_);
581  if (flag) {
582    if (true_label_ != fall_through_) __ jmp(true_label_);
583  } else {
584    if (false_label_ != fall_through_) __ jmp(false_label_);
585  }
586}
587
588
589void FullCodeGenerator::DoTest(Expression* condition,
590                               Label* if_true,
591                               Label* if_false,
592                               Label* fall_through) {
593  Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
594  CallIC(ic, condition->test_id());
595  __ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
596  Split(equal, if_true, if_false, fall_through);
597}
598
599
600void FullCodeGenerator::Split(Condition cc,
601                              Label* if_true,
602                              Label* if_false,
603                              Label* fall_through) {
604  if (if_false == fall_through) {
605    __ j(cc, if_true);
606  } else if (if_true == fall_through) {
607    __ j(NegateCondition(cc), if_false);
608  } else {
609    __ j(cc, if_true);
610    __ jmp(if_false);
611  }
612}
613
614
615MemOperand FullCodeGenerator::StackOperand(Variable* var) {
616  DCHECK(var->IsStackAllocated());
617  // Offset is negative because higher indexes are at lower addresses.
618  int offset = -var->index() * kPointerSize;
619  // Adjust by a (parameter or local) base offset.
620  if (var->IsParameter()) {
621    offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
622  } else {
623    offset += JavaScriptFrameConstants::kLocal0Offset;
624  }
625  return Operand(ebp, offset);
626}
627
628
629MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
630  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
631  if (var->IsContextSlot()) {
632    int context_chain_length = scope()->ContextChainLength(var->scope());
633    __ LoadContext(scratch, context_chain_length);
634    return ContextOperand(scratch, var->index());
635  } else {
636    return StackOperand(var);
637  }
638}
639
640
641void FullCodeGenerator::GetVar(Register dest, Variable* var) {
642  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
643  MemOperand location = VarOperand(var, dest);
644  __ mov(dest, location);
645}
646
647
648void FullCodeGenerator::SetVar(Variable* var,
649                               Register src,
650                               Register scratch0,
651                               Register scratch1) {
652  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
653  DCHECK(!scratch0.is(src));
654  DCHECK(!scratch0.is(scratch1));
655  DCHECK(!scratch1.is(src));
656  MemOperand location = VarOperand(var, scratch0);
657  __ mov(location, src);
658
659  // Emit the write barrier code if the location is in the heap.
660  if (var->IsContextSlot()) {
661    int offset = Context::SlotOffset(var->index());
662    DCHECK(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi));
663    __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
664  }
665}
666
667
668void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
669                                                     bool should_normalize,
670                                                     Label* if_true,
671                                                     Label* if_false) {
672  // Only prepare for bailouts before splits if we're in a test
673  // context. Otherwise, we let the Visit function deal with the
674  // preparation to avoid preparing with the same AST id twice.
675  if (!context()->IsTest()) return;
676
677  Label skip;
678  if (should_normalize) __ jmp(&skip, Label::kNear);
679  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
680  if (should_normalize) {
681    __ cmp(eax, isolate()->factory()->true_value());
682    Split(equal, if_true, if_false, NULL);
683    __ bind(&skip);
684  }
685}
686
687
688void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
689  // The variable in the declaration always resides in the current context.
690  DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
691  if (FLAG_debug_code) {
692    // Check that we're not inside a with or catch context.
693    __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset));
694    __ cmp(ebx, isolate()->factory()->with_context_map());
695    __ Check(not_equal, kDeclarationInWithContext);
696    __ cmp(ebx, isolate()->factory()->catch_context_map());
697    __ Check(not_equal, kDeclarationInCatchContext);
698  }
699}
700
701
702void FullCodeGenerator::VisitVariableDeclaration(
703    VariableDeclaration* declaration) {
704  VariableProxy* proxy = declaration->proxy();
705  Variable* variable = proxy->var();
706  switch (variable->location()) {
707    case VariableLocation::UNALLOCATED: {
708      DCHECK(!variable->binding_needs_init());
709      globals_->Add(variable->name(), zone());
710      FeedbackSlot slot = proxy->VariableFeedbackSlot();
711      DCHECK(!slot.IsInvalid());
712      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
713      globals_->Add(isolate()->factory()->undefined_value(), zone());
714      globals_->Add(isolate()->factory()->undefined_value(), zone());
715      break;
716    }
717    case VariableLocation::PARAMETER:
718    case VariableLocation::LOCAL:
719      if (variable->binding_needs_init()) {
720        Comment cmnt(masm_, "[ VariableDeclaration");
721        __ mov(StackOperand(variable),
722               Immediate(isolate()->factory()->the_hole_value()));
723      }
724      break;
725
726    case VariableLocation::CONTEXT:
727      if (variable->binding_needs_init()) {
728        Comment cmnt(masm_, "[ VariableDeclaration");
729        EmitDebugCheckDeclarationContext(variable);
730        __ mov(ContextOperand(esi, variable->index()),
731               Immediate(isolate()->factory()->the_hole_value()));
732        // No write barrier since the hole value is in old space.
733        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
734      }
735      break;
736
737    case VariableLocation::LOOKUP:
738    case VariableLocation::MODULE:
739      UNREACHABLE();
740  }
741}
742
743
744void FullCodeGenerator::VisitFunctionDeclaration(
745    FunctionDeclaration* declaration) {
746  VariableProxy* proxy = declaration->proxy();
747  Variable* variable = proxy->var();
748  switch (variable->location()) {
749    case VariableLocation::UNALLOCATED: {
750      globals_->Add(variable->name(), zone());
751      FeedbackSlot slot = proxy->VariableFeedbackSlot();
752      DCHECK(!slot.IsInvalid());
753      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
754
755      // We need the slot where the literals array lives, too.
756      slot = declaration->fun()->LiteralFeedbackSlot();
757      DCHECK(!slot.IsInvalid());
758      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
759
760      Handle<SharedFunctionInfo> function =
761          Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
762      // Check for stack-overflow exception.
763      if (function.is_null()) return SetStackOverflow();
764      globals_->Add(function, zone());
765      break;
766    }
767
768    case VariableLocation::PARAMETER:
769    case VariableLocation::LOCAL: {
770      Comment cmnt(masm_, "[ FunctionDeclaration");
771      VisitForAccumulatorValue(declaration->fun());
772      __ mov(StackOperand(variable), result_register());
773      break;
774    }
775
776    case VariableLocation::CONTEXT: {
777      Comment cmnt(masm_, "[ FunctionDeclaration");
778      EmitDebugCheckDeclarationContext(variable);
779      VisitForAccumulatorValue(declaration->fun());
780      __ mov(ContextOperand(esi, variable->index()), result_register());
781      // We know that we have written a function, which is not a smi.
782      __ RecordWriteContextSlot(esi,
783                                Context::SlotOffset(variable->index()),
784                                result_register(),
785                                ecx,
786                                kDontSaveFPRegs,
787                                EMIT_REMEMBERED_SET,
788                                OMIT_SMI_CHECK);
789      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
790      break;
791    }
792
793    case VariableLocation::LOOKUP:
794    case VariableLocation::MODULE:
795      UNREACHABLE();
796  }
797}
798
799
800void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
801  // Call the runtime to declare the globals.
802  __ Push(pairs);
803  __ Push(Smi::FromInt(DeclareGlobalsFlags()));
804  __ EmitLoadFeedbackVector(eax);
805  __ Push(eax);
806  __ CallRuntime(Runtime::kDeclareGlobals);
807  // Return value is ignored.
808}
809
810
811void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
812  Comment cmnt(masm_, "[ SwitchStatement");
813  Breakable nested_statement(this, stmt);
814  SetStatementPosition(stmt);
815
816  // Keep the switch value on the stack until a case matches.
817  VisitForStackValue(stmt->tag());
818  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
819
820  ZoneList<CaseClause*>* clauses = stmt->cases();
821  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
822
823  Label next_test;  // Recycled for each test.
824  // Compile all the tests with branches to their bodies.
825  for (int i = 0; i < clauses->length(); i++) {
826    CaseClause* clause = clauses->at(i);
827    clause->body_target()->Unuse();
828
829    // The default is not a test, but remember it as final fall through.
830    if (clause->is_default()) {
831      default_clause = clause;
832      continue;
833    }
834
835    Comment cmnt(masm_, "[ Case comparison");
836    __ bind(&next_test);
837    next_test.Unuse();
838
839    // Compile the label expression.
840    VisitForAccumulatorValue(clause->label());
841
842    // Perform the comparison as if via '==='.
843    __ mov(edx, Operand(esp, 0));  // Switch value.
844    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
845    JumpPatchSite patch_site(masm_);
846    if (inline_smi_code) {
847      Label slow_case;
848      __ mov(ecx, edx);
849      __ or_(ecx, eax);
850      patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
851
852      __ cmp(edx, eax);
853      __ j(not_equal, &next_test);
854      __ Drop(1);  // Switch value is no longer needed.
855      __ jmp(clause->body_target());
856      __ bind(&slow_case);
857    }
858
859    SetExpressionPosition(clause);
860    Handle<Code> ic =
861        CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
862    CallIC(ic, clause->CompareId());
863    patch_site.EmitPatchInfo();
864
865    Label skip;
866    __ jmp(&skip, Label::kNear);
867    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
868    __ cmp(eax, isolate()->factory()->true_value());
869    __ j(not_equal, &next_test);
870    __ Drop(1);
871    __ jmp(clause->body_target());
872    __ bind(&skip);
873
874    __ test(eax, eax);
875    __ j(not_equal, &next_test);
876    __ Drop(1);  // Switch value is no longer needed.
877    __ jmp(clause->body_target());
878  }
879
880  // Discard the test value and jump to the default if present, otherwise to
881  // the end of the statement.
882  __ bind(&next_test);
883  DropOperands(1);  // Switch value is no longer needed.
884  if (default_clause == NULL) {
885    __ jmp(nested_statement.break_label());
886  } else {
887    __ jmp(default_clause->body_target());
888  }
889
890  // Compile all the case bodies.
891  for (int i = 0; i < clauses->length(); i++) {
892    Comment cmnt(masm_, "[ Case body");
893    CaseClause* clause = clauses->at(i);
894    __ bind(clause->body_target());
895    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
896    VisitStatements(clause->statements());
897  }
898
899  __ bind(nested_statement.break_label());
900  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
901}
902
903
904void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
905  Comment cmnt(masm_, "[ ForInStatement");
906  SetStatementPosition(stmt, SKIP_BREAK);
907
908  FeedbackSlot slot = stmt->ForInFeedbackSlot();
909
910  // Get the object to enumerate over.
911  SetExpressionAsStatementPosition(stmt->enumerable());
912  VisitForAccumulatorValue(stmt->enumerable());
913  OperandStackDepthIncrement(5);
914
915  Label loop, exit;
916  Iteration loop_statement(this, stmt);
917  increment_loop_depth();
918
919  // If the object is null or undefined, skip over the loop, otherwise convert
920  // it to a JS receiver.  See ECMA-262 version 5, section 12.6.4.
921  Label convert, done_convert;
922  __ JumpIfSmi(eax, &convert, Label::kNear);
923  __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, ecx);
924  __ j(above_equal, &done_convert, Label::kNear);
925  __ cmp(eax, isolate()->factory()->undefined_value());
926  __ j(equal, &exit);
927  __ cmp(eax, isolate()->factory()->null_value());
928  __ j(equal, &exit);
929  __ bind(&convert);
930  __ Call(isolate()->builtins()->ToObject(), RelocInfo::CODE_TARGET);
931  RestoreContext();
932  __ bind(&done_convert);
933  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
934  __ push(eax);
935
936  // Check cache validity in generated code. If we cannot guarantee cache
937  // validity, call the runtime system to check cache validity or get the
938  // property names in a fixed array. Note: Proxies never have an enum cache,
939  // so will always take the slow path.
940  Label call_runtime, use_cache, fixed_array;
941  __ CheckEnumCache(&call_runtime);
942
943  __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
944  __ jmp(&use_cache, Label::kNear);
945
946  // Get the set of properties to enumerate.
947  __ bind(&call_runtime);
948  __ push(eax);
949  __ CallRuntime(Runtime::kForInEnumerate);
950  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
951  __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
952         isolate()->factory()->meta_map());
953  __ j(not_equal, &fixed_array);
954
955
956  // We got a map in register eax. Get the enumeration cache from it.
957  Label no_descriptors;
958  __ bind(&use_cache);
959
960  __ EnumLength(edx, eax);
961  __ cmp(edx, Immediate(Smi::kZero));
962  __ j(equal, &no_descriptors);
963
964  __ LoadInstanceDescriptors(eax, ecx);
965  __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumCacheOffset));
966  __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
967
968  // Set up the four remaining stack slots.
969  __ push(eax);  // Map.
970  __ push(ecx);  // Enumeration cache.
971  __ push(edx);  // Number of valid entries for the map in the enum cache.
972  __ push(Immediate(Smi::kZero));  // Initial index.
973  __ jmp(&loop);
974
975  __ bind(&no_descriptors);
976  __ add(esp, Immediate(kPointerSize));
977  __ jmp(&exit);
978
979  // We got a fixed array in register eax. Iterate through that.
980  __ bind(&fixed_array);
981
982  __ push(Immediate(Smi::FromInt(1)));  // Smi(1) indicates slow check
983  __ push(eax);  // Array
984  __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
985  __ push(eax);  // Fixed array length (as smi).
986  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
987  __ push(Immediate(Smi::kZero));  // Initial index.
988
989  // Generate code for doing the condition check.
990  __ bind(&loop);
991  SetExpressionAsStatementPosition(stmt->each());
992
993  __ mov(eax, Operand(esp, 0 * kPointerSize));  // Get the current index.
994  __ cmp(eax, Operand(esp, 1 * kPointerSize));  // Compare to the array length.
995  __ j(above_equal, loop_statement.break_label());
996
997  // Get the current entry of the array into register eax.
998  __ mov(ebx, Operand(esp, 2 * kPointerSize));
999  __ mov(eax, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize));
1000
1001  // Get the expected map from the stack or a smi in the
1002  // permanent slow case into register edx.
1003  __ mov(edx, Operand(esp, 3 * kPointerSize));
1004
1005  // Check if the expected map still matches that of the enumerable.
1006  // If not, we may have to filter the key.
1007  Label update_each;
1008  __ mov(ebx, Operand(esp, 4 * kPointerSize));
1009  __ cmp(edx, FieldOperand(ebx, HeapObject::kMapOffset));
1010  __ j(equal, &update_each, Label::kNear);
1011
1012  // We need to filter the key, record slow-path here.
1013  int const vector_index = SmiFromSlot(slot)->value();
1014  __ EmitLoadFeedbackVector(edx);
1015  __ mov(FieldOperand(edx, FixedArray::OffsetOfElementAt(vector_index)),
1016         Immediate(FeedbackVector::MegamorphicSentinel(isolate())));
1017
1018  // eax contains the key.  The receiver in ebx is the second argument to the
1019  // ForInFilter.  ForInFilter returns undefined if the receiver doesn't
1020  // have the key or returns the name-converted key.
1021  __ Call(isolate()->builtins()->ForInFilter(), RelocInfo::CODE_TARGET);
1022  RestoreContext();
1023  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
1024  __ JumpIfRoot(result_register(), Heap::kUndefinedValueRootIndex,
1025                loop_statement.continue_label());
1026
1027  // Update the 'each' property or variable from the possibly filtered
1028  // entry in register eax.
1029  __ bind(&update_each);
1030  // Perform the assignment as if via '='.
1031  { EffectContext context(this);
1032    EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
1033    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
1034  }
1035
1036  // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
1037  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
1038  // Generate code for the body of the loop.
1039  Visit(stmt->body());
1040
1041  // Generate code for going to the next element by incrementing the
1042  // index (smi) stored on top of the stack.
1043  __ bind(loop_statement.continue_label());
1044  PrepareForBailoutForId(stmt->IncrementId(), BailoutState::NO_REGISTERS);
1045  __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
1046
1047  EmitBackEdgeBookkeeping(stmt, &loop);
1048  __ jmp(&loop);
1049
1050  // Remove the pointers stored on the stack.
1051  __ bind(loop_statement.break_label());
1052  DropOperands(5);
1053
1054  // Exit and decrement the loop depth.
1055  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
1056  __ bind(&exit);
1057  decrement_loop_depth();
1058}
1059
1060void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
1061                                          FeedbackSlot slot) {
1062  DCHECK(NeedsHomeObject(initializer));
1063  __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
1064  __ mov(StoreDescriptor::ValueRegister(), Operand(esp, offset * kPointerSize));
1065  CallStoreIC(slot, isolate()->factory()->home_object_symbol());
1066}
1067
1068void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer,
1069                                                     int offset,
1070                                                     FeedbackSlot slot) {
1071  DCHECK(NeedsHomeObject(initializer));
1072  __ mov(StoreDescriptor::ReceiverRegister(), eax);
1073  __ mov(StoreDescriptor::ValueRegister(), Operand(esp, offset * kPointerSize));
1074  CallStoreIC(slot, isolate()->factory()->home_object_symbol());
1075}
1076
1077void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
1078                                         TypeofMode typeof_mode) {
1079  SetExpressionPosition(proxy);
1080  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
1081  Variable* var = proxy->var();
1082
1083  // Two cases: global variables and all other types of variables.
1084  switch (var->location()) {
1085    case VariableLocation::UNALLOCATED: {
1086      Comment cmnt(masm_, "[ Global variable");
1087      EmitGlobalVariableLoad(proxy, typeof_mode);
1088      context()->Plug(eax);
1089      break;
1090    }
1091
1092    case VariableLocation::PARAMETER:
1093    case VariableLocation::LOCAL:
1094    case VariableLocation::CONTEXT: {
1095      DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode);
1096      Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
1097                                               : "[ Stack variable");
1098
1099      if (proxy->hole_check_mode() == HoleCheckMode::kRequired) {
1100        // Throw a reference error when using an uninitialized let/const
1101        // binding in harmony mode.
1102        Label done;
1103        GetVar(eax, var);
1104        __ cmp(eax, isolate()->factory()->the_hole_value());
1105        __ j(not_equal, &done, Label::kNear);
1106        __ push(Immediate(var->name()));
1107        __ CallRuntime(Runtime::kThrowReferenceError);
1108        __ bind(&done);
1109        context()->Plug(eax);
1110        break;
1111      }
1112      context()->Plug(var);
1113      break;
1114    }
1115
1116    case VariableLocation::LOOKUP:
1117    case VariableLocation::MODULE:
1118      UNREACHABLE();
1119  }
1120}
1121
1122
1123void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
1124  Expression* expression = (property == NULL) ? NULL : property->value();
1125  if (expression == NULL) {
1126    PushOperand(isolate()->factory()->null_value());
1127  } else {
1128    VisitForStackValue(expression);
1129    if (NeedsHomeObject(expression)) {
1130      DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
1131             property->kind() == ObjectLiteral::Property::SETTER);
1132      int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
1133      EmitSetHomeObject(expression, offset, property->GetSlot());
1134    }
1135  }
1136}
1137
1138
1139void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1140  Comment cmnt(masm_, "[ ObjectLiteral");
1141
1142  Handle<BoilerplateDescription> constant_properties =
1143      expr->GetOrBuildConstantProperties(isolate());
1144  int flags = expr->ComputeFlags();
1145  // If any of the keys would store to the elements array, then we shouldn't
1146  // allow it.
1147  if (MustCreateObjectLiteralWithRuntime(expr)) {
1148    __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1149    __ push(Immediate(SmiFromSlot(expr->literal_slot())));
1150    __ push(Immediate(constant_properties));
1151    __ push(Immediate(Smi::FromInt(flags)));
1152    __ CallRuntime(Runtime::kCreateObjectLiteral);
1153  } else {
1154    __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1155    __ mov(ebx, Immediate(SmiFromSlot(expr->literal_slot())));
1156    __ mov(ecx, Immediate(constant_properties));
1157    __ mov(edx, Immediate(Smi::FromInt(flags)));
1158    Callable callable = CodeFactory::FastCloneShallowObject(
1159        isolate(), expr->properties_count());
1160    __ Call(callable.code(), RelocInfo::CODE_TARGET);
1161    RestoreContext();
1162  }
1163  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
1164
1165  // If result_saved is true the result is on top of the stack.  If
1166  // result_saved is false the result is in eax.
1167  bool result_saved = false;
1168
1169  AccessorTable accessor_table(zone());
1170  for (int i = 0; i < expr->properties()->length(); i++) {
1171    ObjectLiteral::Property* property = expr->properties()->at(i);
1172    DCHECK(!property->is_computed_name());
1173    if (property->IsCompileTimeValue()) continue;
1174
1175    Literal* key = property->key()->AsLiteral();
1176    Expression* value = property->value();
1177    if (!result_saved) {
1178      PushOperand(eax);  // Save result on the stack
1179      result_saved = true;
1180    }
1181    switch (property->kind()) {
1182      case ObjectLiteral::Property::SPREAD:
1183      case ObjectLiteral::Property::CONSTANT:
1184        UNREACHABLE();
1185      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1186        DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
1187        // Fall through.
1188      case ObjectLiteral::Property::COMPUTED:
1189        // It is safe to use [[Put]] here because the boilerplate already
1190        // contains computed properties with an uninitialized value.
1191        if (key->IsStringLiteral()) {
1192          DCHECK(key->IsPropertyName());
1193          if (property->emit_store()) {
1194            VisitForAccumulatorValue(value);
1195            DCHECK(StoreDescriptor::ValueRegister().is(eax));
1196            __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
1197            CallStoreIC(property->GetSlot(0), key->value(), true);
1198            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
1199            if (NeedsHomeObject(value)) {
1200              EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
1201            }
1202          } else {
1203            VisitForEffect(value);
1204          }
1205          break;
1206        }
1207        PushOperand(Operand(esp, 0));  // Duplicate receiver.
1208        VisitForStackValue(key);
1209        VisitForStackValue(value);
1210        if (property->emit_store()) {
1211          if (NeedsHomeObject(value)) {
1212            EmitSetHomeObject(value, 2, property->GetSlot());
1213          }
1214          PushOperand(Smi::FromInt(SLOPPY));  // Language mode
1215          CallRuntimeWithOperands(Runtime::kSetProperty);
1216        } else {
1217          DropOperands(3);
1218        }
1219        break;
1220      case ObjectLiteral::Property::PROTOTYPE:
1221        PushOperand(Operand(esp, 0));  // Duplicate receiver.
1222        VisitForStackValue(value);
1223        DCHECK(property->emit_store());
1224        CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
1225        PrepareForBailoutForId(expr->GetIdForPropertySet(i),
1226                               BailoutState::NO_REGISTERS);
1227        break;
1228      case ObjectLiteral::Property::GETTER:
1229        if (property->emit_store()) {
1230          AccessorTable::Iterator it = accessor_table.lookup(key);
1231          it->second->bailout_id = expr->GetIdForPropertySet(i);
1232          it->second->getter = property;
1233        }
1234        break;
1235      case ObjectLiteral::Property::SETTER:
1236        if (property->emit_store()) {
1237          AccessorTable::Iterator it = accessor_table.lookup(key);
1238          it->second->bailout_id = expr->GetIdForPropertySet(i);
1239          it->second->setter = property;
1240        }
1241        break;
1242    }
1243  }
1244
1245  // Emit code to define accessors, using only a single call to the runtime for
1246  // each pair of corresponding getters and setters.
1247  for (AccessorTable::Iterator it = accessor_table.begin();
1248       it != accessor_table.end();
1249       ++it) {
1250    PushOperand(Operand(esp, 0));  // Duplicate receiver.
1251    VisitForStackValue(it->first);
1252
1253    EmitAccessor(it->second->getter);
1254    EmitAccessor(it->second->setter);
1255
1256    PushOperand(Smi::FromInt(NONE));
1257    CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
1258    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
1259  }
1260
1261  if (result_saved) {
1262    context()->PlugTOS();
1263  } else {
1264    context()->Plug(eax);
1265  }
1266}
1267
1268
1269void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1270  Comment cmnt(masm_, "[ ArrayLiteral");
1271
1272  Handle<ConstantElementsPair> constant_elements =
1273      expr->GetOrBuildConstantElements(isolate());
1274
1275  if (MustCreateArrayLiteralWithRuntime(expr)) {
1276    __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1277    __ push(Immediate(SmiFromSlot(expr->literal_slot())));
1278    __ push(Immediate(constant_elements));
1279    __ push(Immediate(Smi::FromInt(expr->ComputeFlags())));
1280    __ CallRuntime(Runtime::kCreateArrayLiteral);
1281  } else {
1282    __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1283    __ mov(ebx, Immediate(SmiFromSlot(expr->literal_slot())));
1284    __ mov(ecx, Immediate(constant_elements));
1285    Callable callable =
1286        CodeFactory::FastCloneShallowArray(isolate(), TRACK_ALLOCATION_SITE);
1287    __ Call(callable.code(), RelocInfo::CODE_TARGET);
1288    RestoreContext();
1289  }
1290  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
1291
1292  bool result_saved = false;  // Is the result saved to the stack?
1293  ZoneList<Expression*>* subexprs = expr->values();
1294  int length = subexprs->length();
1295
1296  // Emit code to evaluate all the non-constant subexpressions and to store
1297  // them into the newly cloned array.
1298  for (int array_index = 0; array_index < length; array_index++) {
1299    Expression* subexpr = subexprs->at(array_index);
1300    DCHECK(!subexpr->IsSpread());
1301
1302    // If the subexpression is a literal or a simple materialized literal it
1303    // is already set in the cloned array.
1304    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1305
1306    if (!result_saved) {
1307      PushOperand(eax);  // array literal.
1308      result_saved = true;
1309    }
1310    VisitForAccumulatorValue(subexpr);
1311
1312    __ mov(StoreDescriptor::NameRegister(),
1313           Immediate(Smi::FromInt(array_index)));
1314    __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
1315    CallKeyedStoreIC(expr->LiteralFeedbackSlot());
1316    PrepareForBailoutForId(expr->GetIdForElement(array_index),
1317                           BailoutState::NO_REGISTERS);
1318  }
1319
1320  if (result_saved) {
1321    context()->PlugTOS();
1322  } else {
1323    context()->Plug(eax);
1324  }
1325}
1326
1327
1328void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1329  DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
1330
1331  Comment cmnt(masm_, "[ Assignment");
1332
1333  Property* property = expr->target()->AsProperty();
1334  LhsKind assign_type = Property::GetAssignType(property);
1335
1336  // Evaluate LHS expression.
1337  switch (assign_type) {
1338    case VARIABLE:
1339      // Nothing to do here.
1340      break;
1341    case NAMED_PROPERTY:
1342      if (expr->is_compound()) {
1343        // We need the receiver both on the stack and in the register.
1344        VisitForStackValue(property->obj());
1345        __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
1346      } else {
1347        VisitForStackValue(property->obj());
1348      }
1349      break;
1350    case KEYED_PROPERTY: {
1351      if (expr->is_compound()) {
1352        VisitForStackValue(property->obj());
1353        VisitForStackValue(property->key());
1354        __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, kPointerSize));
1355        __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0));
1356      } else {
1357        VisitForStackValue(property->obj());
1358        VisitForStackValue(property->key());
1359      }
1360      break;
1361    }
1362    case NAMED_SUPER_PROPERTY:
1363    case KEYED_SUPER_PROPERTY:
1364      UNREACHABLE();
1365      break;
1366  }
1367
1368  // For compound assignments we need another deoptimization point after the
1369  // variable/property load.
1370  if (expr->is_compound()) {
1371    AccumulatorValueContext result_context(this);
1372    { AccumulatorValueContext left_operand_context(this);
1373      switch (assign_type) {
1374        case VARIABLE:
1375          EmitVariableLoad(expr->target()->AsVariableProxy());
1376          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
1377          break;
1378        case NAMED_PROPERTY:
1379          EmitNamedPropertyLoad(property);
1380          PrepareForBailoutForId(property->LoadId(),
1381                                 BailoutState::TOS_REGISTER);
1382          break;
1383        case KEYED_PROPERTY:
1384          EmitKeyedPropertyLoad(property);
1385          PrepareForBailoutForId(property->LoadId(),
1386                                 BailoutState::TOS_REGISTER);
1387          break;
1388        case NAMED_SUPER_PROPERTY:
1389        case KEYED_SUPER_PROPERTY:
1390          UNREACHABLE();
1391          break;
1392      }
1393    }
1394
1395    Token::Value op = expr->binary_op();
1396    PushOperand(eax);  // Left operand goes on the stack.
1397    VisitForAccumulatorValue(expr->value());
1398
1399    if (ShouldInlineSmiCase(op)) {
1400      EmitInlineSmiBinaryOp(expr->binary_operation(),
1401                            op,
1402                            expr->target(),
1403                            expr->value());
1404    } else {
1405      EmitBinaryOp(expr->binary_operation(), op);
1406    }
1407
1408    // Deoptimization point in case the binary operation may have side effects.
1409    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
1410  } else {
1411    VisitForAccumulatorValue(expr->value());
1412  }
1413
1414  SetExpressionPosition(expr);
1415
1416  // Store the value.
1417  switch (assign_type) {
1418    case VARIABLE: {
1419      VariableProxy* proxy = expr->target()->AsVariableProxy();
1420      EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(),
1421                             proxy->hole_check_mode());
1422      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
1423      context()->Plug(eax);
1424      break;
1425    }
1426    case NAMED_PROPERTY:
1427      EmitNamedPropertyAssignment(expr);
1428      break;
1429    case KEYED_PROPERTY:
1430      EmitKeyedPropertyAssignment(expr);
1431      break;
1432    case NAMED_SUPER_PROPERTY:
1433    case KEYED_SUPER_PROPERTY:
1434      UNREACHABLE();
1435      break;
1436  }
1437}
1438
1439
1440void FullCodeGenerator::VisitYield(Yield* expr) {
1441  // Resumable functions are not supported.
1442  UNREACHABLE();
1443}
1444
1445void FullCodeGenerator::PushOperand(MemOperand operand) {
1446  OperandStackDepthIncrement(1);
1447  __ Push(operand);
1448}
1449
1450void FullCodeGenerator::EmitOperandStackDepthCheck() {
1451  if (FLAG_debug_code) {
1452    int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp +
1453                        operand_stack_depth_ * kPointerSize;
1454    __ mov(eax, ebp);
1455    __ sub(eax, esp);
1456    __ cmp(eax, Immediate(expected_diff));
1457    __ Assert(equal, kUnexpectedStackDepth);
1458  }
1459}
1460
1461void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
1462  Label allocate, done_allocate;
1463
1464  __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate,
1465              NO_ALLOCATION_FLAGS);
1466  __ jmp(&done_allocate, Label::kNear);
1467
1468  __ bind(&allocate);
1469  __ Push(Smi::FromInt(JSIteratorResult::kSize));
1470  __ CallRuntime(Runtime::kAllocateInNewSpace);
1471
1472  __ bind(&done_allocate);
1473  __ mov(ebx, NativeContextOperand());
1474  __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX));
1475  __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
1476  __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
1477         isolate()->factory()->empty_fixed_array());
1478  __ mov(FieldOperand(eax, JSObject::kElementsOffset),
1479         isolate()->factory()->empty_fixed_array());
1480  __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset));
1481  __ mov(FieldOperand(eax, JSIteratorResult::kDoneOffset),
1482         isolate()->factory()->ToBoolean(done));
1483  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
1484  OperandStackDepthDecrement(1);
1485}
1486
1487
1488void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
1489                                              Token::Value op,
1490                                              Expression* left,
1491                                              Expression* right) {
1492  // Do combined smi check of the operands. Left operand is on the
1493  // stack. Right operand is in eax.
1494  Label smi_case, done, stub_call;
1495  PopOperand(edx);
1496  __ mov(ecx, eax);
1497  __ or_(eax, edx);
1498  JumpPatchSite patch_site(masm_);
1499  patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear);
1500
1501  __ bind(&stub_call);
1502  __ mov(eax, ecx);
1503  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
1504  CallIC(code, expr->BinaryOperationFeedbackId());
1505  patch_site.EmitPatchInfo();
1506  __ jmp(&done, Label::kNear);
1507
1508  // Smi case.
1509  __ bind(&smi_case);
1510  __ mov(eax, edx);  // Copy left operand in case of a stub call.
1511
1512  switch (op) {
1513    case Token::SAR:
1514      __ SmiUntag(ecx);
1515      __ sar_cl(eax);  // No checks of result necessary
1516      __ and_(eax, Immediate(~kSmiTagMask));
1517      break;
1518    case Token::SHL: {
1519      Label result_ok;
1520      __ SmiUntag(eax);
1521      __ SmiUntag(ecx);
1522      __ shl_cl(eax);
1523      // Check that the *signed* result fits in a smi.
1524      __ cmp(eax, 0xc0000000);
1525      __ j(positive, &result_ok);
1526      __ SmiTag(ecx);
1527      __ jmp(&stub_call);
1528      __ bind(&result_ok);
1529      __ SmiTag(eax);
1530      break;
1531    }
1532    case Token::SHR: {
1533      Label result_ok;
1534      __ SmiUntag(eax);
1535      __ SmiUntag(ecx);
1536      __ shr_cl(eax);
1537      __ test(eax, Immediate(0xc0000000));
1538      __ j(zero, &result_ok);
1539      __ SmiTag(ecx);
1540      __ jmp(&stub_call);
1541      __ bind(&result_ok);
1542      __ SmiTag(eax);
1543      break;
1544    }
1545    case Token::ADD:
1546      __ add(eax, ecx);
1547      __ j(overflow, &stub_call);
1548      break;
1549    case Token::SUB:
1550      __ sub(eax, ecx);
1551      __ j(overflow, &stub_call);
1552      break;
1553    case Token::MUL: {
1554      __ SmiUntag(eax);
1555      __ imul(eax, ecx);
1556      __ j(overflow, &stub_call);
1557      __ test(eax, eax);
1558      __ j(not_zero, &done, Label::kNear);
1559      __ mov(ebx, edx);
1560      __ or_(ebx, ecx);
1561      __ j(negative, &stub_call);
1562      break;
1563    }
1564    case Token::BIT_OR:
1565      __ or_(eax, ecx);
1566      break;
1567    case Token::BIT_AND:
1568      __ and_(eax, ecx);
1569      break;
1570    case Token::BIT_XOR:
1571      __ xor_(eax, ecx);
1572      break;
1573    default:
1574      UNREACHABLE();
1575  }
1576
1577  __ bind(&done);
1578  context()->Plug(eax);
1579}
1580
1581void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
1582  PopOperand(edx);
1583  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
1584  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
1585  CallIC(code, expr->BinaryOperationFeedbackId());
1586  patch_site.EmitPatchInfo();
1587  context()->Plug(eax);
1588}
1589
1590void FullCodeGenerator::EmitAssignment(Expression* expr, FeedbackSlot slot) {
1591  DCHECK(expr->IsValidReferenceExpressionOrThis());
1592
1593  Property* prop = expr->AsProperty();
1594  LhsKind assign_type = Property::GetAssignType(prop);
1595
1596  switch (assign_type) {
1597    case VARIABLE: {
1598      VariableProxy* proxy = expr->AsVariableProxy();
1599      EffectContext context(this);
1600      EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot,
1601                             proxy->hole_check_mode());
1602      break;
1603    }
1604    case NAMED_PROPERTY: {
1605      PushOperand(eax);  // Preserve value.
1606      VisitForAccumulatorValue(prop->obj());
1607      __ Move(StoreDescriptor::ReceiverRegister(), eax);
1608      PopOperand(StoreDescriptor::ValueRegister());  // Restore value.
1609      CallStoreIC(slot, prop->key()->AsLiteral()->value());
1610      break;
1611    }
1612    case KEYED_PROPERTY: {
1613      PushOperand(eax);  // Preserve value.
1614      VisitForStackValue(prop->obj());
1615      VisitForAccumulatorValue(prop->key());
1616      __ Move(StoreDescriptor::NameRegister(), eax);
1617      PopOperand(StoreDescriptor::ReceiverRegister());  // Receiver.
1618      PopOperand(StoreDescriptor::ValueRegister());     // Restore value.
1619      CallKeyedStoreIC(slot);
1620      break;
1621    }
1622    case NAMED_SUPER_PROPERTY:
1623    case KEYED_SUPER_PROPERTY:
1624      UNREACHABLE();
1625      break;
1626  }
1627  context()->Plug(eax);
1628}
1629
1630
1631void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
1632    Variable* var, MemOperand location) {
1633  __ mov(location, eax);
1634  if (var->IsContextSlot()) {
1635    __ mov(edx, eax);
1636    int offset = Context::SlotOffset(var->index());
1637    __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs);
1638  }
1639}
1640
1641void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
1642                                               FeedbackSlot slot,
1643                                               HoleCheckMode hole_check_mode) {
1644  if (var->IsUnallocated()) {
1645    // Global var, const, or let.
1646    __ mov(StoreDescriptor::ReceiverRegister(), NativeContextOperand());
1647    __ mov(StoreDescriptor::ReceiverRegister(),
1648           ContextOperand(StoreDescriptor::ReceiverRegister(),
1649                          Context::EXTENSION_INDEX));
1650    CallStoreIC(slot, var->name());
1651
1652  } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
1653    DCHECK(!var->IsLookupSlot());
1654    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
1655    MemOperand location = VarOperand(var, ecx);
1656    // Perform an initialization check for lexically declared variables.
1657    if (hole_check_mode == HoleCheckMode::kRequired) {
1658      Label assign;
1659      __ mov(edx, location);
1660      __ cmp(edx, isolate()->factory()->the_hole_value());
1661      __ j(not_equal, &assign, Label::kNear);
1662      __ push(Immediate(var->name()));
1663      __ CallRuntime(Runtime::kThrowReferenceError);
1664      __ bind(&assign);
1665    }
1666    if (var->mode() != CONST) {
1667      EmitStoreToStackLocalOrContextSlot(var, location);
1668    } else if (var->throw_on_const_assignment(language_mode())) {
1669      __ CallRuntime(Runtime::kThrowConstAssignError);
1670    }
1671  } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) {
1672    // Initializing assignment to const {this} needs a write barrier.
1673    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
1674    Label uninitialized_this;
1675    MemOperand location = VarOperand(var, ecx);
1676    __ mov(edx, location);
1677    __ cmp(edx, isolate()->factory()->the_hole_value());
1678    __ j(equal, &uninitialized_this);
1679    __ push(Immediate(var->name()));
1680    __ CallRuntime(Runtime::kThrowReferenceError);
1681    __ bind(&uninitialized_this);
1682    EmitStoreToStackLocalOrContextSlot(var, location);
1683
1684  } else {
1685    DCHECK(var->mode() != CONST || op == Token::INIT);
1686    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
1687    DCHECK(!var->IsLookupSlot());
1688    // Assignment to var or initializing assignment to let/const in harmony
1689    // mode.
1690    MemOperand location = VarOperand(var, ecx);
1691    if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) {
1692      // Check for an uninitialized let binding.
1693      __ mov(edx, location);
1694      __ cmp(edx, isolate()->factory()->the_hole_value());
1695      __ Check(equal, kLetBindingReInitialization);
1696    }
1697    EmitStoreToStackLocalOrContextSlot(var, location);
1698  }
1699}
1700
1701
1702void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
1703  // Assignment to a property, using a named store IC.
1704  // eax    : value
1705  // esp[0] : receiver
1706  Property* prop = expr->target()->AsProperty();
1707  DCHECK(prop != NULL);
1708  DCHECK(prop->key()->IsLiteral());
1709
1710  PopOperand(StoreDescriptor::ReceiverRegister());
1711  CallStoreIC(expr->AssignmentSlot(), prop->key()->AsLiteral()->value());
1712  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
1713  context()->Plug(eax);
1714}
1715
1716
1717void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1718  // Assignment to a property, using a keyed store IC.
1719  // eax               : value
1720  // esp[0]            : key
1721  // esp[kPointerSize] : receiver
1722
1723  PopOperand(StoreDescriptor::NameRegister());  // Key.
1724  PopOperand(StoreDescriptor::ReceiverRegister());
1725  DCHECK(StoreDescriptor::ValueRegister().is(eax));
1726  CallKeyedStoreIC(expr->AssignmentSlot());
1727  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
1728  context()->Plug(eax);
1729}
1730
1731// Code common for calls using the IC.
1732void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
1733  Expression* callee = expr->expression();
1734
1735  // Get the target function.
1736  ConvertReceiverMode convert_mode;
1737  if (callee->IsVariableProxy()) {
1738    { StackValueContext context(this);
1739      EmitVariableLoad(callee->AsVariableProxy());
1740      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
1741    }
1742    // Push undefined as receiver. This is patched in the method prologue if it
1743    // is a sloppy mode method.
1744    PushOperand(isolate()->factory()->undefined_value());
1745    convert_mode = ConvertReceiverMode::kNullOrUndefined;
1746  } else {
1747    // Load the function from the receiver.
1748    DCHECK(callee->IsProperty());
1749    DCHECK(!callee->AsProperty()->IsSuperAccess());
1750    __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
1751    EmitNamedPropertyLoad(callee->AsProperty());
1752    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
1753                           BailoutState::TOS_REGISTER);
1754    // Push the target function under the receiver.
1755    PushOperand(Operand(esp, 0));
1756    __ mov(Operand(esp, kPointerSize), eax);
1757    convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
1758  }
1759
1760  EmitCall(expr, convert_mode);
1761}
1762
1763
1764// Code common for calls using the IC.
1765void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
1766                                                Expression* key) {
1767  // Load the key.
1768  VisitForAccumulatorValue(key);
1769
1770  Expression* callee = expr->expression();
1771
1772  // Load the function from the receiver.
1773  DCHECK(callee->IsProperty());
1774  __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
1775  __ mov(LoadDescriptor::NameRegister(), eax);
1776  EmitKeyedPropertyLoad(callee->AsProperty());
1777  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
1778                         BailoutState::TOS_REGISTER);
1779
1780  // Push the target function under the receiver.
1781  PushOperand(Operand(esp, 0));
1782  __ mov(Operand(esp, kPointerSize), eax);
1783
1784  EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined);
1785}
1786
1787
1788void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
1789  // Load the arguments.
1790  ZoneList<Expression*>* args = expr->arguments();
1791  int arg_count = args->length();
1792  for (int i = 0; i < arg_count; i++) {
1793    VisitForStackValue(args->at(i));
1794  }
1795
1796  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
1797  SetCallPosition(expr, expr->tail_call_mode());
1798  if (expr->tail_call_mode() == TailCallMode::kAllow) {
1799    if (FLAG_trace) {
1800      __ CallRuntime(Runtime::kTraceTailCall);
1801    }
1802    // Update profiling counters before the tail call since we will
1803    // not return to this function.
1804    EmitProfilingCounterHandlingForReturnSequence(true);
1805  }
1806  Handle<Code> code =
1807      CodeFactory::CallICTrampoline(isolate(), mode, expr->tail_call_mode())
1808          .code();
1809  __ Move(edx, Immediate(IntFromSlot(expr->CallFeedbackICSlot())));
1810  __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
1811  __ Move(eax, Immediate(arg_count));
1812  CallIC(code);
1813  OperandStackDepthDecrement(arg_count + 1);
1814
1815  RecordJSReturnSite(expr);
1816  RestoreContext();
1817  context()->DropAndPlug(1, eax);
1818}
1819
1820void FullCodeGenerator::VisitCallNew(CallNew* expr) {
1821  Comment cmnt(masm_, "[ CallNew");
1822  // According to ECMA-262, section 11.2.2, page 44, the function
1823  // expression in new calls must be evaluated before the
1824  // arguments.
1825
1826  // Push constructor on the stack.  If it's not a function it's used as
1827  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
1828  // ignored.
1829  DCHECK(!expr->expression()->IsSuperPropertyReference());
1830  VisitForStackValue(expr->expression());
1831
1832  // Push the arguments ("left-to-right") on the stack.
1833  ZoneList<Expression*>* args = expr->arguments();
1834  int arg_count = args->length();
1835  for (int i = 0; i < arg_count; i++) {
1836    VisitForStackValue(args->at(i));
1837  }
1838
1839  // Call the construct call builtin that handles allocation and
1840  // constructor invocation.
1841  SetConstructCallPosition(expr);
1842
1843  // Load function and argument count into edi and eax.
1844  __ Move(eax, Immediate(arg_count));
1845  __ mov(edi, Operand(esp, arg_count * kPointerSize));
1846
1847  // Record call targets in unoptimized code.
1848  __ EmitLoadFeedbackVector(ebx);
1849  __ mov(edx, Immediate(SmiFromSlot(expr->CallNewFeedbackSlot())));
1850
1851  CallConstructStub stub(isolate());
1852  CallIC(stub.GetCode());
1853  OperandStackDepthDecrement(arg_count + 1);
1854  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
1855  RestoreContext();
1856  context()->Plug(eax);
1857}
1858
1859
1860void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
1861  ZoneList<Expression*>* args = expr->arguments();
1862  DCHECK(args->length() == 1);
1863
1864  VisitForAccumulatorValue(args->at(0));
1865
1866  Label materialize_true, materialize_false;
1867  Label* if_true = NULL;
1868  Label* if_false = NULL;
1869  Label* fall_through = NULL;
1870  context()->PrepareTest(&materialize_true, &materialize_false,
1871                         &if_true, &if_false, &fall_through);
1872
1873  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
1874  __ test(eax, Immediate(kSmiTagMask));
1875  Split(zero, if_true, if_false, fall_through);
1876
1877  context()->Plug(if_true, if_false);
1878}
1879
1880
1881void FullCodeGenerator::EmitIsJSReceiver(CallRuntime* expr) {
1882  ZoneList<Expression*>* args = expr->arguments();
1883  DCHECK(args->length() == 1);
1884
1885  VisitForAccumulatorValue(args->at(0));
1886
1887  Label materialize_true, materialize_false;
1888  Label* if_true = NULL;
1889  Label* if_false = NULL;
1890  Label* fall_through = NULL;
1891  context()->PrepareTest(&materialize_true, &materialize_false,
1892                         &if_true, &if_false, &fall_through);
1893
1894  __ JumpIfSmi(eax, if_false);
1895  __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, ebx);
1896  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
1897  Split(above_equal, if_true, if_false, fall_through);
1898
1899  context()->Plug(if_true, if_false);
1900}
1901
1902
1903void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
1904  ZoneList<Expression*>* args = expr->arguments();
1905  DCHECK(args->length() == 1);
1906
1907  VisitForAccumulatorValue(args->at(0));
1908
1909  Label materialize_true, materialize_false;
1910  Label* if_true = NULL;
1911  Label* if_false = NULL;
1912  Label* fall_through = NULL;
1913  context()->PrepareTest(&materialize_true, &materialize_false,
1914                         &if_true, &if_false, &fall_through);
1915
1916  __ JumpIfSmi(eax, if_false);
1917  __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
1918  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
1919  Split(equal, if_true, if_false, fall_through);
1920
1921  context()->Plug(if_true, if_false);
1922}
1923
1924
1925void FullCodeGenerator::EmitIsTypedArray(CallRuntime* expr) {
1926  ZoneList<Expression*>* args = expr->arguments();
1927  DCHECK(args->length() == 1);
1928
1929  VisitForAccumulatorValue(args->at(0));
1930
1931  Label materialize_true, materialize_false;
1932  Label* if_true = NULL;
1933  Label* if_false = NULL;
1934  Label* fall_through = NULL;
1935  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
1936                         &if_false, &fall_through);
1937
1938  __ JumpIfSmi(eax, if_false);
1939  __ CmpObjectType(eax, JS_TYPED_ARRAY_TYPE, ebx);
1940  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
1941  Split(equal, if_true, if_false, fall_through);
1942
1943  context()->Plug(if_true, if_false);
1944}
1945
1946
1947void FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) {
1948  ZoneList<Expression*>* args = expr->arguments();
1949  DCHECK(args->length() == 1);
1950
1951  VisitForAccumulatorValue(args->at(0));
1952
1953  Label materialize_true, materialize_false;
1954  Label* if_true = NULL;
1955  Label* if_false = NULL;
1956  Label* fall_through = NULL;
1957  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
1958                         &if_false, &fall_through);
1959
1960  __ JumpIfSmi(eax, if_false);
1961  __ CmpObjectType(eax, JS_PROXY_TYPE, ebx);
1962  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
1963  Split(equal, if_true, if_false, fall_through);
1964
1965  context()->Plug(if_true, if_false);
1966}
1967
1968
1969void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
1970  ZoneList<Expression*>* args = expr->arguments();
1971  DCHECK(args->length() == 1);
1972  Label done, null, function, non_function_constructor;
1973
1974  VisitForAccumulatorValue(args->at(0));
1975
1976  // If the object is not a JSReceiver, we return null.
1977  __ JumpIfSmi(eax, &null, Label::kNear);
1978  STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
1979  __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, eax);
1980  __ j(below, &null, Label::kNear);
1981
1982  // Return 'Function' for JSFunction and JSBoundFunction objects.
1983  __ CmpInstanceType(eax, FIRST_FUNCTION_TYPE);
1984  STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
1985  __ j(above_equal, &function, Label::kNear);
1986
1987  // Check if the constructor in the map is a JS function.
1988  __ GetMapConstructor(eax, eax, ebx);
1989  __ CmpInstanceType(ebx, JS_FUNCTION_TYPE);
1990  __ j(not_equal, &non_function_constructor, Label::kNear);
1991
1992  // eax now contains the constructor function. Grab the
1993  // instance class name from there.
1994  __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
1995  __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset));
1996  __ jmp(&done, Label::kNear);
1997
1998  // Non-JS objects have class null.
1999  __ bind(&null);
2000  __ mov(eax, isolate()->factory()->null_value());
2001  __ jmp(&done, Label::kNear);
2002
2003  // Functions have class 'Function'.
2004  __ bind(&function);
2005  __ mov(eax, isolate()->factory()->Function_string());
2006  __ jmp(&done, Label::kNear);
2007
2008  // Objects with a non-function constructor have class 'Object'.
2009  __ bind(&non_function_constructor);
2010  __ mov(eax, isolate()->factory()->Object_string());
2011
2012  // All done.
2013  __ bind(&done);
2014
2015  context()->Plug(eax);
2016}
2017
2018
2019void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
2020  ZoneList<Expression*>* args = expr->arguments();
2021  DCHECK(args->length() == 2);
2022
2023  VisitForStackValue(args->at(0));
2024  VisitForAccumulatorValue(args->at(1));
2025
2026  Register object = ebx;
2027  Register index = eax;
2028  Register result = edx;
2029
2030  PopOperand(object);
2031
2032  Label need_conversion;
2033  Label index_out_of_range;
2034  Label done;
2035  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
2036                                      &need_conversion, &index_out_of_range);
2037  generator.GenerateFast(masm_);
2038  __ jmp(&done);
2039
2040  __ bind(&index_out_of_range);
2041  // When the index is out of range, the spec requires us to return
2042  // NaN.
2043  __ Move(result, Immediate(isolate()->factory()->nan_value()));
2044  __ jmp(&done);
2045
2046  __ bind(&need_conversion);
2047  // Move the undefined value into the result register, which will
2048  // trigger conversion.
2049  __ Move(result, Immediate(isolate()->factory()->undefined_value()));
2050  __ jmp(&done);
2051
2052  NopRuntimeCallHelper call_helper;
2053  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
2054
2055  __ bind(&done);
2056  context()->Plug(result);
2057}
2058
2059
2060void FullCodeGenerator::EmitCall(CallRuntime* expr) {
2061  ZoneList<Expression*>* args = expr->arguments();
2062  DCHECK_LE(2, args->length());
2063  // Push target, receiver and arguments onto the stack.
2064  for (Expression* const arg : *args) {
2065    VisitForStackValue(arg);
2066  }
2067  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
2068  // Move target to edi.
2069  int const argc = args->length() - 2;
2070  __ mov(edi, Operand(esp, (argc + 1) * kPointerSize));
2071  // Call the target.
2072  __ mov(eax, Immediate(argc));
2073  __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
2074  OperandStackDepthDecrement(argc + 1);
2075  RestoreContext();
2076  // Discard the function left on TOS.
2077  context()->DropAndPlug(1, eax);
2078}
2079
2080void FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) {
2081  ZoneList<Expression*>* args = expr->arguments();
2082  DCHECK_EQ(1, args->length());
2083  VisitForAccumulatorValue(args->at(0));
2084  __ AssertFunction(eax);
2085  __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
2086  __ mov(eax, FieldOperand(eax, Map::kPrototypeOffset));
2087  context()->Plug(eax);
2088}
2089
2090void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
2091  DCHECK(expr->arguments()->length() == 0);
2092  ExternalReference debug_is_active =
2093      ExternalReference::debug_is_active_address(isolate());
2094  __ movzx_b(eax, Operand::StaticVariable(debug_is_active));
2095  __ SmiTag(eax);
2096  context()->Plug(eax);
2097}
2098
2099
2100void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
2101  ZoneList<Expression*>* args = expr->arguments();
2102  DCHECK_EQ(2, args->length());
2103  VisitForStackValue(args->at(0));
2104  VisitForStackValue(args->at(1));
2105
2106  Label runtime, done;
2107
2108  __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &runtime,
2109              NO_ALLOCATION_FLAGS);
2110  __ mov(ebx, NativeContextOperand());
2111  __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX));
2112  __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
2113  __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
2114         isolate()->factory()->empty_fixed_array());
2115  __ mov(FieldOperand(eax, JSObject::kElementsOffset),
2116         isolate()->factory()->empty_fixed_array());
2117  __ pop(FieldOperand(eax, JSIteratorResult::kDoneOffset));
2118  __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset));
2119  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
2120  __ jmp(&done, Label::kNear);
2121
2122  __ bind(&runtime);
2123  CallRuntimeWithOperands(Runtime::kCreateIterResultObject);
2124
2125  __ bind(&done);
2126  context()->Plug(eax);
2127}
2128
2129
2130void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
2131  // Push function.
2132  __ LoadGlobalFunction(expr->context_index(), eax);
2133  PushOperand(eax);
2134
2135  // Push undefined as receiver.
2136  PushOperand(isolate()->factory()->undefined_value());
2137}
2138
2139
2140void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
2141  ZoneList<Expression*>* args = expr->arguments();
2142  int arg_count = args->length();
2143
2144  SetCallPosition(expr);
2145  __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2146  __ Set(eax, arg_count);
2147  __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
2148          RelocInfo::CODE_TARGET);
2149  OperandStackDepthDecrement(arg_count + 1);
2150  RestoreContext();
2151}
2152
2153
2154void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2155  switch (expr->op()) {
2156    case Token::DELETE: {
2157      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2158      Property* property = expr->expression()->AsProperty();
2159      VariableProxy* proxy = expr->expression()->AsVariableProxy();
2160
2161      if (property != NULL) {
2162        VisitForStackValue(property->obj());
2163        VisitForStackValue(property->key());
2164        CallRuntimeWithOperands(is_strict(language_mode())
2165                                    ? Runtime::kDeleteProperty_Strict
2166                                    : Runtime::kDeleteProperty_Sloppy);
2167        context()->Plug(eax);
2168      } else if (proxy != NULL) {
2169        Variable* var = proxy->var();
2170        // Delete of an unqualified identifier is disallowed in strict mode but
2171        // "delete this" is allowed.
2172        bool is_this = var->is_this();
2173        DCHECK(is_sloppy(language_mode()) || is_this);
2174        if (var->IsUnallocated()) {
2175          __ mov(eax, NativeContextOperand());
2176          __ push(ContextOperand(eax, Context::EXTENSION_INDEX));
2177          __ push(Immediate(var->name()));
2178          __ CallRuntime(Runtime::kDeleteProperty_Sloppy);
2179          context()->Plug(eax);
2180        } else {
2181          DCHECK(!var->IsLookupSlot());
2182          DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2183          // Result of deleting non-global variables is false.  'this' is
2184          // not really a variable, though we implement it as one.  The
2185          // subexpression does not have side effects.
2186          context()->Plug(is_this);
2187        }
2188      } else {
2189        // Result of deleting non-property, non-variable reference is true.
2190        // The subexpression may have side effects.
2191        VisitForEffect(expr->expression());
2192        context()->Plug(true);
2193      }
2194      break;
2195    }
2196
2197    case Token::VOID: {
2198      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
2199      VisitForEffect(expr->expression());
2200      context()->Plug(isolate()->factory()->undefined_value());
2201      break;
2202    }
2203
2204    case Token::NOT: {
2205      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2206      if (context()->IsEffect()) {
2207        // Unary NOT has no side effects so it's only necessary to visit the
2208        // subexpression.  Match the optimizing compiler by not branching.
2209        VisitForEffect(expr->expression());
2210      } else if (context()->IsTest()) {
2211        const TestContext* test = TestContext::cast(context());
2212        // The labels are swapped for the recursive call.
2213        VisitForControl(expr->expression(),
2214                        test->false_label(),
2215                        test->true_label(),
2216                        test->fall_through());
2217        context()->Plug(test->true_label(), test->false_label());
2218      } else {
2219        // We handle value contexts explicitly rather than simply visiting
2220        // for control and plugging the control flow into the context,
2221        // because we need to prepare a pair of extra administrative AST ids
2222        // for the optimizing compiler.
2223        DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
2224        Label materialize_true, materialize_false, done;
2225        VisitForControl(expr->expression(),
2226                        &materialize_false,
2227                        &materialize_true,
2228                        &materialize_true);
2229        if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
2230        __ bind(&materialize_true);
2231        PrepareForBailoutForId(expr->MaterializeTrueId(),
2232                               BailoutState::NO_REGISTERS);
2233        if (context()->IsAccumulatorValue()) {
2234          __ mov(eax, isolate()->factory()->true_value());
2235        } else {
2236          __ Push(isolate()->factory()->true_value());
2237        }
2238        __ jmp(&done, Label::kNear);
2239        __ bind(&materialize_false);
2240        PrepareForBailoutForId(expr->MaterializeFalseId(),
2241                               BailoutState::NO_REGISTERS);
2242        if (context()->IsAccumulatorValue()) {
2243          __ mov(eax, isolate()->factory()->false_value());
2244        } else {
2245          __ Push(isolate()->factory()->false_value());
2246        }
2247        __ bind(&done);
2248      }
2249      break;
2250    }
2251
2252    case Token::TYPEOF: {
2253      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2254      {
2255        AccumulatorValueContext context(this);
2256        VisitForTypeofValue(expr->expression());
2257      }
2258      __ mov(ebx, eax);
2259      __ Call(isolate()->builtins()->Typeof(), RelocInfo::CODE_TARGET);
2260      context()->Plug(eax);
2261      break;
2262    }
2263
2264    default:
2265      UNREACHABLE();
2266  }
2267}
2268
2269
2270void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
2271  DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
2272
2273  Comment cmnt(masm_, "[ CountOperation");
2274
2275  Property* prop = expr->expression()->AsProperty();
2276  LhsKind assign_type = Property::GetAssignType(prop);
2277
2278  // Evaluate expression and get value.
2279  if (assign_type == VARIABLE) {
2280    DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
2281    AccumulatorValueContext context(this);
2282    EmitVariableLoad(expr->expression()->AsVariableProxy());
2283  } else {
2284    // Reserve space for result of postfix operation.
2285    if (expr->is_postfix() && !context()->IsEffect()) {
2286      PushOperand(Smi::kZero);
2287    }
2288    switch (assign_type) {
2289      case NAMED_PROPERTY: {
2290        // Put the object both on the stack and in the register.
2291        VisitForStackValue(prop->obj());
2292        __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
2293        EmitNamedPropertyLoad(prop);
2294        break;
2295      }
2296
2297      case KEYED_PROPERTY: {
2298        VisitForStackValue(prop->obj());
2299        VisitForStackValue(prop->key());
2300        __ mov(LoadDescriptor::ReceiverRegister(),
2301               Operand(esp, kPointerSize));                       // Object.
2302        __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0));  // Key.
2303        EmitKeyedPropertyLoad(prop);
2304        break;
2305      }
2306
2307      case NAMED_SUPER_PROPERTY:
2308      case KEYED_SUPER_PROPERTY:
2309      case VARIABLE:
2310        UNREACHABLE();
2311    }
2312  }
2313
2314  // We need a second deoptimization point after loading the value
2315  // in case evaluating the property load my have a side effect.
2316  if (assign_type == VARIABLE) {
2317    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
2318  } else {
2319    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
2320  }
2321
2322  // Inline smi case if we are in a loop.
2323  Label done, stub_call;
2324  JumpPatchSite patch_site(masm_);
2325  if (ShouldInlineSmiCase(expr->op())) {
2326    Label slow;
2327    patch_site.EmitJumpIfNotSmi(eax, &slow, Label::kNear);
2328
2329    // Save result for postfix expressions.
2330    if (expr->is_postfix()) {
2331      if (!context()->IsEffect()) {
2332        // Save the result on the stack. If we have a named or keyed property
2333        // we store the result under the receiver that is currently on top
2334        // of the stack.
2335        switch (assign_type) {
2336          case VARIABLE:
2337            __ push(eax);
2338            break;
2339          case NAMED_PROPERTY:
2340            __ mov(Operand(esp, kPointerSize), eax);
2341            break;
2342          case KEYED_PROPERTY:
2343            __ mov(Operand(esp, 2 * kPointerSize), eax);
2344            break;
2345          case NAMED_SUPER_PROPERTY:
2346          case KEYED_SUPER_PROPERTY:
2347            UNREACHABLE();
2348            break;
2349        }
2350      }
2351    }
2352
2353    if (expr->op() == Token::INC) {
2354      __ add(eax, Immediate(Smi::FromInt(1)));
2355    } else {
2356      __ sub(eax, Immediate(Smi::FromInt(1)));
2357    }
2358    __ j(no_overflow, &done, Label::kNear);
2359    // Call stub. Undo operation first.
2360    if (expr->op() == Token::INC) {
2361      __ sub(eax, Immediate(Smi::FromInt(1)));
2362    } else {
2363      __ add(eax, Immediate(Smi::FromInt(1)));
2364    }
2365    __ jmp(&stub_call, Label::kNear);
2366    __ bind(&slow);
2367  }
2368
2369  // Convert old value into a number.
2370  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
2371  RestoreContext();
2372  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
2373
2374  // Save result for postfix expressions.
2375  if (expr->is_postfix()) {
2376    if (!context()->IsEffect()) {
2377      // Save the result on the stack. If we have a named or keyed property
2378      // we store the result under the receiver that is currently on top
2379      // of the stack.
2380      switch (assign_type) {
2381        case VARIABLE:
2382          PushOperand(eax);
2383          break;
2384        case NAMED_PROPERTY:
2385          __ mov(Operand(esp, kPointerSize), eax);
2386          break;
2387        case KEYED_PROPERTY:
2388          __ mov(Operand(esp, 2 * kPointerSize), eax);
2389          break;
2390        case NAMED_SUPER_PROPERTY:
2391        case KEYED_SUPER_PROPERTY:
2392          UNREACHABLE();
2393          break;
2394      }
2395    }
2396  }
2397
2398  SetExpressionPosition(expr);
2399
2400  // Call stub for +1/-1.
2401  __ bind(&stub_call);
2402  __ mov(edx, eax);
2403  __ mov(eax, Immediate(Smi::FromInt(1)));
2404  Handle<Code> code =
2405      CodeFactory::BinaryOpIC(isolate(), expr->binary_op()).code();
2406  CallIC(code, expr->CountBinOpFeedbackId());
2407  patch_site.EmitPatchInfo();
2408  __ bind(&done);
2409
2410  // Store the value returned in eax.
2411  switch (assign_type) {
2412    case VARIABLE: {
2413      VariableProxy* proxy = expr->expression()->AsVariableProxy();
2414      if (expr->is_postfix()) {
2415        // Perform the assignment as if via '='.
2416        { EffectContext context(this);
2417          EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
2418                                 proxy->hole_check_mode());
2419          PrepareForBailoutForId(expr->AssignmentId(),
2420                                 BailoutState::TOS_REGISTER);
2421          context.Plug(eax);
2422        }
2423        // For all contexts except EffectContext We have the result on
2424        // top of the stack.
2425        if (!context()->IsEffect()) {
2426          context()->PlugTOS();
2427        }
2428      } else {
2429        // Perform the assignment as if via '='.
2430        EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
2431                               proxy->hole_check_mode());
2432        PrepareForBailoutForId(expr->AssignmentId(),
2433                               BailoutState::TOS_REGISTER);
2434        context()->Plug(eax);
2435      }
2436      break;
2437    }
2438    case NAMED_PROPERTY: {
2439      PopOperand(StoreDescriptor::ReceiverRegister());
2440      CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value());
2441      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2442      if (expr->is_postfix()) {
2443        if (!context()->IsEffect()) {
2444          context()->PlugTOS();
2445        }
2446      } else {
2447        context()->Plug(eax);
2448      }
2449      break;
2450    }
2451    case KEYED_PROPERTY: {
2452      PopOperand(StoreDescriptor::NameRegister());
2453      PopOperand(StoreDescriptor::ReceiverRegister());
2454      CallKeyedStoreIC(expr->CountSlot());
2455      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2456      if (expr->is_postfix()) {
2457        // Result is on the stack
2458        if (!context()->IsEffect()) {
2459          context()->PlugTOS();
2460        }
2461      } else {
2462        context()->Plug(eax);
2463      }
2464      break;
2465    }
2466    case NAMED_SUPER_PROPERTY:
2467    case KEYED_SUPER_PROPERTY:
2468      UNREACHABLE();
2469      break;
2470  }
2471}
2472
2473
2474void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
2475                                                 Expression* sub_expr,
2476                                                 Handle<String> check) {
2477  Label materialize_true, materialize_false;
2478  Label* if_true = NULL;
2479  Label* if_false = NULL;
2480  Label* fall_through = NULL;
2481  context()->PrepareTest(&materialize_true, &materialize_false,
2482                         &if_true, &if_false, &fall_through);
2483
2484  { AccumulatorValueContext context(this);
2485    VisitForTypeofValue(sub_expr);
2486  }
2487  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2488
2489  Factory* factory = isolate()->factory();
2490  if (String::Equals(check, factory->number_string())) {
2491    __ JumpIfSmi(eax, if_true);
2492    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
2493           isolate()->factory()->heap_number_map());
2494    Split(equal, if_true, if_false, fall_through);
2495  } else if (String::Equals(check, factory->string_string())) {
2496    __ JumpIfSmi(eax, if_false);
2497    __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
2498    Split(below, if_true, if_false, fall_through);
2499  } else if (String::Equals(check, factory->symbol_string())) {
2500    __ JumpIfSmi(eax, if_false);
2501    __ CmpObjectType(eax, SYMBOL_TYPE, edx);
2502    Split(equal, if_true, if_false, fall_through);
2503  } else if (String::Equals(check, factory->boolean_string())) {
2504    __ cmp(eax, isolate()->factory()->true_value());
2505    __ j(equal, if_true);
2506    __ cmp(eax, isolate()->factory()->false_value());
2507    Split(equal, if_true, if_false, fall_through);
2508  } else if (String::Equals(check, factory->undefined_string())) {
2509    __ cmp(eax, isolate()->factory()->null_value());
2510    __ j(equal, if_false);
2511    __ JumpIfSmi(eax, if_false);
2512    // Check for undetectable objects => true.
2513    __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
2514    __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
2515              Immediate(1 << Map::kIsUndetectable));
2516    Split(not_zero, if_true, if_false, fall_through);
2517  } else if (String::Equals(check, factory->function_string())) {
2518    __ JumpIfSmi(eax, if_false);
2519    // Check for callable and not undetectable objects => true.
2520    __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
2521    __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
2522    __ and_(ecx, (1 << Map::kIsCallable) | (1 << Map::kIsUndetectable));
2523    __ cmp(ecx, 1 << Map::kIsCallable);
2524    Split(equal, if_true, if_false, fall_through);
2525  } else if (String::Equals(check, factory->object_string())) {
2526    __ JumpIfSmi(eax, if_false);
2527    __ cmp(eax, isolate()->factory()->null_value());
2528    __ j(equal, if_true);
2529    STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
2530    __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, edx);
2531    __ j(below, if_false);
2532    // Check for callable or undetectable objects => false.
2533    __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
2534              Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
2535    Split(zero, if_true, if_false, fall_through);
2536  } else {
2537    if (if_false != fall_through) __ jmp(if_false);
2538  }
2539  context()->Plug(if_true, if_false);
2540}
2541
2542
2543void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
2544  Comment cmnt(masm_, "[ CompareOperation");
2545
2546  // First we try a fast inlined version of the compare when one of
2547  // the operands is a literal.
2548  if (TryLiteralCompare(expr)) return;
2549
2550  // Always perform the comparison for its control flow.  Pack the result
2551  // into the expression's context after the comparison is performed.
2552  Label materialize_true, materialize_false;
2553  Label* if_true = NULL;
2554  Label* if_false = NULL;
2555  Label* fall_through = NULL;
2556  context()->PrepareTest(&materialize_true, &materialize_false,
2557                         &if_true, &if_false, &fall_through);
2558
2559  Token::Value op = expr->op();
2560  VisitForStackValue(expr->left());
2561  switch (op) {
2562    case Token::IN:
2563      VisitForStackValue(expr->right());
2564      SetExpressionPosition(expr);
2565      EmitHasProperty();
2566      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
2567      __ cmp(eax, isolate()->factory()->true_value());
2568      Split(equal, if_true, if_false, fall_through);
2569      break;
2570
2571    case Token::INSTANCEOF: {
2572      VisitForAccumulatorValue(expr->right());
2573      SetExpressionPosition(expr);
2574      PopOperand(edx);
2575      __ Call(isolate()->builtins()->InstanceOf(), RelocInfo::CODE_TARGET);
2576      RestoreContext();
2577      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
2578      __ cmp(eax, isolate()->factory()->true_value());
2579      Split(equal, if_true, if_false, fall_through);
2580      break;
2581    }
2582
2583    default: {
2584      VisitForAccumulatorValue(expr->right());
2585      SetExpressionPosition(expr);
2586      Condition cc = CompareIC::ComputeCondition(op);
2587      PopOperand(edx);
2588
2589      bool inline_smi_code = ShouldInlineSmiCase(op);
2590      JumpPatchSite patch_site(masm_);
2591      if (inline_smi_code) {
2592        Label slow_case;
2593        __ mov(ecx, edx);
2594        __ or_(ecx, eax);
2595        patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
2596        __ cmp(edx, eax);
2597        Split(cc, if_true, if_false, NULL);
2598        __ bind(&slow_case);
2599      }
2600
2601      Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
2602      CallIC(ic, expr->CompareOperationFeedbackId());
2603      patch_site.EmitPatchInfo();
2604
2605      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2606      __ test(eax, eax);
2607      Split(cc, if_true, if_false, fall_through);
2608    }
2609  }
2610
2611  // Convert the result of the comparison into one expected for this
2612  // expression's context.
2613  context()->Plug(if_true, if_false);
2614}
2615
2616
2617void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
2618                                              Expression* sub_expr,
2619                                              NilValue nil) {
2620  Label materialize_true, materialize_false;
2621  Label* if_true = NULL;
2622  Label* if_false = NULL;
2623  Label* fall_through = NULL;
2624  context()->PrepareTest(&materialize_true, &materialize_false,
2625                         &if_true, &if_false, &fall_through);
2626
2627  VisitForAccumulatorValue(sub_expr);
2628  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2629
2630  Handle<Object> nil_value = nil == kNullValue
2631      ? isolate()->factory()->null_value()
2632      : isolate()->factory()->undefined_value();
2633  if (expr->op() == Token::EQ_STRICT) {
2634    __ cmp(eax, nil_value);
2635    Split(equal, if_true, if_false, fall_through);
2636  } else {
2637    __ JumpIfSmi(eax, if_false);
2638    __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
2639    __ test_b(FieldOperand(eax, Map::kBitFieldOffset),
2640              Immediate(1 << Map::kIsUndetectable));
2641    Split(not_zero, if_true, if_false, fall_through);
2642  }
2643  context()->Plug(if_true, if_false);
2644}
2645
2646
2647Register FullCodeGenerator::result_register() {
2648  return eax;
2649}
2650
2651
2652Register FullCodeGenerator::context_register() {
2653  return esi;
2654}
2655
2656void FullCodeGenerator::LoadFromFrameField(int frame_offset, Register value) {
2657  DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
2658  __ mov(value, Operand(ebp, frame_offset));
2659}
2660
2661void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
2662  DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
2663  __ mov(Operand(ebp, frame_offset), value);
2664}
2665
2666
2667void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
2668  __ mov(dst, ContextOperand(esi, context_index));
2669}
2670
2671
2672void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
2673  DeclarationScope* closure_scope = scope()->GetClosureScope();
2674  if (closure_scope->is_script_scope() ||
2675      closure_scope->is_module_scope()) {
2676    // Contexts nested in the native context have a canonical empty function
2677    // as their closure, not the anonymous closure containing the global
2678    // code.
2679    __ mov(eax, NativeContextOperand());
2680    PushOperand(ContextOperand(eax, Context::CLOSURE_INDEX));
2681  } else if (closure_scope->is_eval_scope()) {
2682    // Contexts nested inside eval code have the same closure as the context
2683    // calling eval, not the anonymous closure containing the eval code.
2684    // Fetch it from the context.
2685    PushOperand(ContextOperand(esi, Context::CLOSURE_INDEX));
2686  } else {
2687    DCHECK(closure_scope->is_function_scope());
2688    PushOperand(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
2689  }
2690}
2691
2692
2693#undef __
2694
2695
2696static const byte kJnsInstruction = 0x79;
2697static const byte kJnsOffset = 0x11;
2698static const byte kNopByteOne = 0x66;
2699static const byte kNopByteTwo = 0x90;
2700#ifdef DEBUG
2701static const byte kCallInstruction = 0xe8;
2702#endif
2703
2704
2705void BackEdgeTable::PatchAt(Code* unoptimized_code,
2706                            Address pc,
2707                            BackEdgeState target_state,
2708                            Code* replacement_code) {
2709  Address call_target_address = pc - kIntSize;
2710  Address jns_instr_address = call_target_address - 3;
2711  Address jns_offset_address = call_target_address - 2;
2712
2713  switch (target_state) {
2714    case INTERRUPT:
2715      //     sub <profiling_counter>, <delta>  ;; Not changed
2716      //     jns ok
2717      //     call <interrupt stub>
2718      //   ok:
2719      *jns_instr_address = kJnsInstruction;
2720      *jns_offset_address = kJnsOffset;
2721      break;
2722    case ON_STACK_REPLACEMENT:
2723      //     sub <profiling_counter>, <delta>  ;; Not changed
2724      //     nop
2725      //     nop
2726      //     call <on-stack replacment>
2727      //   ok:
2728      *jns_instr_address = kNopByteOne;
2729      *jns_offset_address = kNopByteTwo;
2730      break;
2731  }
2732
2733  Assembler::set_target_address_at(unoptimized_code->GetIsolate(),
2734                                   call_target_address, unoptimized_code,
2735                                   replacement_code->entry());
2736  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
2737      unoptimized_code, call_target_address, replacement_code);
2738}
2739
2740
2741BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
2742    Isolate* isolate,
2743    Code* unoptimized_code,
2744    Address pc) {
2745  Address call_target_address = pc - kIntSize;
2746  Address jns_instr_address = call_target_address - 3;
2747  DCHECK_EQ(kCallInstruction, *(call_target_address - 1));
2748
2749  if (*jns_instr_address == kJnsInstruction) {
2750    DCHECK_EQ(kJnsOffset, *(call_target_address - 2));
2751    DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(),
2752              Assembler::target_address_at(call_target_address,
2753                                           unoptimized_code));
2754    return INTERRUPT;
2755  }
2756
2757  DCHECK_EQ(kNopByteOne, *jns_instr_address);
2758  DCHECK_EQ(kNopByteTwo, *(call_target_address - 2));
2759
2760  DCHECK_EQ(
2761      isolate->builtins()->OnStackReplacement()->entry(),
2762      Assembler::target_address_at(call_target_address, unoptimized_code));
2763  return ON_STACK_REPLACEMENT;
2764}
2765
2766
2767}  // namespace internal
2768}  // namespace v8
2769
2770#endif  // V8_TARGET_ARCH_IA32
2771