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