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