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