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