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