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/full-codegen/full-codegen.h"
8#include "src/ast/compile-time-value.h"
9#include "src/ast/scopes.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/ia32/frames-ia32.h"
17#include "src/ic/ic.h"
18
19namespace v8 {
20namespace internal {
21
22#define __ ACCESS_MASM(masm())
23
24class JumpPatchSite BASE_EMBEDDED {
25 public:
26  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
27#ifdef DEBUG
28    info_emitted_ = false;
29#endif
30  }
31
32  ~JumpPatchSite() {
33    DCHECK(patch_site_.is_bound() == info_emitted_);
34  }
35
36  void EmitJumpIfNotSmi(Register reg,
37                        Label* target,
38                        Label::Distance distance = Label::kFar) {
39    __ test(reg, Immediate(kSmiTagMask));
40    EmitJump(not_carry, target, distance);  // Always taken before patched.
41  }
42
43  void EmitJumpIfSmi(Register reg,
44                     Label* target,
45                     Label::Distance distance = Label::kFar) {
46    __ test(reg, Immediate(kSmiTagMask));
47    EmitJump(carry, target, distance);  // Never taken before patched.
48  }
49
50  void EmitPatchInfo() {
51    if (patch_site_.is_bound()) {
52      int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
53      DCHECK(is_uint8(delta_to_patch_site));
54      __ test(eax, Immediate(delta_to_patch_site));
55#ifdef DEBUG
56      info_emitted_ = true;
57#endif
58    } else {
59      __ nop();  // Signals no inlined code.
60    }
61  }
62
63 private:
64  // jc will be patched with jz, jnc will become jnz.
65  void EmitJump(Condition cc, Label* target, Label::Distance distance) {
66    DCHECK(!patch_site_.is_bound() && !info_emitted_);
67    DCHECK(cc == carry || cc == not_carry);
68    __ bind(&patch_site_);
69    __ j(cc, target, distance);
70  }
71
72  MacroAssembler* masm() { return masm_; }
73  MacroAssembler* masm_;
74  Label patch_site_;
75#ifdef DEBUG
76  bool info_emitted_;
77#endif
78};
79
80
81// Generate code for a JS function.  On entry to the function the receiver
82// and arguments have been pushed on the stack left to right, with the
83// return address on top of them.  The actual argument count matches the
84// formal parameter count expected by the function.
85//
86// The live registers are:
87//   o edi: the JS function object being called (i.e. ourselves)
88//   o edx: the new target value
89//   o esi: our context
90//   o ebp: our caller's frame pointer
91//   o esp: stack pointer (pointing to return address)
92//
93// The function builds a JS frame.  Please see JavaScriptFrameConstants in
94// frames-ia32.h for its layout.
95void FullCodeGenerator::Generate() {
96  CompilationInfo* info = info_;
97  profiling_counter_ = isolate()->factory()->NewCell(
98      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
99  SetFunctionPosition(literal());
100  Comment cmnt(masm_, "[ function compiled by full code generator");
101
102  ProfileEntryHookStub::MaybeCallEntryHook(masm_);
103
104  if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
105    int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
106    __ mov(ecx, Operand(esp, receiver_offset));
107    __ AssertNotSmi(ecx);
108    __ CmpObjectType(ecx, FIRST_JS_RECEIVER_TYPE, ecx);
109    __ Assert(above_equal, kSloppyFunctionExpectsJSReceiverReceiver);
110  }
111
112  // Open a frame scope to indicate that there is a frame on the stack.  The
113  // MANUAL indicates that the scope shouldn't actually generate code to set up
114  // the frame (that is done below).
115  FrameScope frame_scope(masm_, StackFrame::MANUAL);
116
117  info->set_prologue_offset(masm_->pc_offset());
118  __ Prologue(info->GeneratePreagedPrologue());
119
120  // Increment invocation count for the function.
121  {
122    Comment cmnt(masm_, "[ Increment invocation count");
123    __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset));
124    __ mov(ecx, FieldOperand(ecx, LiteralsArray::kFeedbackVectorOffset));
125    __ add(FieldOperand(
126               ecx, TypeFeedbackVector::kInvocationCountIndex * kPointerSize +
127                        TypeFeedbackVector::kHeaderSize),
128           Immediate(Smi::FromInt(1)));
129  }
130
131  { Comment cmnt(masm_, "[ Allocate locals");
132    int locals_count = info->scope()->num_stack_slots();
133    // Generators allocate locals, if any, in context slots.
134    DCHECK(!IsGeneratorFunction(literal()->kind()) || locals_count == 0);
135    OperandStackDepthIncrement(locals_count);
136    if (locals_count == 1) {
137      __ push(Immediate(isolate()->factory()->undefined_value()));
138    } else if (locals_count > 1) {
139      if (locals_count >= 128) {
140        Label ok;
141        __ mov(ecx, esp);
142        __ sub(ecx, Immediate(locals_count * kPointerSize));
143        ExternalReference stack_limit =
144            ExternalReference::address_of_real_stack_limit(isolate());
145        __ cmp(ecx, Operand::StaticVariable(stack_limit));
146        __ j(above_equal, &ok, Label::kNear);
147        __ CallRuntime(Runtime::kThrowStackOverflow);
148        __ bind(&ok);
149      }
150      __ mov(eax, Immediate(isolate()->factory()->undefined_value()));
151      const int kMaxPushes = 32;
152      if (locals_count >= kMaxPushes) {
153        int loop_iterations = locals_count / kMaxPushes;
154        __ mov(ecx, loop_iterations);
155        Label loop_header;
156        __ bind(&loop_header);
157        // Do pushes.
158        for (int i = 0; i < kMaxPushes; i++) {
159          __ push(eax);
160        }
161        __ dec(ecx);
162        __ j(not_zero, &loop_header, Label::kNear);
163      }
164      int remaining = locals_count % kMaxPushes;
165      // Emit the remaining pushes.
166      for (int i  = 0; i < remaining; i++) {
167        __ push(eax);
168      }
169    }
170  }
171
172  bool function_in_register = true;
173
174  // Possibly allocate a local context.
175  if (info->scope()->NeedsContext()) {
176    Comment cmnt(masm_, "[ Allocate context");
177    bool need_write_barrier = true;
178    int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
179    // Argument to NewContext is the function, which is still in edi.
180    if (info->scope()->is_script_scope()) {
181      __ push(edi);
182      __ Push(info->scope()->scope_info());
183      __ CallRuntime(Runtime::kNewScriptContext);
184      PrepareForBailoutForId(BailoutId::ScriptContext(),
185                             BailoutState::TOS_REGISTER);
186      // The new target value is not used, clobbering is safe.
187      DCHECK_NULL(info->scope()->new_target_var());
188    } else {
189      if (info->scope()->new_target_var() != nullptr) {
190        __ push(edx);  // Preserve new target.
191      }
192      if (slots <= FastNewFunctionContextStub::kMaximumSlots) {
193        FastNewFunctionContextStub stub(isolate());
194        __ mov(FastNewFunctionContextDescriptor::SlotsRegister(),
195               Immediate(slots));
196        __ CallStub(&stub);
197        // Result of FastNewFunctionContextStub is always in new space.
198        need_write_barrier = false;
199      } else {
200        __ push(edi);
201        __ CallRuntime(Runtime::kNewFunctionContext);
202      }
203      if (info->scope()->new_target_var() != nullptr) {
204        __ pop(edx);  // Restore new target.
205      }
206    }
207    function_in_register = false;
208    // Context is returned in eax.  It replaces the context passed to us.
209    // It's saved in the stack and kept live in esi.
210    __ mov(esi, eax);
211    __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax);
212
213    // Copy parameters into context if necessary.
214    int num_parameters = info->scope()->num_parameters();
215    int first_parameter = info->scope()->has_this_declaration() ? -1 : 0;
216    for (int i = first_parameter; i < num_parameters; i++) {
217      Variable* var =
218          (i == -1) ? info->scope()->receiver() : info->scope()->parameter(i);
219      if (var->IsContextSlot()) {
220        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
221            (num_parameters - 1 - i) * kPointerSize;
222        // Load parameter from stack.
223        __ mov(eax, Operand(ebp, parameter_offset));
224        // Store it in the context.
225        int context_offset = Context::SlotOffset(var->index());
226        __ mov(Operand(esi, context_offset), eax);
227        // Update the write barrier. This clobbers eax and ebx.
228        if (need_write_barrier) {
229          __ RecordWriteContextSlot(esi,
230                                    context_offset,
231                                    eax,
232                                    ebx,
233                                    kDontSaveFPRegs);
234        } else if (FLAG_debug_code) {
235          Label done;
236          __ JumpIfInNewSpace(esi, eax, &done, Label::kNear);
237          __ Abort(kExpectedNewSpaceObject);
238          __ bind(&done);
239        }
240      }
241    }
242  }
243
244  // Register holding this function and new target are both trashed in case we
245  // bailout here. But since that can happen only when new target is not used
246  // and we allocate a context, the value of |function_in_register| is correct.
247  PrepareForBailoutForId(BailoutId::FunctionContext(),
248                         BailoutState::NO_REGISTERS);
249
250  // Possibly set up a local binding to the this function which is used in
251  // derived constructors with super calls.
252  Variable* this_function_var = info->scope()->this_function_var();
253  if (this_function_var != nullptr) {
254    Comment cmnt(masm_, "[ This function");
255    if (!function_in_register) {
256      __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
257      // The write barrier clobbers register again, keep it marked as such.
258    }
259    SetVar(this_function_var, edi, ebx, ecx);
260  }
261
262  // Possibly set up a local binding to the new target value.
263  Variable* new_target_var = info->scope()->new_target_var();
264  if (new_target_var != nullptr) {
265    Comment cmnt(masm_, "[ new.target");
266    SetVar(new_target_var, edx, ebx, ecx);
267  }
268
269  // Possibly allocate RestParameters
270  Variable* rest_param = info->scope()->rest_parameter();
271  if (rest_param != nullptr) {
272    Comment cmnt(masm_, "[ Allocate rest parameter array");
273    if (!function_in_register) {
274      __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
275    }
276    FastNewRestParameterStub stub(isolate());
277    __ CallStub(&stub);
278    function_in_register = false;
279    SetVar(rest_param, eax, ebx, edx);
280  }
281
282  Variable* arguments = info->scope()->arguments();
283  if (arguments != NULL) {
284    // Arguments object must be allocated after the context object, in
285    // case the "arguments" or ".arguments" variables are in the context.
286    Comment cmnt(masm_, "[ Allocate arguments object");
287    if (!function_in_register) {
288      __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
289    }
290    if (is_strict(language_mode()) || !has_simple_parameters()) {
291      FastNewStrictArgumentsStub stub(isolate());
292      __ CallStub(&stub);
293    } else if (literal()->has_duplicate_parameters()) {
294      __ Push(edi);
295      __ CallRuntime(Runtime::kNewSloppyArguments_Generic);
296    } else {
297      FastNewSloppyArgumentsStub stub(isolate());
298      __ CallStub(&stub);
299    }
300
301    SetVar(arguments, eax, ebx, edx);
302  }
303
304  if (FLAG_trace) {
305    __ CallRuntime(Runtime::kTraceEnter);
306  }
307
308  // Visit the declarations and body.
309  PrepareForBailoutForId(BailoutId::FunctionEntry(),
310                         BailoutState::NO_REGISTERS);
311  {
312    Comment cmnt(masm_, "[ Declarations");
313    VisitDeclarations(info->scope()->declarations());
314  }
315
316  // Assert that the declarations do not use ICs. Otherwise the debugger
317  // won't be able to redirect a PC at an IC to the correct IC in newly
318  // recompiled code.
319  DCHECK_EQ(0, ic_total_count_);
320
321  {
322    Comment cmnt(masm_, "[ Stack check");
323    PrepareForBailoutForId(BailoutId::Declarations(),
324                           BailoutState::NO_REGISTERS);
325    Label ok;
326    ExternalReference stack_limit =
327        ExternalReference::address_of_stack_limit(isolate());
328    __ cmp(esp, Operand::StaticVariable(stack_limit));
329    __ j(above_equal, &ok, Label::kNear);
330    __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET);
331    __ bind(&ok);
332  }
333
334  {
335    Comment cmnt(masm_, "[ Body");
336    DCHECK(loop_depth() == 0);
337    VisitStatements(literal()->body());
338    DCHECK(loop_depth() == 0);
339  }
340
341  // Always emit a 'return undefined' in case control fell off the end of
342  // the body.
343  { Comment cmnt(masm_, "[ return <undefined>;");
344    __ mov(eax, isolate()->factory()->undefined_value());
345    EmitReturnSequence();
346  }
347}
348
349
350void FullCodeGenerator::ClearAccumulator() {
351  __ Move(eax, Immediate(Smi::kZero));
352}
353
354
355void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
356  __ mov(ebx, Immediate(profiling_counter_));
357  __ sub(FieldOperand(ebx, Cell::kValueOffset),
358         Immediate(Smi::FromInt(delta)));
359}
360
361
362void FullCodeGenerator::EmitProfilingCounterReset() {
363  int reset_value = FLAG_interrupt_budget;
364  __ mov(ebx, Immediate(profiling_counter_));
365  __ mov(FieldOperand(ebx, Cell::kValueOffset),
366         Immediate(Smi::FromInt(reset_value)));
367}
368
369
370void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
371                                                Label* back_edge_target) {
372  Comment cmnt(masm_, "[ Back edge bookkeeping");
373  Label ok;
374
375  DCHECK(back_edge_target->is_bound());
376  int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
377  int weight = Min(kMaxBackEdgeWeight,
378                   Max(1, distance / kCodeSizeMultiplier));
379  EmitProfilingCounterDecrement(weight);
380  __ j(positive, &ok, Label::kNear);
381  __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
382
383  // Record a mapping of this PC offset to the OSR id.  This is used to find
384  // the AST id from the unoptimized code in order to use it as a key into
385  // the deoptimization input data found in the optimized code.
386  RecordBackEdge(stmt->OsrEntryId());
387
388  EmitProfilingCounterReset();
389
390  __ bind(&ok);
391  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
392  // Record a mapping of the OSR id to this PC.  This is used if the OSR
393  // entry becomes the target of a bailout.  We don't expect it to be, but
394  // we want it to work if it is.
395  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
396}
397
398void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
399    bool is_tail_call) {
400  // Pretend that the exit is a backwards jump to the entry.
401  int weight = 1;
402  if (info_->ShouldSelfOptimize()) {
403    weight = FLAG_interrupt_budget / FLAG_self_opt_count;
404  } else {
405    int distance = masm_->pc_offset();
406    weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier));
407  }
408  EmitProfilingCounterDecrement(weight);
409  Label ok;
410  __ j(positive, &ok, Label::kNear);
411  // Don't need to save result register if we are going to do a tail call.
412  if (!is_tail_call) {
413    __ push(eax);
414  }
415  __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
416  if (!is_tail_call) {
417    __ pop(eax);
418  }
419  EmitProfilingCounterReset();
420  __ bind(&ok);
421}
422
423void FullCodeGenerator::EmitReturnSequence() {
424  Comment cmnt(masm_, "[ Return sequence");
425  if (return_label_.is_bound()) {
426    __ jmp(&return_label_);
427  } else {
428    // Common return label
429    __ bind(&return_label_);
430    if (FLAG_trace) {
431      __ push(eax);
432      __ CallRuntime(Runtime::kTraceExit);
433    }
434    EmitProfilingCounterHandlingForReturnSequence(false);
435
436    SetReturnPosition(literal());
437    __ leave();
438
439    int arg_count = info_->scope()->num_parameters() + 1;
440    int arguments_bytes = arg_count * kPointerSize;
441    __ Ret(arguments_bytes, ecx);
442  }
443}
444
445void FullCodeGenerator::RestoreContext() {
446  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
447}
448
449void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
450  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
451  MemOperand operand = codegen()->VarOperand(var, result_register());
452  // Memory operands can be pushed directly.
453  codegen()->PushOperand(operand);
454}
455
456
457void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
458  UNREACHABLE();  // Not used on IA32.
459}
460
461
462void FullCodeGenerator::AccumulatorValueContext::Plug(
463    Heap::RootListIndex index) const {
464  UNREACHABLE();  // Not used on IA32.
465}
466
467
468void FullCodeGenerator::StackValueContext::Plug(
469    Heap::RootListIndex index) const {
470  UNREACHABLE();  // Not used on IA32.
471}
472
473
474void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
475  UNREACHABLE();  // Not used on IA32.
476}
477
478
479void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
480}
481
482
483void FullCodeGenerator::AccumulatorValueContext::Plug(
484    Handle<Object> lit) const {
485  if (lit->IsSmi()) {
486    __ SafeMove(result_register(), Immediate(lit));
487  } else {
488    __ Move(result_register(), Immediate(lit));
489  }
490}
491
492
493void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
494  codegen()->OperandStackDepthIncrement(1);
495  if (lit->IsSmi()) {
496    __ SafePush(Immediate(lit));
497  } else {
498    __ push(Immediate(lit));
499  }
500}
501
502
503void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
504  codegen()->PrepareForBailoutBeforeSplit(condition(),
505                                          true,
506                                          true_label_,
507                                          false_label_);
508  DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
509         !lit->IsUndetectable());
510  if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
511      lit->IsFalse(isolate())) {
512    if (false_label_ != fall_through_) __ jmp(false_label_);
513  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
514    if (true_label_ != fall_through_) __ jmp(true_label_);
515  } else if (lit->IsString()) {
516    if (String::cast(*lit)->length() == 0) {
517      if (false_label_ != fall_through_) __ jmp(false_label_);
518    } else {
519      if (true_label_ != fall_through_) __ jmp(true_label_);
520    }
521  } else if (lit->IsSmi()) {
522    if (Smi::cast(*lit)->value() == 0) {
523      if (false_label_ != fall_through_) __ jmp(false_label_);
524    } else {
525      if (true_label_ != fall_through_) __ jmp(true_label_);
526    }
527  } else {
528    // For simplicity we always test the accumulator register.
529    __ mov(result_register(), lit);
530    codegen()->DoTest(this);
531  }
532}
533
534
535void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
536                                                       Register reg) const {
537  DCHECK(count > 0);
538  if (count > 1) codegen()->DropOperands(count - 1);
539  __ mov(Operand(esp, 0), reg);
540}
541
542
543void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
544                                            Label* materialize_false) const {
545  DCHECK(materialize_true == materialize_false);
546  __ bind(materialize_true);
547}
548
549
550void FullCodeGenerator::AccumulatorValueContext::Plug(
551    Label* materialize_true,
552    Label* materialize_false) const {
553  Label done;
554  __ bind(materialize_true);
555  __ mov(result_register(), isolate()->factory()->true_value());
556  __ jmp(&done, Label::kNear);
557  __ bind(materialize_false);
558  __ mov(result_register(), isolate()->factory()->false_value());
559  __ bind(&done);
560}
561
562
563void FullCodeGenerator::StackValueContext::Plug(
564    Label* materialize_true,
565    Label* materialize_false) const {
566  codegen()->OperandStackDepthIncrement(1);
567  Label done;
568  __ bind(materialize_true);
569  __ push(Immediate(isolate()->factory()->true_value()));
570  __ jmp(&done, Label::kNear);
571  __ bind(materialize_false);
572  __ push(Immediate(isolate()->factory()->false_value()));
573  __ bind(&done);
574}
575
576
577void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
578                                          Label* materialize_false) const {
579  DCHECK(materialize_true == true_label_);
580  DCHECK(materialize_false == false_label_);
581}
582
583
584void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
585  Handle<Object> value = flag
586      ? isolate()->factory()->true_value()
587      : isolate()->factory()->false_value();
588  __ mov(result_register(), value);
589}
590
591
592void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
593  codegen()->OperandStackDepthIncrement(1);
594  Handle<Object> value = flag
595      ? isolate()->factory()->true_value()
596      : isolate()->factory()->false_value();
597  __ push(Immediate(value));
598}
599
600
601void FullCodeGenerator::TestContext::Plug(bool flag) const {
602  codegen()->PrepareForBailoutBeforeSplit(condition(),
603                                          true,
604                                          true_label_,
605                                          false_label_);
606  if (flag) {
607    if (true_label_ != fall_through_) __ jmp(true_label_);
608  } else {
609    if (false_label_ != fall_through_) __ jmp(false_label_);
610  }
611}
612
613
614void FullCodeGenerator::DoTest(Expression* condition,
615                               Label* if_true,
616                               Label* if_false,
617                               Label* fall_through) {
618  Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
619  CallIC(ic, condition->test_id());
620  __ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
621  Split(equal, if_true, if_false, fall_through);
622}
623
624
625void FullCodeGenerator::Split(Condition cc,
626                              Label* if_true,
627                              Label* if_false,
628                              Label* fall_through) {
629  if (if_false == fall_through) {
630    __ j(cc, if_true);
631  } else if (if_true == fall_through) {
632    __ j(NegateCondition(cc), if_false);
633  } else {
634    __ j(cc, if_true);
635    __ jmp(if_false);
636  }
637}
638
639
640MemOperand FullCodeGenerator::StackOperand(Variable* var) {
641  DCHECK(var->IsStackAllocated());
642  // Offset is negative because higher indexes are at lower addresses.
643  int offset = -var->index() * kPointerSize;
644  // Adjust by a (parameter or local) base offset.
645  if (var->IsParameter()) {
646    offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
647  } else {
648    offset += JavaScriptFrameConstants::kLocal0Offset;
649  }
650  return Operand(ebp, offset);
651}
652
653
654MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
655  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
656  if (var->IsContextSlot()) {
657    int context_chain_length = scope()->ContextChainLength(var->scope());
658    __ LoadContext(scratch, context_chain_length);
659    return ContextOperand(scratch, var->index());
660  } else {
661    return StackOperand(var);
662  }
663}
664
665
666void FullCodeGenerator::GetVar(Register dest, Variable* var) {
667  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
668  MemOperand location = VarOperand(var, dest);
669  __ mov(dest, location);
670}
671
672
673void FullCodeGenerator::SetVar(Variable* var,
674                               Register src,
675                               Register scratch0,
676                               Register scratch1) {
677  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
678  DCHECK(!scratch0.is(src));
679  DCHECK(!scratch0.is(scratch1));
680  DCHECK(!scratch1.is(src));
681  MemOperand location = VarOperand(var, scratch0);
682  __ mov(location, src);
683
684  // Emit the write barrier code if the location is in the heap.
685  if (var->IsContextSlot()) {
686    int offset = Context::SlotOffset(var->index());
687    DCHECK(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi));
688    __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
689  }
690}
691
692
693void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
694                                                     bool should_normalize,
695                                                     Label* if_true,
696                                                     Label* if_false) {
697  // Only prepare for bailouts before splits if we're in a test
698  // context. Otherwise, we let the Visit function deal with the
699  // preparation to avoid preparing with the same AST id twice.
700  if (!context()->IsTest()) return;
701
702  Label skip;
703  if (should_normalize) __ jmp(&skip, Label::kNear);
704  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
705  if (should_normalize) {
706    __ cmp(eax, isolate()->factory()->true_value());
707    Split(equal, if_true, if_false, NULL);
708    __ bind(&skip);
709  }
710}
711
712
713void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
714  // The variable in the declaration always resides in the current context.
715  DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
716  if (FLAG_debug_code) {
717    // Check that we're not inside a with or catch context.
718    __ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset));
719    __ cmp(ebx, isolate()->factory()->with_context_map());
720    __ Check(not_equal, kDeclarationInWithContext);
721    __ cmp(ebx, isolate()->factory()->catch_context_map());
722    __ Check(not_equal, kDeclarationInCatchContext);
723  }
724}
725
726
727void FullCodeGenerator::VisitVariableDeclaration(
728    VariableDeclaration* declaration) {
729  VariableProxy* proxy = declaration->proxy();
730  Variable* variable = proxy->var();
731  switch (variable->location()) {
732    case VariableLocation::UNALLOCATED: {
733      DCHECK(!variable->binding_needs_init());
734      FeedbackVectorSlot slot = proxy->VariableFeedbackSlot();
735      DCHECK(!slot.IsInvalid());
736      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
737      globals_->Add(isolate()->factory()->undefined_value(), zone());
738      break;
739    }
740    case VariableLocation::PARAMETER:
741    case VariableLocation::LOCAL:
742      if (variable->binding_needs_init()) {
743        Comment cmnt(masm_, "[ VariableDeclaration");
744        __ mov(StackOperand(variable),
745               Immediate(isolate()->factory()->the_hole_value()));
746      }
747      break;
748
749    case VariableLocation::CONTEXT:
750      if (variable->binding_needs_init()) {
751        Comment cmnt(masm_, "[ VariableDeclaration");
752        EmitDebugCheckDeclarationContext(variable);
753        __ mov(ContextOperand(esi, variable->index()),
754               Immediate(isolate()->factory()->the_hole_value()));
755        // No write barrier since the hole value is in old space.
756        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
757      }
758      break;
759
760    case VariableLocation::LOOKUP: {
761      Comment cmnt(masm_, "[ VariableDeclaration");
762      DCHECK_EQ(VAR, variable->mode());
763      DCHECK(!variable->binding_needs_init());
764      __ push(Immediate(variable->name()));
765      __ CallRuntime(Runtime::kDeclareEvalVar);
766      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
767      break;
768    }
769
770    case VariableLocation::MODULE:
771      UNREACHABLE();
772  }
773}
774
775
776void FullCodeGenerator::VisitFunctionDeclaration(
777    FunctionDeclaration* declaration) {
778  VariableProxy* proxy = declaration->proxy();
779  Variable* variable = proxy->var();
780  switch (variable->location()) {
781    case VariableLocation::UNALLOCATED: {
782      FeedbackVectorSlot slot = proxy->VariableFeedbackSlot();
783      DCHECK(!slot.IsInvalid());
784      globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
785      Handle<SharedFunctionInfo> function =
786          Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
787      // Check for stack-overflow exception.
788      if (function.is_null()) return SetStackOverflow();
789      globals_->Add(function, zone());
790      break;
791    }
792
793    case VariableLocation::PARAMETER:
794    case VariableLocation::LOCAL: {
795      Comment cmnt(masm_, "[ FunctionDeclaration");
796      VisitForAccumulatorValue(declaration->fun());
797      __ mov(StackOperand(variable), result_register());
798      break;
799    }
800
801    case VariableLocation::CONTEXT: {
802      Comment cmnt(masm_, "[ FunctionDeclaration");
803      EmitDebugCheckDeclarationContext(variable);
804      VisitForAccumulatorValue(declaration->fun());
805      __ mov(ContextOperand(esi, variable->index()), result_register());
806      // We know that we have written a function, which is not a smi.
807      __ RecordWriteContextSlot(esi,
808                                Context::SlotOffset(variable->index()),
809                                result_register(),
810                                ecx,
811                                kDontSaveFPRegs,
812                                EMIT_REMEMBERED_SET,
813                                OMIT_SMI_CHECK);
814      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
815      break;
816    }
817
818    case VariableLocation::LOOKUP: {
819      Comment cmnt(masm_, "[ FunctionDeclaration");
820      PushOperand(variable->name());
821      VisitForStackValue(declaration->fun());
822      CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
823      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
824      break;
825    }
826
827    case VariableLocation::MODULE:
828      UNREACHABLE();
829  }
830}
831
832
833void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
834  // Call the runtime to declare the globals.
835  __ Push(pairs);
836  __ Push(Smi::FromInt(DeclareGlobalsFlags()));
837  __ EmitLoadTypeFeedbackVector(eax);
838  __ Push(eax);
839  __ CallRuntime(Runtime::kDeclareGlobals);
840  // Return value is ignored.
841}
842
843
844void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
845  Comment cmnt(masm_, "[ SwitchStatement");
846  Breakable nested_statement(this, stmt);
847  SetStatementPosition(stmt);
848
849  // Keep the switch value on the stack until a case matches.
850  VisitForStackValue(stmt->tag());
851  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
852
853  ZoneList<CaseClause*>* clauses = stmt->cases();
854  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
855
856  Label next_test;  // Recycled for each test.
857  // Compile all the tests with branches to their bodies.
858  for (int i = 0; i < clauses->length(); i++) {
859    CaseClause* clause = clauses->at(i);
860    clause->body_target()->Unuse();
861
862    // The default is not a test, but remember it as final fall through.
863    if (clause->is_default()) {
864      default_clause = clause;
865      continue;
866    }
867
868    Comment cmnt(masm_, "[ Case comparison");
869    __ bind(&next_test);
870    next_test.Unuse();
871
872    // Compile the label expression.
873    VisitForAccumulatorValue(clause->label());
874
875    // Perform the comparison as if via '==='.
876    __ mov(edx, Operand(esp, 0));  // Switch value.
877    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
878    JumpPatchSite patch_site(masm_);
879    if (inline_smi_code) {
880      Label slow_case;
881      __ mov(ecx, edx);
882      __ or_(ecx, eax);
883      patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
884
885      __ cmp(edx, eax);
886      __ j(not_equal, &next_test);
887      __ Drop(1);  // Switch value is no longer needed.
888      __ jmp(clause->body_target());
889      __ bind(&slow_case);
890    }
891
892    SetExpressionPosition(clause);
893    Handle<Code> ic =
894        CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
895    CallIC(ic, clause->CompareId());
896    patch_site.EmitPatchInfo();
897
898    Label skip;
899    __ jmp(&skip, Label::kNear);
900    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
901    __ cmp(eax, isolate()->factory()->true_value());
902    __ j(not_equal, &next_test);
903    __ Drop(1);
904    __ jmp(clause->body_target());
905    __ bind(&skip);
906
907    __ test(eax, eax);
908    __ j(not_equal, &next_test);
909    __ Drop(1);  // Switch value is no longer needed.
910    __ jmp(clause->body_target());
911  }
912
913  // Discard the test value and jump to the default if present, otherwise to
914  // the end of the statement.
915  __ bind(&next_test);
916  DropOperands(1);  // Switch value is no longer needed.
917  if (default_clause == NULL) {
918    __ jmp(nested_statement.break_label());
919  } else {
920    __ jmp(default_clause->body_target());
921  }
922
923  // Compile all the case bodies.
924  for (int i = 0; i < clauses->length(); i++) {
925    Comment cmnt(masm_, "[ Case body");
926    CaseClause* clause = clauses->at(i);
927    __ bind(clause->body_target());
928    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
929    VisitStatements(clause->statements());
930  }
931
932  __ bind(nested_statement.break_label());
933  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
934}
935
936
937void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
938  Comment cmnt(masm_, "[ ForInStatement");
939  SetStatementPosition(stmt, SKIP_BREAK);
940
941  FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
942
943  // Get the object to enumerate over.
944  SetExpressionAsStatementPosition(stmt->enumerable());
945  VisitForAccumulatorValue(stmt->enumerable());
946  OperandStackDepthIncrement(5);
947
948  Label loop, exit;
949  Iteration loop_statement(this, stmt);
950  increment_loop_depth();
951
952  // If the object is null or undefined, skip over the loop, otherwise convert
953  // it to a JS receiver.  See ECMA-262 version 5, section 12.6.4.
954  Label convert, done_convert;
955  __ JumpIfSmi(eax, &convert, Label::kNear);
956  __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, ecx);
957  __ j(above_equal, &done_convert, Label::kNear);
958  __ cmp(eax, isolate()->factory()->undefined_value());
959  __ j(equal, &exit);
960  __ cmp(eax, isolate()->factory()->null_value());
961  __ j(equal, &exit);
962  __ bind(&convert);
963  __ Call(isolate()->builtins()->ToObject(), RelocInfo::CODE_TARGET);
964  RestoreContext();
965  __ bind(&done_convert);
966  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
967  __ push(eax);
968
969  // Check cache validity in generated code. If we cannot guarantee cache
970  // validity, call the runtime system to check cache validity or get the
971  // property names in a fixed array. Note: Proxies never have an enum cache,
972  // so will always take the slow path.
973  Label call_runtime, use_cache, fixed_array;
974  __ CheckEnumCache(&call_runtime);
975
976  __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
977  __ jmp(&use_cache, Label::kNear);
978
979  // Get the set of properties to enumerate.
980  __ bind(&call_runtime);
981  __ push(eax);
982  __ CallRuntime(Runtime::kForInEnumerate);
983  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
984  __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
985         isolate()->factory()->meta_map());
986  __ j(not_equal, &fixed_array);
987
988
989  // We got a map in register eax. Get the enumeration cache from it.
990  Label no_descriptors;
991  __ bind(&use_cache);
992
993  __ EnumLength(edx, eax);
994  __ cmp(edx, Immediate(Smi::kZero));
995  __ j(equal, &no_descriptors);
996
997  __ LoadInstanceDescriptors(eax, ecx);
998  __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumCacheOffset));
999  __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1000
1001  // Set up the four remaining stack slots.
1002  __ push(eax);  // Map.
1003  __ push(ecx);  // Enumeration cache.
1004  __ push(edx);  // Number of valid entries for the map in the enum cache.
1005  __ push(Immediate(Smi::kZero));  // Initial index.
1006  __ jmp(&loop);
1007
1008  __ bind(&no_descriptors);
1009  __ add(esp, Immediate(kPointerSize));
1010  __ jmp(&exit);
1011
1012  // We got a fixed array in register eax. Iterate through that.
1013  __ bind(&fixed_array);
1014
1015  __ push(Immediate(Smi::FromInt(1)));  // Smi(1) indicates slow check
1016  __ push(eax);  // Array
1017  __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
1018  __ push(eax);  // Fixed array length (as smi).
1019  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
1020  __ push(Immediate(Smi::kZero));  // Initial index.
1021
1022  // Generate code for doing the condition check.
1023  __ bind(&loop);
1024  SetExpressionAsStatementPosition(stmt->each());
1025
1026  __ mov(eax, Operand(esp, 0 * kPointerSize));  // Get the current index.
1027  __ cmp(eax, Operand(esp, 1 * kPointerSize));  // Compare to the array length.
1028  __ j(above_equal, loop_statement.break_label());
1029
1030  // Get the current entry of the array into register eax.
1031  __ mov(ebx, Operand(esp, 2 * kPointerSize));
1032  __ mov(eax, FieldOperand(ebx, eax, times_2, FixedArray::kHeaderSize));
1033
1034  // Get the expected map from the stack or a smi in the
1035  // permanent slow case into register edx.
1036  __ mov(edx, Operand(esp, 3 * kPointerSize));
1037
1038  // Check if the expected map still matches that of the enumerable.
1039  // If not, we may have to filter the key.
1040  Label update_each;
1041  __ mov(ebx, Operand(esp, 4 * kPointerSize));
1042  __ cmp(edx, FieldOperand(ebx, HeapObject::kMapOffset));
1043  __ j(equal, &update_each, Label::kNear);
1044
1045  // We need to filter the key, record slow-path here.
1046  int const vector_index = SmiFromSlot(slot)->value();
1047  __ EmitLoadTypeFeedbackVector(edx);
1048  __ mov(FieldOperand(edx, FixedArray::OffsetOfElementAt(vector_index)),
1049         Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate())));
1050
1051  // eax contains the key.  The receiver in ebx is the second argument to the
1052  // ForInFilter.  ForInFilter returns undefined if the receiver doesn't
1053  // have the key or returns the name-converted key.
1054  __ Call(isolate()->builtins()->ForInFilter(), RelocInfo::CODE_TARGET);
1055  RestoreContext();
1056  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
1057  __ JumpIfRoot(result_register(), Heap::kUndefinedValueRootIndex,
1058                loop_statement.continue_label());
1059
1060  // Update the 'each' property or variable from the possibly filtered
1061  // entry in register eax.
1062  __ bind(&update_each);
1063  // Perform the assignment as if via '='.
1064  { EffectContext context(this);
1065    EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
1066    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
1067  }
1068
1069  // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
1070  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
1071  // Generate code for the body of the loop.
1072  Visit(stmt->body());
1073
1074  // Generate code for going to the next element by incrementing the
1075  // index (smi) stored on top of the stack.
1076  __ bind(loop_statement.continue_label());
1077  PrepareForBailoutForId(stmt->IncrementId(), BailoutState::NO_REGISTERS);
1078  __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
1079
1080  EmitBackEdgeBookkeeping(stmt, &loop);
1081  __ jmp(&loop);
1082
1083  // Remove the pointers stored on the stack.
1084  __ bind(loop_statement.break_label());
1085  DropOperands(5);
1086
1087  // Exit and decrement the loop depth.
1088  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
1089  __ bind(&exit);
1090  decrement_loop_depth();
1091}
1092
1093
1094void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
1095                                          FeedbackVectorSlot slot) {
1096  DCHECK(NeedsHomeObject(initializer));
1097  __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
1098  __ mov(StoreDescriptor::ValueRegister(), Operand(esp, offset * kPointerSize));
1099  CallStoreIC(slot, isolate()->factory()->home_object_symbol());
1100}
1101
1102
1103void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer,
1104                                                     int offset,
1105                                                     FeedbackVectorSlot slot) {
1106  DCHECK(NeedsHomeObject(initializer));
1107  __ mov(StoreDescriptor::ReceiverRegister(), eax);
1108  __ mov(StoreDescriptor::ValueRegister(), Operand(esp, offset * kPointerSize));
1109  CallStoreIC(slot, isolate()->factory()->home_object_symbol());
1110}
1111
1112
1113void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
1114                                                      TypeofMode typeof_mode,
1115                                                      Label* slow) {
1116  Register context = esi;
1117  Register temp = edx;
1118
1119  int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
1120  for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
1121    if (!s->NeedsContext()) continue;
1122    if (s->calls_sloppy_eval()) {
1123      // Check that extension is "the hole".
1124      __ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
1125                       Heap::kTheHoleValueRootIndex, slow);
1126    }
1127    // Load next context in chain.
1128    __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1129    // Walk the rest of the chain without clobbering esi.
1130    context = temp;
1131    to_check--;
1132  }
1133
1134  // All extension objects were empty and it is safe to use a normal global
1135  // load machinery.
1136  EmitGlobalVariableLoad(proxy, typeof_mode);
1137}
1138
1139
1140MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1141                                                                Label* slow) {
1142  DCHECK(var->IsContextSlot());
1143  Register context = esi;
1144  Register temp = ebx;
1145
1146  for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
1147    if (s->NeedsContext()) {
1148      if (s->calls_sloppy_eval()) {
1149        // Check that extension is "the hole".
1150        __ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
1151                         Heap::kTheHoleValueRootIndex, slow);
1152      }
1153      __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1154      // Walk the rest of the chain without clobbering esi.
1155      context = temp;
1156    }
1157  }
1158  // Check that last extension is "the hole".
1159  __ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
1160                   Heap::kTheHoleValueRootIndex, slow);
1161
1162  // This function is used only for loads, not stores, so it's safe to
1163  // return an esi-based operand (the write barrier cannot be allowed to
1164  // destroy the esi register).
1165  return ContextOperand(context, var->index());
1166}
1167
1168
1169void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
1170                                                  TypeofMode typeof_mode,
1171                                                  Label* slow, Label* done) {
1172  // Generate fast-case code for variables that might be shadowed by
1173  // eval-introduced variables.  Eval is used a lot without
1174  // introducing variables.  In those cases, we do not want to
1175  // perform a runtime call for all variables in the scope
1176  // containing the eval.
1177  Variable* var = proxy->var();
1178  if (var->mode() == DYNAMIC_GLOBAL) {
1179    EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow);
1180    __ jmp(done);
1181  } else if (var->mode() == DYNAMIC_LOCAL) {
1182    Variable* local = var->local_if_not_shadowed();
1183    __ mov(eax, ContextSlotOperandCheckExtensions(local, slow));
1184    if (local->binding_needs_init()) {
1185      __ cmp(eax, isolate()->factory()->the_hole_value());
1186      __ j(not_equal, done);
1187      __ push(Immediate(var->name()));
1188      __ CallRuntime(Runtime::kThrowReferenceError);
1189    } else {
1190      __ jmp(done);
1191    }
1192  }
1193}
1194
1195void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
1196                                         TypeofMode typeof_mode) {
1197  SetExpressionPosition(proxy);
1198  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
1199  Variable* var = proxy->var();
1200
1201  // Three cases: global variables, lookup variables, and all other types of
1202  // variables.
1203  switch (var->location()) {
1204    case VariableLocation::UNALLOCATED: {
1205      Comment cmnt(masm_, "[ Global variable");
1206      EmitGlobalVariableLoad(proxy, typeof_mode);
1207      context()->Plug(eax);
1208      break;
1209    }
1210
1211    case VariableLocation::PARAMETER:
1212    case VariableLocation::LOCAL:
1213    case VariableLocation::CONTEXT: {
1214      DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode);
1215      Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
1216                                               : "[ Stack variable");
1217
1218      if (proxy->hole_check_mode() == HoleCheckMode::kRequired) {
1219        // Throw a reference error when using an uninitialized let/const
1220        // binding in harmony mode.
1221        Label done;
1222        GetVar(eax, var);
1223        __ cmp(eax, isolate()->factory()->the_hole_value());
1224        __ j(not_equal, &done, Label::kNear);
1225        __ push(Immediate(var->name()));
1226        __ CallRuntime(Runtime::kThrowReferenceError);
1227        __ bind(&done);
1228        context()->Plug(eax);
1229        break;
1230      }
1231      context()->Plug(var);
1232      break;
1233    }
1234
1235    case VariableLocation::LOOKUP: {
1236      Comment cmnt(masm_, "[ Lookup variable");
1237      Label done, slow;
1238      // Generate code for loading from variables potentially shadowed
1239      // by eval-introduced variables.
1240      EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done);
1241      __ bind(&slow);
1242      __ push(Immediate(var->name()));
1243      Runtime::FunctionId function_id =
1244          typeof_mode == NOT_INSIDE_TYPEOF
1245              ? Runtime::kLoadLookupSlot
1246              : Runtime::kLoadLookupSlotInsideTypeof;
1247      __ CallRuntime(function_id);
1248      __ bind(&done);
1249      context()->Plug(eax);
1250      break;
1251    }
1252
1253    case VariableLocation::MODULE:
1254      UNREACHABLE();
1255  }
1256}
1257
1258
1259void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
1260  Expression* expression = (property == NULL) ? NULL : property->value();
1261  if (expression == NULL) {
1262    PushOperand(isolate()->factory()->null_value());
1263  } else {
1264    VisitForStackValue(expression);
1265    if (NeedsHomeObject(expression)) {
1266      DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
1267             property->kind() == ObjectLiteral::Property::SETTER);
1268      int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
1269      EmitSetHomeObject(expression, offset, property->GetSlot());
1270    }
1271  }
1272}
1273
1274
1275void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1276  Comment cmnt(masm_, "[ ObjectLiteral");
1277
1278  Handle<FixedArray> constant_properties = expr->constant_properties();
1279  int flags = expr->ComputeFlags();
1280  // If any of the keys would store to the elements array, then we shouldn't
1281  // allow it.
1282  if (MustCreateObjectLiteralWithRuntime(expr)) {
1283    __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1284    __ push(Immediate(Smi::FromInt(expr->literal_index())));
1285    __ push(Immediate(constant_properties));
1286    __ push(Immediate(Smi::FromInt(flags)));
1287    __ CallRuntime(Runtime::kCreateObjectLiteral);
1288  } else {
1289    __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1290    __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index())));
1291    __ mov(ecx, Immediate(constant_properties));
1292    __ mov(edx, Immediate(Smi::FromInt(flags)));
1293    FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
1294    __ CallStub(&stub);
1295    RestoreContext();
1296  }
1297  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
1298
1299  // If result_saved is true the result is on top of the stack.  If
1300  // result_saved is false the result is in eax.
1301  bool result_saved = false;
1302
1303  AccessorTable accessor_table(zone());
1304  int property_index = 0;
1305  for (; property_index < expr->properties()->length(); property_index++) {
1306    ObjectLiteral::Property* property = expr->properties()->at(property_index);
1307    if (property->is_computed_name()) break;
1308    if (property->IsCompileTimeValue()) continue;
1309
1310    Literal* key = property->key()->AsLiteral();
1311    Expression* value = property->value();
1312    if (!result_saved) {
1313      PushOperand(eax);  // Save result on the stack
1314      result_saved = true;
1315    }
1316    switch (property->kind()) {
1317      case ObjectLiteral::Property::CONSTANT:
1318        UNREACHABLE();
1319      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1320        DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
1321        // Fall through.
1322      case ObjectLiteral::Property::COMPUTED:
1323        // It is safe to use [[Put]] here because the boilerplate already
1324        // contains computed properties with an uninitialized value.
1325        if (key->IsStringLiteral()) {
1326          DCHECK(key->IsPropertyName());
1327          if (property->emit_store()) {
1328            VisitForAccumulatorValue(value);
1329            DCHECK(StoreDescriptor::ValueRegister().is(eax));
1330            __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
1331            CallStoreIC(property->GetSlot(0), key->value());
1332            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
1333            if (NeedsHomeObject(value)) {
1334              EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
1335            }
1336          } else {
1337            VisitForEffect(value);
1338          }
1339          break;
1340        }
1341        PushOperand(Operand(esp, 0));  // Duplicate receiver.
1342        VisitForStackValue(key);
1343        VisitForStackValue(value);
1344        if (property->emit_store()) {
1345          if (NeedsHomeObject(value)) {
1346            EmitSetHomeObject(value, 2, property->GetSlot());
1347          }
1348          PushOperand(Smi::FromInt(SLOPPY));  // Language mode
1349          CallRuntimeWithOperands(Runtime::kSetProperty);
1350        } else {
1351          DropOperands(3);
1352        }
1353        break;
1354      case ObjectLiteral::Property::PROTOTYPE:
1355        PushOperand(Operand(esp, 0));  // Duplicate receiver.
1356        VisitForStackValue(value);
1357        DCHECK(property->emit_store());
1358        CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
1359        PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
1360                               BailoutState::NO_REGISTERS);
1361        break;
1362      case ObjectLiteral::Property::GETTER:
1363        if (property->emit_store()) {
1364          AccessorTable::Iterator it = accessor_table.lookup(key);
1365          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
1366          it->second->getter = property;
1367        }
1368        break;
1369      case ObjectLiteral::Property::SETTER:
1370        if (property->emit_store()) {
1371          AccessorTable::Iterator it = accessor_table.lookup(key);
1372          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
1373          it->second->setter = property;
1374        }
1375        break;
1376    }
1377  }
1378
1379  // Emit code to define accessors, using only a single call to the runtime for
1380  // each pair of corresponding getters and setters.
1381  for (AccessorTable::Iterator it = accessor_table.begin();
1382       it != accessor_table.end();
1383       ++it) {
1384    PushOperand(Operand(esp, 0));  // Duplicate receiver.
1385    VisitForStackValue(it->first);
1386
1387    EmitAccessor(it->second->getter);
1388    EmitAccessor(it->second->setter);
1389
1390    PushOperand(Smi::FromInt(NONE));
1391    CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
1392    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
1393  }
1394
1395  // Object literals have two parts. The "static" part on the left contains no
1396  // computed property names, and so we can compute its map ahead of time; see
1397  // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part
1398  // starts with the first computed property name, and continues with all
1399  // properties to its right.  All the code from above initializes the static
1400  // component of the object literal, and arranges for the map of the result to
1401  // reflect the static order in which the keys appear. For the dynamic
1402  // properties, we compile them into a series of "SetOwnProperty" runtime
1403  // calls. This will preserve insertion order.
1404  for (; property_index < expr->properties()->length(); property_index++) {
1405    ObjectLiteral::Property* property = expr->properties()->at(property_index);
1406
1407    Expression* value = property->value();
1408    if (!result_saved) {
1409      PushOperand(eax);  // Save result on the stack
1410      result_saved = true;
1411    }
1412
1413    PushOperand(Operand(esp, 0));  // Duplicate receiver.
1414
1415    if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1416      DCHECK(!property->is_computed_name());
1417      VisitForStackValue(value);
1418      DCHECK(property->emit_store());
1419      CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
1420      PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
1421                             BailoutState::NO_REGISTERS);
1422    } else {
1423      EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
1424      VisitForStackValue(value);
1425      if (NeedsHomeObject(value)) {
1426        EmitSetHomeObject(value, 2, property->GetSlot());
1427      }
1428
1429      switch (property->kind()) {
1430        case ObjectLiteral::Property::CONSTANT:
1431        case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1432        case ObjectLiteral::Property::COMPUTED:
1433          if (property->emit_store()) {
1434            PushOperand(Smi::FromInt(NONE));
1435            PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
1436            CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
1437            PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
1438                                   BailoutState::NO_REGISTERS);
1439          } else {
1440            DropOperands(3);
1441          }
1442          break;
1443
1444        case ObjectLiteral::Property::PROTOTYPE:
1445          UNREACHABLE();
1446          break;
1447
1448        case ObjectLiteral::Property::GETTER:
1449          PushOperand(Smi::FromInt(NONE));
1450          CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked);
1451          break;
1452
1453        case ObjectLiteral::Property::SETTER:
1454          PushOperand(Smi::FromInt(NONE));
1455          CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked);
1456          break;
1457      }
1458    }
1459  }
1460
1461  if (result_saved) {
1462    context()->PlugTOS();
1463  } else {
1464    context()->Plug(eax);
1465  }
1466}
1467
1468
1469void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1470  Comment cmnt(masm_, "[ ArrayLiteral");
1471
1472  Handle<FixedArray> constant_elements = expr->constant_elements();
1473  bool has_constant_fast_elements =
1474      IsFastObjectElementsKind(expr->constant_elements_kind());
1475
1476  AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1477  if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
1478    // If the only customer of allocation sites is transitioning, then
1479    // we can turn it off if we don't have anywhere else to transition to.
1480    allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1481  }
1482
1483  if (MustCreateArrayLiteralWithRuntime(expr)) {
1484    __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1485    __ push(Immediate(Smi::FromInt(expr->literal_index())));
1486    __ push(Immediate(constant_elements));
1487    __ push(Immediate(Smi::FromInt(expr->ComputeFlags())));
1488    __ CallRuntime(Runtime::kCreateArrayLiteral);
1489  } else {
1490    __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
1491    __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index())));
1492    __ mov(ecx, Immediate(constant_elements));
1493    FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
1494    __ CallStub(&stub);
1495    RestoreContext();
1496  }
1497  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
1498
1499  bool result_saved = false;  // Is the result saved to the stack?
1500  ZoneList<Expression*>* subexprs = expr->values();
1501  int length = subexprs->length();
1502
1503  // Emit code to evaluate all the non-constant subexpressions and to store
1504  // them into the newly cloned array.
1505  for (int array_index = 0; array_index < length; array_index++) {
1506    Expression* subexpr = subexprs->at(array_index);
1507    DCHECK(!subexpr->IsSpread());
1508
1509    // If the subexpression is a literal or a simple materialized literal it
1510    // is already set in the cloned array.
1511    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1512
1513    if (!result_saved) {
1514      PushOperand(eax);  // array literal.
1515      result_saved = true;
1516    }
1517    VisitForAccumulatorValue(subexpr);
1518
1519    __ mov(StoreDescriptor::NameRegister(),
1520           Immediate(Smi::FromInt(array_index)));
1521    __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
1522    CallKeyedStoreIC(expr->LiteralFeedbackSlot());
1523    PrepareForBailoutForId(expr->GetIdForElement(array_index),
1524                           BailoutState::NO_REGISTERS);
1525  }
1526
1527  if (result_saved) {
1528    context()->PlugTOS();
1529  } else {
1530    context()->Plug(eax);
1531  }
1532}
1533
1534
1535void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1536  DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
1537
1538  Comment cmnt(masm_, "[ Assignment");
1539
1540  Property* property = expr->target()->AsProperty();
1541  LhsKind assign_type = Property::GetAssignType(property);
1542
1543  // Evaluate LHS expression.
1544  switch (assign_type) {
1545    case VARIABLE:
1546      // Nothing to do here.
1547      break;
1548    case NAMED_SUPER_PROPERTY:
1549      VisitForStackValue(
1550          property->obj()->AsSuperPropertyReference()->this_var());
1551      VisitForAccumulatorValue(
1552          property->obj()->AsSuperPropertyReference()->home_object());
1553      PushOperand(result_register());
1554      if (expr->is_compound()) {
1555        PushOperand(MemOperand(esp, kPointerSize));
1556        PushOperand(result_register());
1557      }
1558      break;
1559    case NAMED_PROPERTY:
1560      if (expr->is_compound()) {
1561        // We need the receiver both on the stack and in the register.
1562        VisitForStackValue(property->obj());
1563        __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
1564      } else {
1565        VisitForStackValue(property->obj());
1566      }
1567      break;
1568    case KEYED_SUPER_PROPERTY:
1569      VisitForStackValue(
1570          property->obj()->AsSuperPropertyReference()->this_var());
1571      VisitForStackValue(
1572          property->obj()->AsSuperPropertyReference()->home_object());
1573      VisitForAccumulatorValue(property->key());
1574      PushOperand(result_register());
1575      if (expr->is_compound()) {
1576        PushOperand(MemOperand(esp, 2 * kPointerSize));
1577        PushOperand(MemOperand(esp, 2 * kPointerSize));
1578        PushOperand(result_register());
1579      }
1580      break;
1581    case KEYED_PROPERTY: {
1582      if (expr->is_compound()) {
1583        VisitForStackValue(property->obj());
1584        VisitForStackValue(property->key());
1585        __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, kPointerSize));
1586        __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0));
1587      } else {
1588        VisitForStackValue(property->obj());
1589        VisitForStackValue(property->key());
1590      }
1591      break;
1592    }
1593  }
1594
1595  // For compound assignments we need another deoptimization point after the
1596  // variable/property load.
1597  if (expr->is_compound()) {
1598    AccumulatorValueContext result_context(this);
1599    { AccumulatorValueContext left_operand_context(this);
1600      switch (assign_type) {
1601        case VARIABLE:
1602          EmitVariableLoad(expr->target()->AsVariableProxy());
1603          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
1604          break;
1605        case NAMED_SUPER_PROPERTY:
1606          EmitNamedSuperPropertyLoad(property);
1607          PrepareForBailoutForId(property->LoadId(),
1608                                 BailoutState::TOS_REGISTER);
1609          break;
1610        case NAMED_PROPERTY:
1611          EmitNamedPropertyLoad(property);
1612          PrepareForBailoutForId(property->LoadId(),
1613                                 BailoutState::TOS_REGISTER);
1614          break;
1615        case KEYED_SUPER_PROPERTY:
1616          EmitKeyedSuperPropertyLoad(property);
1617          PrepareForBailoutForId(property->LoadId(),
1618                                 BailoutState::TOS_REGISTER);
1619          break;
1620        case KEYED_PROPERTY:
1621          EmitKeyedPropertyLoad(property);
1622          PrepareForBailoutForId(property->LoadId(),
1623                                 BailoutState::TOS_REGISTER);
1624          break;
1625      }
1626    }
1627
1628    Token::Value op = expr->binary_op();
1629    PushOperand(eax);  // Left operand goes on the stack.
1630    VisitForAccumulatorValue(expr->value());
1631
1632    if (ShouldInlineSmiCase(op)) {
1633      EmitInlineSmiBinaryOp(expr->binary_operation(),
1634                            op,
1635                            expr->target(),
1636                            expr->value());
1637    } else {
1638      EmitBinaryOp(expr->binary_operation(), op);
1639    }
1640
1641    // Deoptimization point in case the binary operation may have side effects.
1642    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
1643  } else {
1644    VisitForAccumulatorValue(expr->value());
1645  }
1646
1647  SetExpressionPosition(expr);
1648
1649  // Store the value.
1650  switch (assign_type) {
1651    case VARIABLE: {
1652      VariableProxy* proxy = expr->target()->AsVariableProxy();
1653      EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(),
1654                             proxy->hole_check_mode());
1655      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
1656      context()->Plug(eax);
1657      break;
1658    }
1659    case NAMED_PROPERTY:
1660      EmitNamedPropertyAssignment(expr);
1661      break;
1662    case NAMED_SUPER_PROPERTY:
1663      EmitNamedSuperPropertyStore(property);
1664      context()->Plug(result_register());
1665      break;
1666    case KEYED_SUPER_PROPERTY:
1667      EmitKeyedSuperPropertyStore(property);
1668      context()->Plug(result_register());
1669      break;
1670    case KEYED_PROPERTY:
1671      EmitKeyedPropertyAssignment(expr);
1672      break;
1673  }
1674}
1675
1676
1677void FullCodeGenerator::VisitYield(Yield* expr) {
1678  Comment cmnt(masm_, "[ Yield");
1679  SetExpressionPosition(expr);
1680
1681  // Evaluate yielded value first; the initial iterator definition depends on
1682  // this.  It stays on the stack while we update the iterator.
1683  VisitForStackValue(expr->expression());
1684
1685  Label suspend, continuation, post_runtime, resume, exception;
1686
1687  __ jmp(&suspend);
1688  __ bind(&continuation);
1689  // When we arrive here, eax holds the generator object.
1690  __ RecordGeneratorContinuation();
1691  __ mov(ebx, FieldOperand(eax, JSGeneratorObject::kResumeModeOffset));
1692  __ mov(eax, FieldOperand(eax, JSGeneratorObject::kInputOrDebugPosOffset));
1693  STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
1694  STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
1695  __ cmp(ebx, Immediate(Smi::FromInt(JSGeneratorObject::kReturn)));
1696  __ j(less, &resume);
1697  __ Push(result_register());
1698  __ j(greater, &exception);
1699  EmitCreateIteratorResult(true);
1700  EmitUnwindAndReturn();
1701
1702  __ bind(&exception);
1703  __ CallRuntime(expr->rethrow_on_exception() ? Runtime::kReThrow
1704                                              : Runtime::kThrow);
1705
1706  __ bind(&suspend);
1707  OperandStackDepthIncrement(1);  // Not popped on this path.
1708  VisitForAccumulatorValue(expr->generator_object());
1709  DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
1710  __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
1711         Immediate(Smi::FromInt(continuation.pos())));
1712  __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi);
1713  __ mov(ecx, esi);
1714  __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
1715                      kDontSaveFPRegs);
1716  __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset));
1717  __ cmp(esp, ebx);
1718  __ j(equal, &post_runtime);
1719  __ push(eax);  // generator object
1720  __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
1721  RestoreContext();
1722  __ bind(&post_runtime);
1723  PopOperand(result_register());
1724  EmitReturnSequence();
1725
1726  __ bind(&resume);
1727  context()->Plug(result_register());
1728}
1729
1730void FullCodeGenerator::PushOperand(MemOperand operand) {
1731  OperandStackDepthIncrement(1);
1732  __ Push(operand);
1733}
1734
1735void FullCodeGenerator::EmitOperandStackDepthCheck() {
1736  if (FLAG_debug_code) {
1737    int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp +
1738                        operand_stack_depth_ * kPointerSize;
1739    __ mov(eax, ebp);
1740    __ sub(eax, esp);
1741    __ cmp(eax, Immediate(expected_diff));
1742    __ Assert(equal, kUnexpectedStackDepth);
1743  }
1744}
1745
1746void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
1747  Label allocate, done_allocate;
1748
1749  __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate,
1750              NO_ALLOCATION_FLAGS);
1751  __ jmp(&done_allocate, Label::kNear);
1752
1753  __ bind(&allocate);
1754  __ Push(Smi::FromInt(JSIteratorResult::kSize));
1755  __ CallRuntime(Runtime::kAllocateInNewSpace);
1756
1757  __ bind(&done_allocate);
1758  __ mov(ebx, NativeContextOperand());
1759  __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX));
1760  __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
1761  __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
1762         isolate()->factory()->empty_fixed_array());
1763  __ mov(FieldOperand(eax, JSObject::kElementsOffset),
1764         isolate()->factory()->empty_fixed_array());
1765  __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset));
1766  __ mov(FieldOperand(eax, JSIteratorResult::kDoneOffset),
1767         isolate()->factory()->ToBoolean(done));
1768  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
1769  OperandStackDepthDecrement(1);
1770}
1771
1772
1773void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
1774                                              Token::Value op,
1775                                              Expression* left,
1776                                              Expression* right) {
1777  // Do combined smi check of the operands. Left operand is on the
1778  // stack. Right operand is in eax.
1779  Label smi_case, done, stub_call;
1780  PopOperand(edx);
1781  __ mov(ecx, eax);
1782  __ or_(eax, edx);
1783  JumpPatchSite patch_site(masm_);
1784  patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear);
1785
1786  __ bind(&stub_call);
1787  __ mov(eax, ecx);
1788  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
1789  CallIC(code, expr->BinaryOperationFeedbackId());
1790  patch_site.EmitPatchInfo();
1791  __ jmp(&done, Label::kNear);
1792
1793  // Smi case.
1794  __ bind(&smi_case);
1795  __ mov(eax, edx);  // Copy left operand in case of a stub call.
1796
1797  switch (op) {
1798    case Token::SAR:
1799      __ SmiUntag(ecx);
1800      __ sar_cl(eax);  // No checks of result necessary
1801      __ and_(eax, Immediate(~kSmiTagMask));
1802      break;
1803    case Token::SHL: {
1804      Label result_ok;
1805      __ SmiUntag(eax);
1806      __ SmiUntag(ecx);
1807      __ shl_cl(eax);
1808      // Check that the *signed* result fits in a smi.
1809      __ cmp(eax, 0xc0000000);
1810      __ j(positive, &result_ok);
1811      __ SmiTag(ecx);
1812      __ jmp(&stub_call);
1813      __ bind(&result_ok);
1814      __ SmiTag(eax);
1815      break;
1816    }
1817    case Token::SHR: {
1818      Label result_ok;
1819      __ SmiUntag(eax);
1820      __ SmiUntag(ecx);
1821      __ shr_cl(eax);
1822      __ test(eax, Immediate(0xc0000000));
1823      __ j(zero, &result_ok);
1824      __ SmiTag(ecx);
1825      __ jmp(&stub_call);
1826      __ bind(&result_ok);
1827      __ SmiTag(eax);
1828      break;
1829    }
1830    case Token::ADD:
1831      __ add(eax, ecx);
1832      __ j(overflow, &stub_call);
1833      break;
1834    case Token::SUB:
1835      __ sub(eax, ecx);
1836      __ j(overflow, &stub_call);
1837      break;
1838    case Token::MUL: {
1839      __ SmiUntag(eax);
1840      __ imul(eax, ecx);
1841      __ j(overflow, &stub_call);
1842      __ test(eax, eax);
1843      __ j(not_zero, &done, Label::kNear);
1844      __ mov(ebx, edx);
1845      __ or_(ebx, ecx);
1846      __ j(negative, &stub_call);
1847      break;
1848    }
1849    case Token::BIT_OR:
1850      __ or_(eax, ecx);
1851      break;
1852    case Token::BIT_AND:
1853      __ and_(eax, ecx);
1854      break;
1855    case Token::BIT_XOR:
1856      __ xor_(eax, ecx);
1857      break;
1858    default:
1859      UNREACHABLE();
1860  }
1861
1862  __ bind(&done);
1863  context()->Plug(eax);
1864}
1865
1866
1867void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
1868  for (int i = 0; i < lit->properties()->length(); i++) {
1869    ClassLiteral::Property* property = lit->properties()->at(i);
1870    Expression* value = property->value();
1871
1872    if (property->is_static()) {
1873      PushOperand(Operand(esp, kPointerSize));  // constructor
1874    } else {
1875      PushOperand(Operand(esp, 0));  // prototype
1876    }
1877    EmitPropertyKey(property, lit->GetIdForProperty(i));
1878
1879    // The static prototype property is read only. We handle the non computed
1880    // property name case in the parser. Since this is the only case where we
1881    // need to check for an own read only property we special case this so we do
1882    // not need to do this for every property.
1883    if (property->is_static() && property->is_computed_name()) {
1884      __ CallRuntime(Runtime::kThrowIfStaticPrototype);
1885      __ push(eax);
1886    }
1887
1888    VisitForStackValue(value);
1889    if (NeedsHomeObject(value)) {
1890      EmitSetHomeObject(value, 2, property->GetSlot());
1891    }
1892
1893    switch (property->kind()) {
1894      case ClassLiteral::Property::METHOD:
1895        PushOperand(Smi::FromInt(DONT_ENUM));
1896        PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
1897        CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
1898        break;
1899
1900      case ClassLiteral::Property::GETTER:
1901        PushOperand(Smi::FromInt(DONT_ENUM));
1902        CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked);
1903        break;
1904
1905      case ClassLiteral::Property::SETTER:
1906        PushOperand(Smi::FromInt(DONT_ENUM));
1907        CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked);
1908        break;
1909
1910      case ClassLiteral::Property::FIELD:
1911        UNREACHABLE();
1912        break;
1913    }
1914  }
1915}
1916
1917
1918void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
1919  PopOperand(edx);
1920  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
1921  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
1922  CallIC(code, expr->BinaryOperationFeedbackId());
1923  patch_site.EmitPatchInfo();
1924  context()->Plug(eax);
1925}
1926
1927
1928void FullCodeGenerator::EmitAssignment(Expression* expr,
1929                                       FeedbackVectorSlot slot) {
1930  DCHECK(expr->IsValidReferenceExpressionOrThis());
1931
1932  Property* prop = expr->AsProperty();
1933  LhsKind assign_type = Property::GetAssignType(prop);
1934
1935  switch (assign_type) {
1936    case VARIABLE: {
1937      VariableProxy* proxy = expr->AsVariableProxy();
1938      EffectContext context(this);
1939      EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot,
1940                             proxy->hole_check_mode());
1941      break;
1942    }
1943    case NAMED_PROPERTY: {
1944      PushOperand(eax);  // Preserve value.
1945      VisitForAccumulatorValue(prop->obj());
1946      __ Move(StoreDescriptor::ReceiverRegister(), eax);
1947      PopOperand(StoreDescriptor::ValueRegister());  // Restore value.
1948      CallStoreIC(slot, prop->key()->AsLiteral()->value());
1949      break;
1950    }
1951    case NAMED_SUPER_PROPERTY: {
1952      PushOperand(eax);
1953      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
1954      VisitForAccumulatorValue(
1955          prop->obj()->AsSuperPropertyReference()->home_object());
1956      // stack: value, this; eax: home_object
1957      Register scratch = ecx;
1958      Register scratch2 = edx;
1959      __ mov(scratch, result_register());               // home_object
1960      __ mov(eax, MemOperand(esp, kPointerSize));       // value
1961      __ mov(scratch2, MemOperand(esp, 0));             // this
1962      __ mov(MemOperand(esp, kPointerSize), scratch2);  // this
1963      __ mov(MemOperand(esp, 0), scratch);              // home_object
1964      // stack: this, home_object. eax: value
1965      EmitNamedSuperPropertyStore(prop);
1966      break;
1967    }
1968    case KEYED_SUPER_PROPERTY: {
1969      PushOperand(eax);
1970      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
1971      VisitForStackValue(
1972          prop->obj()->AsSuperPropertyReference()->home_object());
1973      VisitForAccumulatorValue(prop->key());
1974      Register scratch = ecx;
1975      Register scratch2 = edx;
1976      __ mov(scratch2, MemOperand(esp, 2 * kPointerSize));  // value
1977      // stack: value, this, home_object; eax: key, edx: value
1978      __ mov(scratch, MemOperand(esp, kPointerSize));  // this
1979      __ mov(MemOperand(esp, 2 * kPointerSize), scratch);
1980      __ mov(scratch, MemOperand(esp, 0));  // home_object
1981      __ mov(MemOperand(esp, kPointerSize), scratch);
1982      __ mov(MemOperand(esp, 0), eax);
1983      __ mov(eax, scratch2);
1984      // stack: this, home_object, key; eax: value.
1985      EmitKeyedSuperPropertyStore(prop);
1986      break;
1987    }
1988    case KEYED_PROPERTY: {
1989      PushOperand(eax);  // Preserve value.
1990      VisitForStackValue(prop->obj());
1991      VisitForAccumulatorValue(prop->key());
1992      __ Move(StoreDescriptor::NameRegister(), eax);
1993      PopOperand(StoreDescriptor::ReceiverRegister());  // Receiver.
1994      PopOperand(StoreDescriptor::ValueRegister());     // Restore value.
1995      CallKeyedStoreIC(slot);
1996      break;
1997    }
1998  }
1999  context()->Plug(eax);
2000}
2001
2002
2003void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2004    Variable* var, MemOperand location) {
2005  __ mov(location, eax);
2006  if (var->IsContextSlot()) {
2007    __ mov(edx, eax);
2008    int offset = Context::SlotOffset(var->index());
2009    __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs);
2010  }
2011}
2012
2013void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
2014                                               FeedbackVectorSlot slot,
2015                                               HoleCheckMode hole_check_mode) {
2016  if (var->IsUnallocated()) {
2017    // Global var, const, or let.
2018    __ mov(StoreDescriptor::ReceiverRegister(), NativeContextOperand());
2019    __ mov(StoreDescriptor::ReceiverRegister(),
2020           ContextOperand(StoreDescriptor::ReceiverRegister(),
2021                          Context::EXTENSION_INDEX));
2022    CallStoreIC(slot, var->name());
2023
2024  } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
2025    DCHECK(!var->IsLookupSlot());
2026    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2027    MemOperand location = VarOperand(var, ecx);
2028    // Perform an initialization check for lexically declared variables.
2029    if (hole_check_mode == HoleCheckMode::kRequired) {
2030      Label assign;
2031      __ mov(edx, location);
2032      __ cmp(edx, isolate()->factory()->the_hole_value());
2033      __ j(not_equal, &assign, Label::kNear);
2034      __ push(Immediate(var->name()));
2035      __ CallRuntime(Runtime::kThrowReferenceError);
2036      __ bind(&assign);
2037    }
2038    if (var->mode() != CONST) {
2039      EmitStoreToStackLocalOrContextSlot(var, location);
2040    } else if (var->throw_on_const_assignment(language_mode())) {
2041      __ CallRuntime(Runtime::kThrowConstAssignError);
2042    }
2043  } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) {
2044    // Initializing assignment to const {this} needs a write barrier.
2045    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2046    Label uninitialized_this;
2047    MemOperand location = VarOperand(var, ecx);
2048    __ mov(edx, location);
2049    __ cmp(edx, isolate()->factory()->the_hole_value());
2050    __ j(equal, &uninitialized_this);
2051    __ push(Immediate(var->name()));
2052    __ CallRuntime(Runtime::kThrowReferenceError);
2053    __ bind(&uninitialized_this);
2054    EmitStoreToStackLocalOrContextSlot(var, location);
2055
2056  } else {
2057    DCHECK(var->mode() != CONST || op == Token::INIT);
2058    if (var->IsLookupSlot()) {
2059      // Assignment to var.
2060      __ Push(Immediate(var->name()));
2061      __ Push(eax);
2062      __ CallRuntime(is_strict(language_mode())
2063                         ? Runtime::kStoreLookupSlot_Strict
2064                         : Runtime::kStoreLookupSlot_Sloppy);
2065    } else {
2066      // Assignment to var or initializing assignment to let/const in harmony
2067      // mode.
2068      DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2069      MemOperand location = VarOperand(var, ecx);
2070      if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) {
2071        // Check for an uninitialized let binding.
2072        __ mov(edx, location);
2073        __ cmp(edx, isolate()->factory()->the_hole_value());
2074        __ Check(equal, kLetBindingReInitialization);
2075      }
2076      EmitStoreToStackLocalOrContextSlot(var, location);
2077    }
2078  }
2079}
2080
2081
2082void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2083  // Assignment to a property, using a named store IC.
2084  // eax    : value
2085  // esp[0] : receiver
2086  Property* prop = expr->target()->AsProperty();
2087  DCHECK(prop != NULL);
2088  DCHECK(prop->key()->IsLiteral());
2089
2090  PopOperand(StoreDescriptor::ReceiverRegister());
2091  CallStoreIC(expr->AssignmentSlot(), prop->key()->AsLiteral()->value());
2092  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2093  context()->Plug(eax);
2094}
2095
2096
2097void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
2098  // Assignment to named property of super.
2099  // eax : value
2100  // stack : receiver ('this'), home_object
2101  DCHECK(prop != NULL);
2102  Literal* key = prop->key()->AsLiteral();
2103  DCHECK(key != NULL);
2104
2105  PushOperand(key->value());
2106  PushOperand(eax);
2107  CallRuntimeWithOperands(is_strict(language_mode())
2108                              ? Runtime::kStoreToSuper_Strict
2109                              : Runtime::kStoreToSuper_Sloppy);
2110}
2111
2112
2113void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
2114  // Assignment to named property of super.
2115  // eax : value
2116  // stack : receiver ('this'), home_object, key
2117
2118  PushOperand(eax);
2119  CallRuntimeWithOperands(is_strict(language_mode())
2120                              ? Runtime::kStoreKeyedToSuper_Strict
2121                              : Runtime::kStoreKeyedToSuper_Sloppy);
2122}
2123
2124
2125void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2126  // Assignment to a property, using a keyed store IC.
2127  // eax               : value
2128  // esp[0]            : key
2129  // esp[kPointerSize] : receiver
2130
2131  PopOperand(StoreDescriptor::NameRegister());  // Key.
2132  PopOperand(StoreDescriptor::ReceiverRegister());
2133  DCHECK(StoreDescriptor::ValueRegister().is(eax));
2134  CallKeyedStoreIC(expr->AssignmentSlot());
2135  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2136  context()->Plug(eax);
2137}
2138
2139// Code common for calls using the IC.
2140void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
2141  Expression* callee = expr->expression();
2142
2143  // Get the target function.
2144  ConvertReceiverMode convert_mode;
2145  if (callee->IsVariableProxy()) {
2146    { StackValueContext context(this);
2147      EmitVariableLoad(callee->AsVariableProxy());
2148      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
2149    }
2150    // Push undefined as receiver. This is patched in the method prologue if it
2151    // is a sloppy mode method.
2152    PushOperand(isolate()->factory()->undefined_value());
2153    convert_mode = ConvertReceiverMode::kNullOrUndefined;
2154  } else {
2155    // Load the function from the receiver.
2156    DCHECK(callee->IsProperty());
2157    DCHECK(!callee->AsProperty()->IsSuperAccess());
2158    __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
2159    EmitNamedPropertyLoad(callee->AsProperty());
2160    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
2161                           BailoutState::TOS_REGISTER);
2162    // Push the target function under the receiver.
2163    PushOperand(Operand(esp, 0));
2164    __ mov(Operand(esp, kPointerSize), eax);
2165    convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
2166  }
2167
2168  EmitCall(expr, convert_mode);
2169}
2170
2171
2172void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
2173  SetExpressionPosition(expr);
2174  Expression* callee = expr->expression();
2175  DCHECK(callee->IsProperty());
2176  Property* prop = callee->AsProperty();
2177  DCHECK(prop->IsSuperAccess());
2178
2179  Literal* key = prop->key()->AsLiteral();
2180  DCHECK(!key->value()->IsSmi());
2181  // Load the function from the receiver.
2182  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
2183  VisitForStackValue(super_ref->home_object());
2184  VisitForAccumulatorValue(super_ref->this_var());
2185  PushOperand(eax);
2186  PushOperand(eax);
2187  PushOperand(Operand(esp, kPointerSize * 2));
2188  PushOperand(key->value());
2189  // Stack here:
2190  //  - home_object
2191  //  - this (receiver)
2192  //  - this (receiver) <-- LoadFromSuper will pop here and below.
2193  //  - home_object
2194  //  - key
2195  CallRuntimeWithOperands(Runtime::kLoadFromSuper);
2196  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
2197
2198  // Replace home_object with target function.
2199  __ mov(Operand(esp, kPointerSize), eax);
2200
2201  // Stack here:
2202  // - target function
2203  // - this (receiver)
2204  EmitCall(expr);
2205}
2206
2207
2208// Code common for calls using the IC.
2209void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2210                                                Expression* key) {
2211  // Load the key.
2212  VisitForAccumulatorValue(key);
2213
2214  Expression* callee = expr->expression();
2215
2216  // Load the function from the receiver.
2217  DCHECK(callee->IsProperty());
2218  __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
2219  __ mov(LoadDescriptor::NameRegister(), eax);
2220  EmitKeyedPropertyLoad(callee->AsProperty());
2221  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
2222                         BailoutState::TOS_REGISTER);
2223
2224  // Push the target function under the receiver.
2225  PushOperand(Operand(esp, 0));
2226  __ mov(Operand(esp, kPointerSize), eax);
2227
2228  EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined);
2229}
2230
2231
2232void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
2233  Expression* callee = expr->expression();
2234  DCHECK(callee->IsProperty());
2235  Property* prop = callee->AsProperty();
2236  DCHECK(prop->IsSuperAccess());
2237
2238  SetExpressionPosition(prop);
2239  // Load the function from the receiver.
2240  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
2241  VisitForStackValue(super_ref->home_object());
2242  VisitForAccumulatorValue(super_ref->this_var());
2243  PushOperand(eax);
2244  PushOperand(eax);
2245  PushOperand(Operand(esp, kPointerSize * 2));
2246  VisitForStackValue(prop->key());
2247  // Stack here:
2248  //  - home_object
2249  //  - this (receiver)
2250  //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
2251  //  - home_object
2252  //  - key
2253  CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
2254  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
2255
2256  // Replace home_object with target function.
2257  __ mov(Operand(esp, kPointerSize), eax);
2258
2259  // Stack here:
2260  // - target function
2261  // - this (receiver)
2262  EmitCall(expr);
2263}
2264
2265
2266void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
2267  // Load the arguments.
2268  ZoneList<Expression*>* args = expr->arguments();
2269  int arg_count = args->length();
2270  for (int i = 0; i < arg_count; i++) {
2271    VisitForStackValue(args->at(i));
2272  }
2273
2274  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
2275  SetCallPosition(expr, expr->tail_call_mode());
2276  if (expr->tail_call_mode() == TailCallMode::kAllow) {
2277    if (FLAG_trace) {
2278      __ CallRuntime(Runtime::kTraceTailCall);
2279    }
2280    // Update profiling counters before the tail call since we will
2281    // not return to this function.
2282    EmitProfilingCounterHandlingForReturnSequence(true);
2283  }
2284  Handle<Code> code =
2285      CodeFactory::CallIC(isolate(), mode, expr->tail_call_mode()).code();
2286  __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot())));
2287  __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2288  __ Move(eax, Immediate(arg_count));
2289  CallIC(code);
2290  OperandStackDepthDecrement(arg_count + 1);
2291
2292  RecordJSReturnSite(expr);
2293  RestoreContext();
2294  context()->DropAndPlug(1, eax);
2295}
2296
2297void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
2298  int arg_count = expr->arguments()->length();
2299  // Push copy of the first argument or undefined if it doesn't exist.
2300  if (arg_count > 0) {
2301    __ push(Operand(esp, arg_count * kPointerSize));
2302  } else {
2303    __ push(Immediate(isolate()->factory()->undefined_value()));
2304  }
2305
2306  // Push the enclosing function.
2307  __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
2308
2309  // Push the language mode.
2310  __ push(Immediate(Smi::FromInt(language_mode())));
2311
2312  // Push the start position of the scope the calls resides in.
2313  __ push(Immediate(Smi::FromInt(scope()->start_position())));
2314
2315  // Push the source position of the eval call.
2316  __ push(Immediate(Smi::FromInt(expr->position())));
2317
2318  // Do the runtime call.
2319  __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
2320}
2321
2322
2323// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
2324void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
2325  VariableProxy* callee = expr->expression()->AsVariableProxy();
2326  if (callee->var()->IsLookupSlot()) {
2327    Label slow, done;
2328    SetExpressionPosition(callee);
2329    // Generate code for loading from variables potentially shadowed by
2330    // eval-introduced variables.
2331    EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
2332
2333    __ bind(&slow);
2334    // Call the runtime to find the function to call (returned in eax) and
2335    // the object holding it (returned in edx).
2336    __ Push(callee->name());
2337    __ CallRuntime(Runtime::kLoadLookupSlotForCall);
2338    PushOperand(eax);  // Function.
2339    PushOperand(edx);  // Receiver.
2340    PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
2341
2342    // If fast case code has been generated, emit code to push the function
2343    // and receiver and have the slow path jump around this code.
2344    if (done.is_linked()) {
2345      Label call;
2346      __ jmp(&call, Label::kNear);
2347      __ bind(&done);
2348      // Push function.
2349      __ push(eax);
2350      // The receiver is implicitly the global receiver. Indicate this by
2351      // passing the hole to the call function stub.
2352      __ push(Immediate(isolate()->factory()->undefined_value()));
2353      __ bind(&call);
2354    }
2355  } else {
2356    VisitForStackValue(callee);
2357    // refEnv.WithBaseObject()
2358    PushOperand(isolate()->factory()->undefined_value());
2359  }
2360}
2361
2362
2363void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
2364  // In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
2365  // to resolve the function we need to call.  Then we call the resolved
2366  // function using the given arguments.
2367  ZoneList<Expression*>* args = expr->arguments();
2368  int arg_count = args->length();
2369
2370  PushCalleeAndWithBaseObject(expr);
2371
2372  // Push the arguments.
2373  for (int i = 0; i < arg_count; i++) {
2374    VisitForStackValue(args->at(i));
2375  }
2376
2377  // Push a copy of the function (found below the arguments) and
2378  // resolve eval.
2379  __ push(Operand(esp, (arg_count + 1) * kPointerSize));
2380  EmitResolvePossiblyDirectEval(expr);
2381
2382  // Touch up the stack with the resolved function.
2383  __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
2384
2385  PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
2386
2387  SetCallPosition(expr);
2388  Handle<Code> code = CodeFactory::CallIC(isolate(), ConvertReceiverMode::kAny,
2389                                          expr->tail_call_mode())
2390                          .code();
2391  __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot())));
2392  __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2393  __ Move(eax, Immediate(arg_count));
2394  __ call(code, RelocInfo::CODE_TARGET);
2395  OperandStackDepthDecrement(arg_count + 1);
2396  RecordJSReturnSite(expr);
2397  RestoreContext();
2398  context()->DropAndPlug(1, eax);
2399}
2400
2401
2402void FullCodeGenerator::VisitCallNew(CallNew* expr) {
2403  Comment cmnt(masm_, "[ CallNew");
2404  // According to ECMA-262, section 11.2.2, page 44, the function
2405  // expression in new calls must be evaluated before the
2406  // arguments.
2407
2408  // Push constructor on the stack.  If it's not a function it's used as
2409  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
2410  // ignored.
2411  DCHECK(!expr->expression()->IsSuperPropertyReference());
2412  VisitForStackValue(expr->expression());
2413
2414  // Push the arguments ("left-to-right") on the stack.
2415  ZoneList<Expression*>* args = expr->arguments();
2416  int arg_count = args->length();
2417  for (int i = 0; i < arg_count; i++) {
2418    VisitForStackValue(args->at(i));
2419  }
2420
2421  // Call the construct call builtin that handles allocation and
2422  // constructor invocation.
2423  SetConstructCallPosition(expr);
2424
2425  // Load function and argument count into edi and eax.
2426  __ Move(eax, Immediate(arg_count));
2427  __ mov(edi, Operand(esp, arg_count * kPointerSize));
2428
2429  // Record call targets in unoptimized code.
2430  __ EmitLoadTypeFeedbackVector(ebx);
2431  __ mov(edx, Immediate(SmiFromSlot(expr->CallNewFeedbackSlot())));
2432
2433  CallConstructStub stub(isolate());
2434  CallIC(stub.GetCode());
2435  OperandStackDepthDecrement(arg_count + 1);
2436  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
2437  RestoreContext();
2438  context()->Plug(eax);
2439}
2440
2441
2442void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
2443  SuperCallReference* super_call_ref =
2444      expr->expression()->AsSuperCallReference();
2445  DCHECK_NOT_NULL(super_call_ref);
2446
2447  // Push the super constructor target on the stack (may be null,
2448  // but the Construct builtin can deal with that properly).
2449  VisitForAccumulatorValue(super_call_ref->this_function_var());
2450  __ AssertFunction(result_register());
2451  __ mov(result_register(),
2452         FieldOperand(result_register(), HeapObject::kMapOffset));
2453  PushOperand(FieldOperand(result_register(), Map::kPrototypeOffset));
2454
2455  // Push the arguments ("left-to-right") on the stack.
2456  ZoneList<Expression*>* args = expr->arguments();
2457  int arg_count = args->length();
2458  for (int i = 0; i < arg_count; i++) {
2459    VisitForStackValue(args->at(i));
2460  }
2461
2462  // Call the construct call builtin that handles allocation and
2463  // constructor invocation.
2464  SetConstructCallPosition(expr);
2465
2466  // Load new target into edx.
2467  VisitForAccumulatorValue(super_call_ref->new_target_var());
2468  __ mov(edx, result_register());
2469
2470  // Load function and argument count into edi and eax.
2471  __ Move(eax, Immediate(arg_count));
2472  __ mov(edi, Operand(esp, arg_count * kPointerSize));
2473
2474  __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
2475  OperandStackDepthDecrement(arg_count + 1);
2476
2477  RecordJSReturnSite(expr);
2478  RestoreContext();
2479  context()->Plug(eax);
2480}
2481
2482
2483void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2484  ZoneList<Expression*>* args = expr->arguments();
2485  DCHECK(args->length() == 1);
2486
2487  VisitForAccumulatorValue(args->at(0));
2488
2489  Label materialize_true, materialize_false;
2490  Label* if_true = NULL;
2491  Label* if_false = NULL;
2492  Label* fall_through = NULL;
2493  context()->PrepareTest(&materialize_true, &materialize_false,
2494                         &if_true, &if_false, &fall_through);
2495
2496  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2497  __ test(eax, Immediate(kSmiTagMask));
2498  Split(zero, if_true, if_false, fall_through);
2499
2500  context()->Plug(if_true, if_false);
2501}
2502
2503
2504void FullCodeGenerator::EmitIsJSReceiver(CallRuntime* expr) {
2505  ZoneList<Expression*>* args = expr->arguments();
2506  DCHECK(args->length() == 1);
2507
2508  VisitForAccumulatorValue(args->at(0));
2509
2510  Label materialize_true, materialize_false;
2511  Label* if_true = NULL;
2512  Label* if_false = NULL;
2513  Label* fall_through = NULL;
2514  context()->PrepareTest(&materialize_true, &materialize_false,
2515                         &if_true, &if_false, &fall_through);
2516
2517  __ JumpIfSmi(eax, if_false);
2518  __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, ebx);
2519  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2520  Split(above_equal, if_true, if_false, fall_through);
2521
2522  context()->Plug(if_true, if_false);
2523}
2524
2525
2526void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
2527  ZoneList<Expression*>* args = expr->arguments();
2528  DCHECK(args->length() == 1);
2529
2530  VisitForAccumulatorValue(args->at(0));
2531
2532  Label materialize_true, materialize_false;
2533  Label* if_true = NULL;
2534  Label* if_false = NULL;
2535  Label* fall_through = NULL;
2536  context()->PrepareTest(&materialize_true, &materialize_false,
2537                         &if_true, &if_false, &fall_through);
2538
2539  __ JumpIfSmi(eax, if_false);
2540  __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx);
2541  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2542  Split(equal, if_true, if_false, fall_through);
2543
2544  context()->Plug(if_true, if_false);
2545}
2546
2547
2548void FullCodeGenerator::EmitIsTypedArray(CallRuntime* expr) {
2549  ZoneList<Expression*>* args = expr->arguments();
2550  DCHECK(args->length() == 1);
2551
2552  VisitForAccumulatorValue(args->at(0));
2553
2554  Label materialize_true, materialize_false;
2555  Label* if_true = NULL;
2556  Label* if_false = NULL;
2557  Label* fall_through = NULL;
2558  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
2559                         &if_false, &fall_through);
2560
2561  __ JumpIfSmi(eax, if_false);
2562  __ CmpObjectType(eax, JS_TYPED_ARRAY_TYPE, ebx);
2563  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2564  Split(equal, if_true, if_false, fall_through);
2565
2566  context()->Plug(if_true, if_false);
2567}
2568
2569
2570void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
2571  ZoneList<Expression*>* args = expr->arguments();
2572  DCHECK(args->length() == 1);
2573
2574  VisitForAccumulatorValue(args->at(0));
2575
2576  Label materialize_true, materialize_false;
2577  Label* if_true = NULL;
2578  Label* if_false = NULL;
2579  Label* fall_through = NULL;
2580  context()->PrepareTest(&materialize_true, &materialize_false,
2581                         &if_true, &if_false, &fall_through);
2582
2583  __ JumpIfSmi(eax, if_false);
2584  __ CmpObjectType(eax, JS_REGEXP_TYPE, ebx);
2585  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2586  Split(equal, if_true, if_false, fall_through);
2587
2588  context()->Plug(if_true, if_false);
2589}
2590
2591
2592void FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) {
2593  ZoneList<Expression*>* args = expr->arguments();
2594  DCHECK(args->length() == 1);
2595
2596  VisitForAccumulatorValue(args->at(0));
2597
2598  Label materialize_true, materialize_false;
2599  Label* if_true = NULL;
2600  Label* if_false = NULL;
2601  Label* fall_through = NULL;
2602  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
2603                         &if_false, &fall_through);
2604
2605  __ JumpIfSmi(eax, if_false);
2606  __ CmpObjectType(eax, JS_PROXY_TYPE, ebx);
2607  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2608  Split(equal, if_true, if_false, fall_through);
2609
2610  context()->Plug(if_true, if_false);
2611}
2612
2613
2614void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
2615  ZoneList<Expression*>* args = expr->arguments();
2616  DCHECK(args->length() == 1);
2617  Label done, null, function, non_function_constructor;
2618
2619  VisitForAccumulatorValue(args->at(0));
2620
2621  // If the object is not a JSReceiver, we return null.
2622  __ JumpIfSmi(eax, &null, Label::kNear);
2623  STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
2624  __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, eax);
2625  __ j(below, &null, Label::kNear);
2626
2627  // Return 'Function' for JSFunction and JSBoundFunction objects.
2628  __ CmpInstanceType(eax, FIRST_FUNCTION_TYPE);
2629  STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
2630  __ j(above_equal, &function, Label::kNear);
2631
2632  // Check if the constructor in the map is a JS function.
2633  __ GetMapConstructor(eax, eax, ebx);
2634  __ CmpInstanceType(ebx, JS_FUNCTION_TYPE);
2635  __ j(not_equal, &non_function_constructor, Label::kNear);
2636
2637  // eax now contains the constructor function. Grab the
2638  // instance class name from there.
2639  __ mov(eax, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
2640  __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kInstanceClassNameOffset));
2641  __ jmp(&done, Label::kNear);
2642
2643  // Non-JS objects have class null.
2644  __ bind(&null);
2645  __ mov(eax, isolate()->factory()->null_value());
2646  __ jmp(&done, Label::kNear);
2647
2648  // Functions have class 'Function'.
2649  __ bind(&function);
2650  __ mov(eax, isolate()->factory()->Function_string());
2651  __ jmp(&done, Label::kNear);
2652
2653  // Objects with a non-function constructor have class 'Object'.
2654  __ bind(&non_function_constructor);
2655  __ mov(eax, isolate()->factory()->Object_string());
2656
2657  // All done.
2658  __ bind(&done);
2659
2660  context()->Plug(eax);
2661}
2662
2663
2664void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
2665  ZoneList<Expression*>* args = expr->arguments();
2666  DCHECK(args->length() == 2);
2667
2668  VisitForStackValue(args->at(0));
2669  VisitForAccumulatorValue(args->at(1));
2670
2671  Register object = ebx;
2672  Register index = eax;
2673  Register result = edx;
2674
2675  PopOperand(object);
2676
2677  Label need_conversion;
2678  Label index_out_of_range;
2679  Label done;
2680  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
2681                                      &need_conversion, &index_out_of_range);
2682  generator.GenerateFast(masm_);
2683  __ jmp(&done);
2684
2685  __ bind(&index_out_of_range);
2686  // When the index is out of range, the spec requires us to return
2687  // NaN.
2688  __ Move(result, Immediate(isolate()->factory()->nan_value()));
2689  __ jmp(&done);
2690
2691  __ bind(&need_conversion);
2692  // Move the undefined value into the result register, which will
2693  // trigger conversion.
2694  __ Move(result, Immediate(isolate()->factory()->undefined_value()));
2695  __ jmp(&done);
2696
2697  NopRuntimeCallHelper call_helper;
2698  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
2699
2700  __ bind(&done);
2701  context()->Plug(result);
2702}
2703
2704
2705void FullCodeGenerator::EmitCall(CallRuntime* expr) {
2706  ZoneList<Expression*>* args = expr->arguments();
2707  DCHECK_LE(2, args->length());
2708  // Push target, receiver and arguments onto the stack.
2709  for (Expression* const arg : *args) {
2710    VisitForStackValue(arg);
2711  }
2712  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
2713  // Move target to edi.
2714  int const argc = args->length() - 2;
2715  __ mov(edi, Operand(esp, (argc + 1) * kPointerSize));
2716  // Call the target.
2717  __ mov(eax, Immediate(argc));
2718  __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
2719  OperandStackDepthDecrement(argc + 1);
2720  RestoreContext();
2721  // Discard the function left on TOS.
2722  context()->DropAndPlug(1, eax);
2723}
2724
2725void FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) {
2726  ZoneList<Expression*>* args = expr->arguments();
2727  DCHECK_EQ(1, args->length());
2728  VisitForAccumulatorValue(args->at(0));
2729  __ AssertFunction(eax);
2730  __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
2731  __ mov(eax, FieldOperand(eax, Map::kPrototypeOffset));
2732  context()->Plug(eax);
2733}
2734
2735void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
2736  DCHECK(expr->arguments()->length() == 0);
2737  ExternalReference debug_is_active =
2738      ExternalReference::debug_is_active_address(isolate());
2739  __ movzx_b(eax, Operand::StaticVariable(debug_is_active));
2740  __ SmiTag(eax);
2741  context()->Plug(eax);
2742}
2743
2744
2745void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
2746  ZoneList<Expression*>* args = expr->arguments();
2747  DCHECK_EQ(2, args->length());
2748  VisitForStackValue(args->at(0));
2749  VisitForStackValue(args->at(1));
2750
2751  Label runtime, done;
2752
2753  __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &runtime,
2754              NO_ALLOCATION_FLAGS);
2755  __ mov(ebx, NativeContextOperand());
2756  __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX));
2757  __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
2758  __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
2759         isolate()->factory()->empty_fixed_array());
2760  __ mov(FieldOperand(eax, JSObject::kElementsOffset),
2761         isolate()->factory()->empty_fixed_array());
2762  __ pop(FieldOperand(eax, JSIteratorResult::kDoneOffset));
2763  __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset));
2764  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
2765  __ jmp(&done, Label::kNear);
2766
2767  __ bind(&runtime);
2768  CallRuntimeWithOperands(Runtime::kCreateIterResultObject);
2769
2770  __ bind(&done);
2771  context()->Plug(eax);
2772}
2773
2774
2775void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
2776  // Push function.
2777  __ LoadGlobalFunction(expr->context_index(), eax);
2778  PushOperand(eax);
2779
2780  // Push undefined as receiver.
2781  PushOperand(isolate()->factory()->undefined_value());
2782}
2783
2784
2785void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
2786  ZoneList<Expression*>* args = expr->arguments();
2787  int arg_count = args->length();
2788
2789  SetCallPosition(expr);
2790  __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2791  __ Set(eax, arg_count);
2792  __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
2793          RelocInfo::CODE_TARGET);
2794  OperandStackDepthDecrement(arg_count + 1);
2795  RestoreContext();
2796}
2797
2798
2799void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2800  switch (expr->op()) {
2801    case Token::DELETE: {
2802      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
2803      Property* property = expr->expression()->AsProperty();
2804      VariableProxy* proxy = expr->expression()->AsVariableProxy();
2805
2806      if (property != NULL) {
2807        VisitForStackValue(property->obj());
2808        VisitForStackValue(property->key());
2809        CallRuntimeWithOperands(is_strict(language_mode())
2810                                    ? Runtime::kDeleteProperty_Strict
2811                                    : Runtime::kDeleteProperty_Sloppy);
2812        context()->Plug(eax);
2813      } else if (proxy != NULL) {
2814        Variable* var = proxy->var();
2815        // Delete of an unqualified identifier is disallowed in strict mode but
2816        // "delete this" is allowed.
2817        bool is_this = var->is_this();
2818        DCHECK(is_sloppy(language_mode()) || is_this);
2819        if (var->IsUnallocated()) {
2820          __ mov(eax, NativeContextOperand());
2821          __ push(ContextOperand(eax, Context::EXTENSION_INDEX));
2822          __ push(Immediate(var->name()));
2823          __ CallRuntime(Runtime::kDeleteProperty_Sloppy);
2824          context()->Plug(eax);
2825        } else if (var->IsStackAllocated() || var->IsContextSlot()) {
2826          // Result of deleting non-global variables is false.  'this' is
2827          // not really a variable, though we implement it as one.  The
2828          // subexpression does not have side effects.
2829          context()->Plug(is_this);
2830        } else {
2831          // Non-global variable.  Call the runtime to try to delete from the
2832          // context where the variable was introduced.
2833          __ Push(var->name());
2834          __ CallRuntime(Runtime::kDeleteLookupSlot);
2835          context()->Plug(eax);
2836        }
2837      } else {
2838        // Result of deleting non-property, non-variable reference is true.
2839        // The subexpression may have side effects.
2840        VisitForEffect(expr->expression());
2841        context()->Plug(true);
2842      }
2843      break;
2844    }
2845
2846    case Token::VOID: {
2847      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
2848      VisitForEffect(expr->expression());
2849      context()->Plug(isolate()->factory()->undefined_value());
2850      break;
2851    }
2852
2853    case Token::NOT: {
2854      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2855      if (context()->IsEffect()) {
2856        // Unary NOT has no side effects so it's only necessary to visit the
2857        // subexpression.  Match the optimizing compiler by not branching.
2858        VisitForEffect(expr->expression());
2859      } else if (context()->IsTest()) {
2860        const TestContext* test = TestContext::cast(context());
2861        // The labels are swapped for the recursive call.
2862        VisitForControl(expr->expression(),
2863                        test->false_label(),
2864                        test->true_label(),
2865                        test->fall_through());
2866        context()->Plug(test->true_label(), test->false_label());
2867      } else {
2868        // We handle value contexts explicitly rather than simply visiting
2869        // for control and plugging the control flow into the context,
2870        // because we need to prepare a pair of extra administrative AST ids
2871        // for the optimizing compiler.
2872        DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
2873        Label materialize_true, materialize_false, done;
2874        VisitForControl(expr->expression(),
2875                        &materialize_false,
2876                        &materialize_true,
2877                        &materialize_true);
2878        if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
2879        __ bind(&materialize_true);
2880        PrepareForBailoutForId(expr->MaterializeTrueId(),
2881                               BailoutState::NO_REGISTERS);
2882        if (context()->IsAccumulatorValue()) {
2883          __ mov(eax, isolate()->factory()->true_value());
2884        } else {
2885          __ Push(isolate()->factory()->true_value());
2886        }
2887        __ jmp(&done, Label::kNear);
2888        __ bind(&materialize_false);
2889        PrepareForBailoutForId(expr->MaterializeFalseId(),
2890                               BailoutState::NO_REGISTERS);
2891        if (context()->IsAccumulatorValue()) {
2892          __ mov(eax, isolate()->factory()->false_value());
2893        } else {
2894          __ Push(isolate()->factory()->false_value());
2895        }
2896        __ bind(&done);
2897      }
2898      break;
2899    }
2900
2901    case Token::TYPEOF: {
2902      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2903      {
2904        AccumulatorValueContext context(this);
2905        VisitForTypeofValue(expr->expression());
2906      }
2907      __ mov(ebx, eax);
2908      __ Call(isolate()->builtins()->Typeof(), RelocInfo::CODE_TARGET);
2909      context()->Plug(eax);
2910      break;
2911    }
2912
2913    default:
2914      UNREACHABLE();
2915  }
2916}
2917
2918
2919void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
2920  DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
2921
2922  Comment cmnt(masm_, "[ CountOperation");
2923
2924  Property* prop = expr->expression()->AsProperty();
2925  LhsKind assign_type = Property::GetAssignType(prop);
2926
2927  // Evaluate expression and get value.
2928  if (assign_type == VARIABLE) {
2929    DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
2930    AccumulatorValueContext context(this);
2931    EmitVariableLoad(expr->expression()->AsVariableProxy());
2932  } else {
2933    // Reserve space for result of postfix operation.
2934    if (expr->is_postfix() && !context()->IsEffect()) {
2935      PushOperand(Smi::kZero);
2936    }
2937    switch (assign_type) {
2938      case NAMED_PROPERTY: {
2939        // Put the object both on the stack and in the register.
2940        VisitForStackValue(prop->obj());
2941        __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
2942        EmitNamedPropertyLoad(prop);
2943        break;
2944      }
2945
2946      case NAMED_SUPER_PROPERTY: {
2947        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
2948        VisitForAccumulatorValue(
2949            prop->obj()->AsSuperPropertyReference()->home_object());
2950        PushOperand(result_register());
2951        PushOperand(MemOperand(esp, kPointerSize));
2952        PushOperand(result_register());
2953        EmitNamedSuperPropertyLoad(prop);
2954        break;
2955      }
2956
2957      case KEYED_SUPER_PROPERTY: {
2958        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
2959        VisitForStackValue(
2960            prop->obj()->AsSuperPropertyReference()->home_object());
2961        VisitForAccumulatorValue(prop->key());
2962        PushOperand(result_register());
2963        PushOperand(MemOperand(esp, 2 * kPointerSize));
2964        PushOperand(MemOperand(esp, 2 * kPointerSize));
2965        PushOperand(result_register());
2966        EmitKeyedSuperPropertyLoad(prop);
2967        break;
2968      }
2969
2970      case KEYED_PROPERTY: {
2971        VisitForStackValue(prop->obj());
2972        VisitForStackValue(prop->key());
2973        __ mov(LoadDescriptor::ReceiverRegister(),
2974               Operand(esp, kPointerSize));                       // Object.
2975        __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0));  // Key.
2976        EmitKeyedPropertyLoad(prop);
2977        break;
2978      }
2979
2980      case VARIABLE:
2981        UNREACHABLE();
2982    }
2983  }
2984
2985  // We need a second deoptimization point after loading the value
2986  // in case evaluating the property load my have a side effect.
2987  if (assign_type == VARIABLE) {
2988    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
2989  } else {
2990    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
2991  }
2992
2993  // Inline smi case if we are in a loop.
2994  Label done, stub_call;
2995  JumpPatchSite patch_site(masm_);
2996  if (ShouldInlineSmiCase(expr->op())) {
2997    Label slow;
2998    patch_site.EmitJumpIfNotSmi(eax, &slow, Label::kNear);
2999
3000    // Save result for postfix expressions.
3001    if (expr->is_postfix()) {
3002      if (!context()->IsEffect()) {
3003        // Save the result on the stack. If we have a named or keyed property
3004        // we store the result under the receiver that is currently on top
3005        // of the stack.
3006        switch (assign_type) {
3007          case VARIABLE:
3008            __ push(eax);
3009            break;
3010          case NAMED_PROPERTY:
3011            __ mov(Operand(esp, kPointerSize), eax);
3012            break;
3013          case NAMED_SUPER_PROPERTY:
3014            __ mov(Operand(esp, 2 * kPointerSize), eax);
3015            break;
3016          case KEYED_PROPERTY:
3017            __ mov(Operand(esp, 2 * kPointerSize), eax);
3018            break;
3019          case KEYED_SUPER_PROPERTY:
3020            __ mov(Operand(esp, 3 * kPointerSize), eax);
3021            break;
3022        }
3023      }
3024    }
3025
3026    if (expr->op() == Token::INC) {
3027      __ add(eax, Immediate(Smi::FromInt(1)));
3028    } else {
3029      __ sub(eax, Immediate(Smi::FromInt(1)));
3030    }
3031    __ j(no_overflow, &done, Label::kNear);
3032    // Call stub. Undo operation first.
3033    if (expr->op() == Token::INC) {
3034      __ sub(eax, Immediate(Smi::FromInt(1)));
3035    } else {
3036      __ add(eax, Immediate(Smi::FromInt(1)));
3037    }
3038    __ jmp(&stub_call, Label::kNear);
3039    __ bind(&slow);
3040  }
3041
3042  // Convert old value into a number.
3043  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
3044  RestoreContext();
3045  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
3046
3047  // Save result for postfix expressions.
3048  if (expr->is_postfix()) {
3049    if (!context()->IsEffect()) {
3050      // Save the result on the stack. If we have a named or keyed property
3051      // we store the result under the receiver that is currently on top
3052      // of the stack.
3053      switch (assign_type) {
3054        case VARIABLE:
3055          PushOperand(eax);
3056          break;
3057        case NAMED_PROPERTY:
3058          __ mov(Operand(esp, kPointerSize), eax);
3059          break;
3060        case NAMED_SUPER_PROPERTY:
3061          __ mov(Operand(esp, 2 * kPointerSize), eax);
3062          break;
3063        case KEYED_PROPERTY:
3064          __ mov(Operand(esp, 2 * kPointerSize), eax);
3065          break;
3066        case KEYED_SUPER_PROPERTY:
3067          __ mov(Operand(esp, 3 * kPointerSize), eax);
3068          break;
3069      }
3070    }
3071  }
3072
3073  SetExpressionPosition(expr);
3074
3075  // Call stub for +1/-1.
3076  __ bind(&stub_call);
3077  __ mov(edx, eax);
3078  __ mov(eax, Immediate(Smi::FromInt(1)));
3079  Handle<Code> code =
3080      CodeFactory::BinaryOpIC(isolate(), expr->binary_op()).code();
3081  CallIC(code, expr->CountBinOpFeedbackId());
3082  patch_site.EmitPatchInfo();
3083  __ bind(&done);
3084
3085  // Store the value returned in eax.
3086  switch (assign_type) {
3087    case VARIABLE: {
3088      VariableProxy* proxy = expr->expression()->AsVariableProxy();
3089      if (expr->is_postfix()) {
3090        // Perform the assignment as if via '='.
3091        { EffectContext context(this);
3092          EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
3093                                 proxy->hole_check_mode());
3094          PrepareForBailoutForId(expr->AssignmentId(),
3095                                 BailoutState::TOS_REGISTER);
3096          context.Plug(eax);
3097        }
3098        // For all contexts except EffectContext We have the result on
3099        // top of the stack.
3100        if (!context()->IsEffect()) {
3101          context()->PlugTOS();
3102        }
3103      } else {
3104        // Perform the assignment as if via '='.
3105        EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(),
3106                               proxy->hole_check_mode());
3107        PrepareForBailoutForId(expr->AssignmentId(),
3108                               BailoutState::TOS_REGISTER);
3109        context()->Plug(eax);
3110      }
3111      break;
3112    }
3113    case NAMED_PROPERTY: {
3114      PopOperand(StoreDescriptor::ReceiverRegister());
3115      CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value());
3116      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3117      if (expr->is_postfix()) {
3118        if (!context()->IsEffect()) {
3119          context()->PlugTOS();
3120        }
3121      } else {
3122        context()->Plug(eax);
3123      }
3124      break;
3125    }
3126    case NAMED_SUPER_PROPERTY: {
3127      EmitNamedSuperPropertyStore(prop);
3128      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3129      if (expr->is_postfix()) {
3130        if (!context()->IsEffect()) {
3131          context()->PlugTOS();
3132        }
3133      } else {
3134        context()->Plug(eax);
3135      }
3136      break;
3137    }
3138    case KEYED_SUPER_PROPERTY: {
3139      EmitKeyedSuperPropertyStore(prop);
3140      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3141      if (expr->is_postfix()) {
3142        if (!context()->IsEffect()) {
3143          context()->PlugTOS();
3144        }
3145      } else {
3146        context()->Plug(eax);
3147      }
3148      break;
3149    }
3150    case KEYED_PROPERTY: {
3151      PopOperand(StoreDescriptor::NameRegister());
3152      PopOperand(StoreDescriptor::ReceiverRegister());
3153      CallKeyedStoreIC(expr->CountSlot());
3154      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3155      if (expr->is_postfix()) {
3156        // Result is on the stack
3157        if (!context()->IsEffect()) {
3158          context()->PlugTOS();
3159        }
3160      } else {
3161        context()->Plug(eax);
3162      }
3163      break;
3164    }
3165  }
3166}
3167
3168
3169void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
3170                                                 Expression* sub_expr,
3171                                                 Handle<String> check) {
3172  Label materialize_true, materialize_false;
3173  Label* if_true = NULL;
3174  Label* if_false = NULL;
3175  Label* fall_through = NULL;
3176  context()->PrepareTest(&materialize_true, &materialize_false,
3177                         &if_true, &if_false, &fall_through);
3178
3179  { AccumulatorValueContext context(this);
3180    VisitForTypeofValue(sub_expr);
3181  }
3182  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3183
3184  Factory* factory = isolate()->factory();
3185  if (String::Equals(check, factory->number_string())) {
3186    __ JumpIfSmi(eax, if_true);
3187    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3188           isolate()->factory()->heap_number_map());
3189    Split(equal, if_true, if_false, fall_through);
3190  } else if (String::Equals(check, factory->string_string())) {
3191    __ JumpIfSmi(eax, if_false);
3192    __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
3193    Split(below, if_true, if_false, fall_through);
3194  } else if (String::Equals(check, factory->symbol_string())) {
3195    __ JumpIfSmi(eax, if_false);
3196    __ CmpObjectType(eax, SYMBOL_TYPE, edx);
3197    Split(equal, if_true, if_false, fall_through);
3198  } else if (String::Equals(check, factory->boolean_string())) {
3199    __ cmp(eax, isolate()->factory()->true_value());
3200    __ j(equal, if_true);
3201    __ cmp(eax, isolate()->factory()->false_value());
3202    Split(equal, if_true, if_false, fall_through);
3203  } else if (String::Equals(check, factory->undefined_string())) {
3204    __ cmp(eax, isolate()->factory()->null_value());
3205    __ j(equal, if_false);
3206    __ JumpIfSmi(eax, if_false);
3207    // Check for undetectable objects => true.
3208    __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
3209    __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
3210              Immediate(1 << Map::kIsUndetectable));
3211    Split(not_zero, if_true, if_false, fall_through);
3212  } else if (String::Equals(check, factory->function_string())) {
3213    __ JumpIfSmi(eax, if_false);
3214    // Check for callable and not undetectable objects => true.
3215    __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
3216    __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
3217    __ and_(ecx, (1 << Map::kIsCallable) | (1 << Map::kIsUndetectable));
3218    __ cmp(ecx, 1 << Map::kIsCallable);
3219    Split(equal, if_true, if_false, fall_through);
3220  } else if (String::Equals(check, factory->object_string())) {
3221    __ JumpIfSmi(eax, if_false);
3222    __ cmp(eax, isolate()->factory()->null_value());
3223    __ j(equal, if_true);
3224    STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
3225    __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, edx);
3226    __ j(below, if_false);
3227    // Check for callable or undetectable objects => false.
3228    __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
3229              Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
3230    Split(zero, if_true, if_false, fall_through);
3231// clang-format off
3232#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type)   \
3233  } else if (String::Equals(check, factory->type##_string())) { \
3234    __ JumpIfSmi(eax, if_false);                                \
3235    __ cmp(FieldOperand(eax, HeapObject::kMapOffset),           \
3236           isolate()->factory()->type##_map());                 \
3237    Split(equal, if_true, if_false, fall_through);
3238  SIMD128_TYPES(SIMD128_TYPE)
3239#undef SIMD128_TYPE
3240    // clang-format on
3241  } else {
3242    if (if_false != fall_through) __ jmp(if_false);
3243  }
3244  context()->Plug(if_true, if_false);
3245}
3246
3247
3248void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
3249  Comment cmnt(masm_, "[ CompareOperation");
3250
3251  // First we try a fast inlined version of the compare when one of
3252  // the operands is a literal.
3253  if (TryLiteralCompare(expr)) return;
3254
3255  // Always perform the comparison for its control flow.  Pack the result
3256  // into the expression's context after the comparison is performed.
3257  Label materialize_true, materialize_false;
3258  Label* if_true = NULL;
3259  Label* if_false = NULL;
3260  Label* fall_through = NULL;
3261  context()->PrepareTest(&materialize_true, &materialize_false,
3262                         &if_true, &if_false, &fall_through);
3263
3264  Token::Value op = expr->op();
3265  VisitForStackValue(expr->left());
3266  switch (op) {
3267    case Token::IN:
3268      VisitForStackValue(expr->right());
3269      SetExpressionPosition(expr);
3270      EmitHasProperty();
3271      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
3272      __ cmp(eax, isolate()->factory()->true_value());
3273      Split(equal, if_true, if_false, fall_through);
3274      break;
3275
3276    case Token::INSTANCEOF: {
3277      VisitForAccumulatorValue(expr->right());
3278      SetExpressionPosition(expr);
3279      PopOperand(edx);
3280      __ Call(isolate()->builtins()->InstanceOf(), RelocInfo::CODE_TARGET);
3281      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
3282      __ cmp(eax, isolate()->factory()->true_value());
3283      Split(equal, if_true, if_false, fall_through);
3284      break;
3285    }
3286
3287    default: {
3288      VisitForAccumulatorValue(expr->right());
3289      SetExpressionPosition(expr);
3290      Condition cc = CompareIC::ComputeCondition(op);
3291      PopOperand(edx);
3292
3293      bool inline_smi_code = ShouldInlineSmiCase(op);
3294      JumpPatchSite patch_site(masm_);
3295      if (inline_smi_code) {
3296        Label slow_case;
3297        __ mov(ecx, edx);
3298        __ or_(ecx, eax);
3299        patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
3300        __ cmp(edx, eax);
3301        Split(cc, if_true, if_false, NULL);
3302        __ bind(&slow_case);
3303      }
3304
3305      Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
3306      CallIC(ic, expr->CompareOperationFeedbackId());
3307      patch_site.EmitPatchInfo();
3308
3309      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3310      __ test(eax, eax);
3311      Split(cc, if_true, if_false, fall_through);
3312    }
3313  }
3314
3315  // Convert the result of the comparison into one expected for this
3316  // expression's context.
3317  context()->Plug(if_true, if_false);
3318}
3319
3320
3321void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
3322                                              Expression* sub_expr,
3323                                              NilValue nil) {
3324  Label materialize_true, materialize_false;
3325  Label* if_true = NULL;
3326  Label* if_false = NULL;
3327  Label* fall_through = NULL;
3328  context()->PrepareTest(&materialize_true, &materialize_false,
3329                         &if_true, &if_false, &fall_through);
3330
3331  VisitForAccumulatorValue(sub_expr);
3332  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3333
3334  Handle<Object> nil_value = nil == kNullValue
3335      ? isolate()->factory()->null_value()
3336      : isolate()->factory()->undefined_value();
3337  if (expr->op() == Token::EQ_STRICT) {
3338    __ cmp(eax, nil_value);
3339    Split(equal, if_true, if_false, fall_through);
3340  } else {
3341    __ JumpIfSmi(eax, if_false);
3342    __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
3343    __ test_b(FieldOperand(eax, Map::kBitFieldOffset),
3344              Immediate(1 << Map::kIsUndetectable));
3345    Split(not_zero, if_true, if_false, fall_through);
3346  }
3347  context()->Plug(if_true, if_false);
3348}
3349
3350
3351Register FullCodeGenerator::result_register() {
3352  return eax;
3353}
3354
3355
3356Register FullCodeGenerator::context_register() {
3357  return esi;
3358}
3359
3360void FullCodeGenerator::LoadFromFrameField(int frame_offset, Register value) {
3361  DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
3362  __ mov(value, Operand(ebp, frame_offset));
3363}
3364
3365void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3366  DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
3367  __ mov(Operand(ebp, frame_offset), value);
3368}
3369
3370
3371void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
3372  __ mov(dst, ContextOperand(esi, context_index));
3373}
3374
3375
3376void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
3377  DeclarationScope* closure_scope = scope()->GetClosureScope();
3378  if (closure_scope->is_script_scope() ||
3379      closure_scope->is_module_scope()) {
3380    // Contexts nested in the native context have a canonical empty function
3381    // as their closure, not the anonymous closure containing the global
3382    // code.
3383    __ mov(eax, NativeContextOperand());
3384    PushOperand(ContextOperand(eax, Context::CLOSURE_INDEX));
3385  } else if (closure_scope->is_eval_scope()) {
3386    // Contexts nested inside eval code have the same closure as the context
3387    // calling eval, not the anonymous closure containing the eval code.
3388    // Fetch it from the context.
3389    PushOperand(ContextOperand(esi, Context::CLOSURE_INDEX));
3390  } else {
3391    DCHECK(closure_scope->is_function_scope());
3392    PushOperand(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
3393  }
3394}
3395
3396
3397// ----------------------------------------------------------------------------
3398// Non-local control flow support.
3399
3400void FullCodeGenerator::EnterFinallyBlock() {
3401  // Store pending message while executing finally block.
3402  ExternalReference pending_message_obj =
3403      ExternalReference::address_of_pending_message_obj(isolate());
3404  __ mov(edx, Operand::StaticVariable(pending_message_obj));
3405  PushOperand(edx);
3406
3407  ClearPendingMessage();
3408}
3409
3410
3411void FullCodeGenerator::ExitFinallyBlock() {
3412  DCHECK(!result_register().is(edx));
3413  // Restore pending message from stack.
3414  PopOperand(edx);
3415  ExternalReference pending_message_obj =
3416      ExternalReference::address_of_pending_message_obj(isolate());
3417  __ mov(Operand::StaticVariable(pending_message_obj), edx);
3418}
3419
3420
3421void FullCodeGenerator::ClearPendingMessage() {
3422  DCHECK(!result_register().is(edx));
3423  ExternalReference pending_message_obj =
3424      ExternalReference::address_of_pending_message_obj(isolate());
3425  __ mov(edx, Immediate(isolate()->factory()->the_hole_value()));
3426  __ mov(Operand::StaticVariable(pending_message_obj), edx);
3427}
3428
3429
3430void FullCodeGenerator::DeferredCommands::EmitCommands() {
3431  DCHECK(!result_register().is(edx));
3432  __ Pop(result_register());  // Restore the accumulator.
3433  __ Pop(edx);                // Get the token.
3434  for (DeferredCommand cmd : commands_) {
3435    Label skip;
3436    __ cmp(edx, Immediate(Smi::FromInt(cmd.token)));
3437    __ j(not_equal, &skip);
3438    switch (cmd.command) {
3439      case kReturn:
3440        codegen_->EmitUnwindAndReturn();
3441        break;
3442      case kThrow:
3443        __ Push(result_register());
3444        __ CallRuntime(Runtime::kReThrow);
3445        break;
3446      case kContinue:
3447        codegen_->EmitContinue(cmd.target);
3448        break;
3449      case kBreak:
3450        codegen_->EmitBreak(cmd.target);
3451        break;
3452    }
3453    __ bind(&skip);
3454  }
3455}
3456
3457#undef __
3458
3459
3460static const byte kJnsInstruction = 0x79;
3461static const byte kJnsOffset = 0x11;
3462static const byte kNopByteOne = 0x66;
3463static const byte kNopByteTwo = 0x90;
3464#ifdef DEBUG
3465static const byte kCallInstruction = 0xe8;
3466#endif
3467
3468
3469void BackEdgeTable::PatchAt(Code* unoptimized_code,
3470                            Address pc,
3471                            BackEdgeState target_state,
3472                            Code* replacement_code) {
3473  Address call_target_address = pc - kIntSize;
3474  Address jns_instr_address = call_target_address - 3;
3475  Address jns_offset_address = call_target_address - 2;
3476
3477  switch (target_state) {
3478    case INTERRUPT:
3479      //     sub <profiling_counter>, <delta>  ;; Not changed
3480      //     jns ok
3481      //     call <interrupt stub>
3482      //   ok:
3483      *jns_instr_address = kJnsInstruction;
3484      *jns_offset_address = kJnsOffset;
3485      break;
3486    case ON_STACK_REPLACEMENT:
3487      //     sub <profiling_counter>, <delta>  ;; Not changed
3488      //     nop
3489      //     nop
3490      //     call <on-stack replacment>
3491      //   ok:
3492      *jns_instr_address = kNopByteOne;
3493      *jns_offset_address = kNopByteTwo;
3494      break;
3495  }
3496
3497  Assembler::set_target_address_at(unoptimized_code->GetIsolate(),
3498                                   call_target_address, unoptimized_code,
3499                                   replacement_code->entry());
3500  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
3501      unoptimized_code, call_target_address, replacement_code);
3502}
3503
3504
3505BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
3506    Isolate* isolate,
3507    Code* unoptimized_code,
3508    Address pc) {
3509  Address call_target_address = pc - kIntSize;
3510  Address jns_instr_address = call_target_address - 3;
3511  DCHECK_EQ(kCallInstruction, *(call_target_address - 1));
3512
3513  if (*jns_instr_address == kJnsInstruction) {
3514    DCHECK_EQ(kJnsOffset, *(call_target_address - 2));
3515    DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(),
3516              Assembler::target_address_at(call_target_address,
3517                                           unoptimized_code));
3518    return INTERRUPT;
3519  }
3520
3521  DCHECK_EQ(kNopByteOne, *jns_instr_address);
3522  DCHECK_EQ(kNopByteTwo, *(call_target_address - 2));
3523
3524  DCHECK_EQ(
3525      isolate->builtins()->OnStackReplacement()->entry(),
3526      Assembler::target_address_at(call_target_address, unoptimized_code));
3527  return ON_STACK_REPLACEMENT;
3528}
3529
3530
3531}  // namespace internal
3532}  // namespace v8
3533
3534#endif  // V8_TARGET_ARCH_IA32
3535