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