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