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