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