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