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