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